diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
commit | 8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch) | |
tree | 4099e8021376c7d8c05bdf8503093d80e9c7bad0 /lib/util | |
parent | Initial commit. (diff) | |
download | samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip |
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/util')
208 files changed, 62062 insertions, 0 deletions
diff --git a/lib/util/Doxyfile b/lib/util/Doxyfile new file mode 100644 index 0000000..02e36a7 --- /dev/null +++ b/lib/util/Doxyfile @@ -0,0 +1,24 @@ +PROJECT_NAME = SAMBA_UTIL +OUTPUT_DIRECTORY = apidocs +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +OPTIMIZE_OUTPUT_FOR_C = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +GENERATE_TODOLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +SHOW_USED_FILES = NO +SHOW_DIRECTORIES = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +INPUT = . +FILE_PATTERNS = *.c *.h *.dox +GENERATE_HTML = YES +HTML_OUTPUT = html +GENERATE_MAN = YES +ALWAYS_DETAILED_SEC = YES +JAVADOC_AUTOBRIEF = YES diff --git a/lib/util/README b/lib/util/README new file mode 100644 index 0000000..fffd44d --- /dev/null +++ b/lib/util/README @@ -0,0 +1,6 @@ +This directory contains libutil (until we can think of a better name) + +The idea is that this library contains simple but useful data structures +and support functions that are generally useful; not just for Samba but for +other projects as well. Functions here should not depend on any external +libraries, just on libc (perhaps partially provided by libreplace). diff --git a/lib/util/access.c b/lib/util/access.c new file mode 100644 index 0000000..fd9912d --- /dev/null +++ b/lib/util/access.c @@ -0,0 +1,377 @@ +/* + This module is an adaption of code from the tcpd-1.4 package written + by Wietse Venema, Eindhoven University of Technology, The Netherlands. + + The code is used here with permission. + + The code has been considerably changed from the original. Bug reports + should be sent to samba-technical@lists.samba.org + + Updated for IPv6 by Jeremy Allison (C) 2007. +*/ + +#include "replace.h" +#include "system/locale.h" +#include "lib/util/debug.h" +#include "../lib/util/memcache.h" +#include "lib/socket/interfaces.h" +#include "lib/util/samba_util.h" +#include "lib/util/util_net.h" +#include "lib/util/samba_util.h" +#include "lib/util/memory.h" +#include "lib/util/access.h" +#include "lib/util/unix_match.h" +#include "lib/util/smb_strtox.h" + +#define NAME_INDEX 0 +#define ADDR_INDEX 1 + +/* masked_match - match address against netnumber/netmask */ +static bool masked_match(const char *tok, const char *slash, const char *s) +{ + struct sockaddr_storage ss_mask; + struct sockaddr_storage ss_tok; + struct sockaddr_storage ss_host; + char *tok_copy = NULL; + + if (!interpret_string_addr(&ss_host, s, 0)) { + return false; + } + + if (*tok == '[') { + /* IPv6 address - remove braces. */ + tok_copy = smb_xstrdup(tok+1); + if (!tok_copy) { + return false; + } + /* Remove the terminating ']' */ + tok_copy[PTR_DIFF(slash,tok)-1] = '\0'; + } else { + tok_copy = smb_xstrdup(tok); + if (!tok_copy) { + return false; + } + /* Remove the terminating '/' */ + tok_copy[PTR_DIFF(slash,tok)] = '\0'; + } + + if (!interpret_string_addr(&ss_tok, tok_copy, 0)) { + SAFE_FREE(tok_copy); + return false; + } + + SAFE_FREE(tok_copy); + + if (strlen(slash + 1) > 2) { + if (!interpret_string_addr(&ss_mask, slash+1, 0)) { + return false; + } + } else { + int error = 0; + unsigned long val; + + val = smb_strtoul(slash+1, + NULL, + 0, + &error, + SMB_STR_FULL_STR_CONV); + if (error != 0) { + return false; + } + if (!make_netmask(&ss_mask, &ss_tok, val)) { + return false; + } + } + + return same_net((struct sockaddr *)(void *)&ss_host, + (struct sockaddr *)(void *)&ss_tok, + (struct sockaddr *)(void *)&ss_mask); +} + +/* string_match - match string s against token tok */ +static bool string_match(const char *tok,const char *s) +{ + size_t tok_len; + size_t str_len; + const char *cut; + + /* Return true if a token has the magic value "ALL". Return + * true if the token is "FAIL". If the token starts with a "." + * (domain name), return true if it matches the last fields of + * the string. If the token has the magic value "LOCAL", + * return true if the string does not contain a "." + * character. If the token ends on a "." (network number), + * return true if it matches the first fields of the + * string. If the token begins with a "@" (netgroup name), + * return true if the string is a (host) member of the + * netgroup. Return true if the token fully matches the + * string. If the token is a netnumber/netmask pair, return + * true if the address is a member of the specified subnet. + */ + + if (tok[0] == '.') { /* domain: match last fields */ + if ((str_len = strlen(s)) > (tok_len = strlen(tok)) + && strequal_m(tok, s + str_len - tok_len)) { + return true; + } + } else if (tok[0] == '@') { /* netgroup: look it up */ +#if defined(HAVE_NETGROUP) && defined(HAVE_INNETGR) + DATA_BLOB tmp; + char *mydomain = NULL; + char *hostname = NULL; + bool netgroup_ok = false; + char nis_domain_buf[256]; + + if (memcache_lookup( + NULL, SINGLETON_CACHE, + data_blob_string_const_null("yp_default_domain"), + &tmp)) { + + SMB_ASSERT(tmp.length > 0); + mydomain = (tmp.data[0] == '\0') + ? NULL : (char *)tmp.data; + } else { + if (getdomainname(nis_domain_buf, + sizeof(nis_domain_buf)) == 0) { + mydomain = &nis_domain_buf[0]; + memcache_add(NULL, + SINGLETON_CACHE, + data_blob_string_const_null( + "yp_default_domain"), + data_blob_string_const_null( + mydomain)); + } else { + mydomain = NULL; + } + } + + if (!mydomain) { + DEBUG(0,("Unable to get default yp domain. " + "Try without it.\n")); + } + if (!(hostname = smb_xstrdup(s))) { + DEBUG(1,("out of memory for strdup!\n")); + return false; + } + + netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain); + + DBG_INFO("%s %s of domain %s in netgroup %s\n", + netgroup_ok ? "Found" : "Could not find", + hostname, + mydomain?mydomain:"(ANY)", + tok+1); + + SAFE_FREE(hostname); + + if (netgroup_ok) + return true; +#else + DEBUG(0,("access: netgroup support is not configured\n")); + return false; +#endif + } else if (strequal_m(tok, "ALL")) { /* all: match any */ + return true; + } else if (strequal_m(tok, "FAIL")) { /* fail: match any */ + return true; + } else if (strequal_m(tok, "LOCAL")) { /* local: no dots */ + if (strchr_m(s, '.') == 0 && !strequal_m(s, "unknown")) { + return true; + } + } else if (strequal_m(tok, s)) { /* match host name or address */ + return true; + } else if (tok[(tok_len = strlen(tok)) - 1] == '.') { /* network */ + if (strncmp(tok, s, tok_len) == 0) { + return true; + } + } else if ((cut = strchr_m(tok, '/')) != 0) { /* netnumber/netmask */ + if ((isdigit(s[0]) && strchr_m(tok, '.') != NULL) || + (tok[0] == '[' && cut > tok && cut[-1] == ']') || + ((isxdigit(s[0]) || s[0] == ':') && + strchr_m(tok, ':') != NULL)) { + /* IPv4/netmask or + * [IPv6:addr]/netmask or IPv6:addr/netmask */ + return masked_match(tok, cut, s); + } + } else if (strchr_m(tok, '*') != 0 || strchr_m(tok, '?')) { + return unix_wild_match(tok, s); + } + return false; +} + +/* client_match - match host name and address against token */ +bool client_match(const char *tok, const void *item) +{ + const char **client = discard_const_p(const char *, item); + const char *tok_addr = tok; + const char *cli_addr = client[ADDR_INDEX]; + + /* + * tok and client[ADDR_INDEX] can be an IPv4 mapped to IPv6, + * we try and match the IPv4 part of address only. + * Bug #5311 and #7383. + */ + + if (strncasecmp_m(tok_addr, "::ffff:", 7) == 0) { + tok_addr += 7; + } + + if (strncasecmp_m(cli_addr, "::ffff:", 7) == 0) { + cli_addr += 7; + } + + /* + * Try to match the address first. If that fails, try to match the host + * name if available. + */ + + if (string_match(tok_addr, cli_addr)) { + return true; + } + + if (client[NAME_INDEX][0] != 0) { + if (string_match(tok, client[NAME_INDEX])) { + return true; + } + } + + return false; +} + +/* list_match - match an item against a list of tokens with exceptions */ +bool list_match(const char **list,const void *item, + bool (*match_fn)(const char *, const void *)) +{ + bool match = false; + + if (!list) { + return false; + } + + /* + * Process tokens one at a time. We have exhausted all possible matches + * when we reach an "EXCEPT" token or the end of the list. If we do find + * a match, look for an "EXCEPT" list and recurse to determine whether + * the match is affected by any exceptions. + */ + + for (; *list ; list++) { + if (strequal_m(*list, "EXCEPT")) { + /* EXCEPT: give up */ + break; + } + if ((match = (*match_fn) (*list, item))) { + /* true or FAIL */ + break; + } + } + /* Process exceptions to true or FAIL matches. */ + + if (match != false) { + while (*list && !strequal_m(*list, "EXCEPT")) { + list++; + } + + for (; *list; list++) { + if ((*match_fn) (*list, item)) { + /* Exception Found */ + return false; + } + } + } + + return match; +} + +/* return true if access should be allowed */ +static bool allow_access_internal(const char **deny_list, + const char **allow_list, + const char *cname, + const char *caddr) +{ + const char *client[2]; + + client[NAME_INDEX] = cname; + client[ADDR_INDEX] = caddr; + + /* if it is loopback then always allow unless specifically denied */ + if (strcmp(caddr, "127.0.0.1") == 0 || strcmp(caddr, "::1") == 0) { + /* + * If 127.0.0.1 matches both allow and deny then allow. + * Patch from Steve Langasek vorlon@netexpress.net. + */ + if (deny_list && + list_match(deny_list,client,client_match) && + (!allow_list || + !list_match(allow_list,client, client_match))) { + return false; + } + return true; + } + + /* if there's no deny list and no allow list then allow access */ + if ((!deny_list || *deny_list == 0) && + (!allow_list || *allow_list == 0)) { + return true; + } + + /* if there is an allow list but no deny list then allow only hosts + on the allow list */ + if (!deny_list || *deny_list == 0) { + return(list_match(allow_list,client,client_match)); + } + + /* if there's a deny list but no allow list then allow + all hosts not on the deny list */ + if (!allow_list || *allow_list == 0) { + return(!list_match(deny_list,client,client_match)); + } + + /* if there are both types of list then allow all hosts on the + allow list */ + if (list_match(allow_list,(const char *)client,client_match)) { + return true; + } + + /* if there are both types of list and it's not on the allow then + allow it if its not on the deny */ + if (list_match(deny_list,(const char *)client,client_match)) { + return false; + } + + return true; +} + +/* return true if access should be allowed - doesn't print log message */ +bool allow_access_nolog(const char **deny_list, + const char **allow_list, + const char *cname, + const char *caddr) +{ + bool ret; + char *nc_cname = smb_xstrdup(cname); + char *nc_caddr = smb_xstrdup(caddr); + + ret = allow_access_internal(deny_list, allow_list, nc_cname, nc_caddr); + + SAFE_FREE(nc_cname); + SAFE_FREE(nc_caddr); + return ret; +} + +/* return true if access should be allowed - prints log message */ +bool allow_access(const char **deny_list, + const char **allow_list, + const char *cname, + const char *caddr) +{ + bool ret; + + ret = allow_access_nolog(deny_list, allow_list, cname, caddr); + + DEBUG(ret ? 3 : 0, + ("%s connection from %s (%s)\n", + ret ? "Allowed" : "Denied", cname, caddr)); + + return ret; +} diff --git a/lib/util/access.h b/lib/util/access.h new file mode 100644 index 0000000..73f71b6 --- /dev/null +++ b/lib/util/access.h @@ -0,0 +1,28 @@ +/* + This module is an adaption of code from the tcpd-1.4 package written + by Wietse Venema, Eindhoven University of Technology, The Netherlands. + + The code is used here with permission. + + The code has been considerably changed from the original. Bug reports + should be sent to samba-technical@lists.samba.org + + Updated for IPv6 by Jeremy Allison (C) 2007. +*/ + +#ifndef _UTIL_ACCESS_H_ +#define _UTIL_ACCESS_H_ + +bool client_match(const char *tok, const void *item); +bool list_match(const char **list,const void *item, + bool (*match_fn)(const char *, const void *)); +bool allow_access_nolog(const char **deny_list, + const char **allow_list, + const char *cname, + const char *caddr); +bool allow_access(const char **deny_list, + const char **allow_list, + const char *cname, + const char *caddr); + +#endif diff --git a/lib/util/asn1.c b/lib/util/asn1.c new file mode 100644 index 0000000..1a92a55 --- /dev/null +++ b/lib/util/asn1.c @@ -0,0 +1,1176 @@ +/* + Unix SMB/CIFS implementation. + simple ASN1 routines + Copyright (C) Andrew Tridgell 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/locale.h" +#include "lib/util/asn1.h" +#include "lib/util/debug.h" +#include "lib/util/samba_util.h" +#include "lib/util/smb_strtox.h" + +struct nesting { + off_t start; + size_t taglen; /* for parsing */ + struct nesting *next; +}; + + +struct asn1_data { + uint8_t *data; + size_t length; + off_t ofs; + struct nesting *nesting; + bool has_error; + unsigned depth; + unsigned max_depth; +}; + +/* allocate an asn1 structure */ +struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx, unsigned max_depth) +{ + struct asn1_data *ret = talloc_zero(mem_ctx, struct asn1_data); + if (ret == NULL) { + DBG_ERR("asn1_init failed! out of memory\n"); + return ret; + } + ret->max_depth = max_depth; + return ret; +} + +/* free an asn1 structure */ +void asn1_free(struct asn1_data *data) +{ + talloc_free(data); +} + +bool asn1_has_error(const struct asn1_data *data) +{ + return data->has_error; +} + +void asn1_set_error(struct asn1_data *data) +{ + data->has_error = true; +} + +bool asn1_has_nesting(const struct asn1_data *data) +{ + return data->nesting != NULL; +} + +off_t asn1_current_ofs(const struct asn1_data *data) +{ + return data->ofs; +} + +/* write to the ASN1 buffer, advancing the buffer pointer */ +bool asn1_write(struct asn1_data *data, const void *p, int len) +{ + if (data->has_error) return false; + + if ((len < 0) || (data->ofs + (size_t)len < data->ofs)) { + data->has_error = true; + return false; + } + + if (data->length < data->ofs+len) { + uint8_t *newp; + newp = talloc_realloc(data, data->data, uint8_t, data->ofs+len); + if (!newp) { + data->has_error = true; + return false; + } + data->data = newp; + data->length = data->ofs+len; + } + if (len > 0) { + memcpy(data->data + data->ofs, p, len); + data->ofs += len; + } + return true; +} + +/* useful fn for writing a uint8_t */ +bool asn1_write_uint8(struct asn1_data *data, uint8_t v) +{ + return asn1_write(data, &v, 1); +} + +/* push a tag onto the asn1 data buffer. Used for nested structures */ +bool asn1_push_tag(struct asn1_data *data, uint8_t tag) +{ + struct nesting *nesting; + + if (!asn1_write_uint8(data, tag)) { + return false; + } + nesting = talloc(data, struct nesting); + if (!nesting) { + data->has_error = true; + return false; + } + + nesting->start = data->ofs; + nesting->next = data->nesting; + data->nesting = nesting; + return asn1_write_uint8(data, 0xff); +} + +/* pop a tag */ +bool asn1_pop_tag(struct asn1_data *data) +{ + struct nesting *nesting; + size_t len; + + if (data->has_error) { + return false; + } + + nesting = data->nesting; + + if (!nesting) { + data->has_error = true; + return false; + } + len = data->ofs - (nesting->start+1); + /* yes, this is ugly. We don't know in advance how many bytes the length + of a tag will take, so we assumed 1 byte. If we were wrong then we + need to correct our mistake */ + if (len > 0xFFFFFF) { + data->data[nesting->start] = 0x84; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + memmove(data->data+nesting->start+5, data->data+nesting->start+1, len); + data->data[nesting->start+1] = (len>>24) & 0xFF; + data->data[nesting->start+2] = (len>>16) & 0xFF; + data->data[nesting->start+3] = (len>>8) & 0xFF; + data->data[nesting->start+4] = len&0xff; + } else if (len > 0xFFFF) { + data->data[nesting->start] = 0x83; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + memmove(data->data+nesting->start+4, data->data+nesting->start+1, len); + data->data[nesting->start+1] = (len>>16) & 0xFF; + data->data[nesting->start+2] = (len>>8) & 0xFF; + data->data[nesting->start+3] = len&0xff; + } else if (len > 255) { + data->data[nesting->start] = 0x82; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + memmove(data->data+nesting->start+3, data->data+nesting->start+1, len); + data->data[nesting->start+1] = len>>8; + data->data[nesting->start+2] = len&0xff; + } else if (len > 127) { + data->data[nesting->start] = 0x81; + if (!asn1_write_uint8(data, 0)) return false; + memmove(data->data+nesting->start+2, data->data+nesting->start+1, len); + data->data[nesting->start+1] = len; + } else { + data->data[nesting->start] = len; + } + + data->nesting = nesting->next; + talloc_free(nesting); + return true; +} + +/* "i" is the one's complement representation, as is the normal result of an + * implicit signed->unsigned conversion */ + +static bool push_int_bigendian(struct asn1_data *data, unsigned int i, bool negative) +{ + uint8_t lowest = i & 0xFF; + + i = i >> 8; + if (i != 0) + if (!push_int_bigendian(data, i, negative)) + return false; + + if (data->nesting->start+1 == data->ofs) { + + /* We did not write anything yet, looking at the highest + * valued byte */ + + if (negative) { + /* Don't write leading 0xff's */ + if (lowest == 0xFF) + return true; + + if ((lowest & 0x80) == 0) { + /* The only exception for a leading 0xff is if + * the highest bit is 0, which would indicate + * a positive value */ + if (!asn1_write_uint8(data, 0xff)) + return false; + } + } else { + if (lowest & 0x80) { + /* The highest bit of a positive integer is 1, + * this would indicate a negative number. Push + * a 0 to indicate a positive one */ + if (!asn1_write_uint8(data, 0)) + return false; + } + } + } + + return asn1_write_uint8(data, lowest); +} + +/* write an Integer without the tag framing. Needed for example for the LDAP + * Abandon Operation */ + +bool asn1_write_implicit_Integer(struct asn1_data *data, int i) +{ + if (data->has_error) { + return false; + } + + if (i == -1) { + /* -1 is special as it consists of all-0xff bytes. In + push_int_bigendian this is the only case that is not + properly handled, as all 0xff bytes would be handled as + leading ones to be ignored. */ + return asn1_write_uint8(data, 0xff); + } else { + return push_int_bigendian(data, i, i<0); + } +} + + +/* write an integer */ +bool asn1_write_Integer(struct asn1_data *data, int i) +{ + if (!asn1_push_tag(data, ASN1_INTEGER)) return false; + if (!asn1_write_implicit_Integer(data, i)) return false; + return asn1_pop_tag(data); +} + +/* write a BIT STRING */ +bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, uint8_t padding) +{ + if (!asn1_push_tag(data, ASN1_BIT_STRING)) return false; + if (!asn1_write_uint8(data, padding)) return false; + if (!asn1_write(data, p, length)) return false; + return asn1_pop_tag(data); +} + +bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID) +{ + unsigned int v, v2; + const char *p = (const char *)OID; + char *newp; + int i; + int error = 0; + + if (!isdigit(*p)) return false; + v = smb_strtoul(p, &newp, 10, &error, SMB_STR_STANDARD); + if (newp[0] != '.' || error != 0) { + return false; + } + p = newp + 1; + + if (!isdigit(*p)) return false; + v2 = smb_strtoul(p, &newp, 10, &error, SMB_STR_STANDARD); + if (newp[0] != '.' || error != 0) { + return false; + } + p = newp + 1; + + /*the ber representation can't use more space than the string one */ + *blob = data_blob_talloc(mem_ctx, NULL, strlen(OID)); + if (!blob->data) return false; + + blob->data[0] = 40*v + v2; + + i = 1; + while (*p) { + if (!isdigit(*p)) return false; + v = smb_strtoul(p, &newp, 10, &error, SMB_STR_STANDARD); + if (newp[0] == '.' || error != 0) { + p = newp + 1; + /* check for empty last component */ + if (!*p) return false; + } else if (newp[0] == '\0') { + p = newp; + } else { + data_blob_free(blob); + return false; + } + if (v >= (1<<28)) blob->data[i++] = (0x80 | ((v>>28)&0x7f)); + if (v >= (1<<21)) blob->data[i++] = (0x80 | ((v>>21)&0x7f)); + if (v >= (1<<14)) blob->data[i++] = (0x80 | ((v>>14)&0x7f)); + if (v >= (1<<7)) blob->data[i++] = (0x80 | ((v>>7)&0x7f)); + blob->data[i++] = (v&0x7f); + } + + blob->length = i; + + return true; +} + +/** + * Serialize partial OID string. + * Partial OIDs are in the form: + * 1:2.5.6:0x81 + * 1:2.5.6:0x8182 + */ +bool ber_write_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *partial_oid) +{ + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + char *oid = talloc_strdup(tmp_ctx, partial_oid); + char *p; + + /* truncate partial part so ber_write_OID_String() works */ + p = strchr(oid, ':'); + if (p) { + *p = '\0'; + p++; + } + + if (!ber_write_OID_String(mem_ctx, blob, oid)) { + talloc_free(tmp_ctx); + return false; + } + + /* Add partially encoded sub-identifier */ + if (p) { + DATA_BLOB tmp_blob = strhex_to_data_blob(tmp_ctx, p); + if (!data_blob_append(mem_ctx, blob, tmp_blob.data, + tmp_blob.length)) { + talloc_free(tmp_ctx); + return false; + } + } + + talloc_free(tmp_ctx); + + return true; +} + +/* write an object ID to a ASN1 buffer */ +bool asn1_write_OID(struct asn1_data *data, const char *OID) +{ + DATA_BLOB blob; + + if (!asn1_push_tag(data, ASN1_OID)) return false; + + if (!ber_write_OID_String(NULL, &blob, OID)) { + data->has_error = true; + return false; + } + + if (!asn1_write(data, blob.data, blob.length)) { + data_blob_free(&blob); + data->has_error = true; + return false; + } + data_blob_free(&blob); + return asn1_pop_tag(data); +} + +/* write an octet string */ +bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length) +{ + if (!asn1_push_tag(data, ASN1_OCTET_STRING)) return false; + if (!asn1_write(data, p, length)) return false; + return asn1_pop_tag(data); +} + +/* write a LDAP string */ +bool asn1_write_LDAPString(struct asn1_data *data, const char *s) +{ + return asn1_write(data, s, strlen(s)); +} + +/* write a LDAP string from a DATA_BLOB */ +bool asn1_write_DATA_BLOB_LDAPString(struct asn1_data *data, const DATA_BLOB *s) +{ + return asn1_write(data, s->data, s->length); +} + +/* write a general string */ +bool asn1_write_GeneralString(struct asn1_data *data, const char *s) +{ + if (!asn1_push_tag(data, ASN1_GENERAL_STRING)) return false; + if (!asn1_write_LDAPString(data, s)) return false; + return asn1_pop_tag(data); +} + +bool asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob) +{ + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false; + if (!asn1_write(data, blob->data, blob->length)) return false; + return asn1_pop_tag(data); +} + +/* write a BOOLEAN */ +bool asn1_write_BOOLEAN(struct asn1_data *data, bool v) +{ + if (!asn1_push_tag(data, ASN1_BOOLEAN)) return false; + if (!asn1_write_uint8(data, v ? 0xFF : 0)) return false; + return asn1_pop_tag(data); +} + +bool asn1_read_BOOLEAN(struct asn1_data *data, bool *v) +{ + uint8_t tmp = 0; + if (!asn1_start_tag(data, ASN1_BOOLEAN)) return false; + *v = false; + if (!asn1_read_uint8(data, &tmp)) return false; + if (tmp == 0xFF) { + *v = true; + } + return asn1_end_tag(data); +} + +/* write a BOOLEAN in a simple context */ +bool asn1_write_BOOLEAN_context(struct asn1_data *data, bool v, int context) +{ + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(context))) return false; + if (!asn1_write_uint8(data, v ? 0xFF : 0)) return false; + return asn1_pop_tag(data); +} + +bool asn1_read_BOOLEAN_context(struct asn1_data *data, bool *v, int context) +{ + uint8_t tmp = 0; + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(context))) return false; + *v = false; + if (!asn1_read_uint8(data, &tmp)) return false; + if (tmp == 0xFF) { + *v = true; + } + return asn1_end_tag(data); +} + +/* check a BOOLEAN */ +bool asn1_check_BOOLEAN(struct asn1_data *data, bool v) +{ + uint8_t b = 0; + + if (!asn1_read_uint8(data, &b)) return false; + if (b != ASN1_BOOLEAN) { + data->has_error = true; + return false; + } + if (!asn1_read_uint8(data, &b)) return false; + if (b != v) { + data->has_error = true; + return false; + } + return !data->has_error; +} + + +/* load a struct asn1_data structure with a lump of data, ready to be parsed */ +bool asn1_load(struct asn1_data *data, DATA_BLOB blob) +{ + /* + * Save the maximum depth + */ + unsigned max_depth = data->max_depth; + + ZERO_STRUCTP(data); + data->data = (uint8_t *)talloc_memdup(data, blob.data, blob.length); + if (!data->data) { + data->has_error = true; + return false; + } + data->length = blob.length; + data->max_depth = max_depth; + return true; +} + +/* Peek into an ASN1 buffer, not advancing the pointer */ +bool asn1_peek(struct asn1_data *data, void *p, int len) +{ + if (data->has_error) + return false; + + if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len) + return false; + + if (data->ofs + len > data->length) { + /* we need to mark the buffer as consumed, so the caller knows + this was an out of data error, and not a decode error */ + data->ofs = data->length; + return false; + } + + memcpy(p, data->data + data->ofs, len); + return true; +} + +/* read from a ASN1 buffer, advancing the buffer pointer */ +bool asn1_read(struct asn1_data *data, void *p, int len) +{ + if (!asn1_peek(data, p, len)) { + data->has_error = true; + return false; + } + + data->ofs += len; + return true; +} + +/* read a uint8_t from a ASN1 buffer */ +bool asn1_read_uint8(struct asn1_data *data, uint8_t *v) +{ + return asn1_read(data, v, 1); +} + +bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v) +{ + return asn1_peek(data, v, 1); +} + +bool asn1_peek_tag(struct asn1_data *data, uint8_t tag) +{ + uint8_t b; + + if (asn1_tag_remaining(data) <= 0) { + return false; + } + + if (!asn1_peek_uint8(data, &b)) + return false; + + return (b == tag); +} + +/* + * just get the needed size the tag would consume + */ +static bool asn1_peek_tag_needed_size(struct asn1_data *data, uint8_t tag, + size_t *size) +{ + off_t start_ofs = data->ofs; + uint8_t b; + size_t taglen = 0; + + if (data->has_error) { + return false; + } + + if (!asn1_read_uint8(data, &b)) { + data->ofs = start_ofs; + data->has_error = false; + return false; + } + + if (b != tag) { + data->ofs = start_ofs; + data->has_error = false; + return false; + } + + if (!asn1_read_uint8(data, &b)) { + data->ofs = start_ofs; + data->has_error = false; + return false; + } + + if (b & 0x80) { + int n = b & 0x7f; + if (!asn1_read_uint8(data, &b)) { + data->ofs = start_ofs; + data->has_error = false; + return false; + } + if (n > 4) { + /* + * We should not allow more than 4 bytes + * for the encoding of the tag length. + * + * Otherwise we'd overflow the taglen + * variable on 32 bit systems. + */ + data->ofs = start_ofs; + data->has_error = false; + return false; + } + taglen = b; + while (n > 1) { + size_t tmp_taglen; + + if (!asn1_read_uint8(data, &b)) { + data->ofs = start_ofs; + data->has_error = false; + return false; + } + + tmp_taglen = (taglen << 8) | b; + + if ((tmp_taglen >> 8) != taglen) { + /* overflow */ + data->ofs = start_ofs; + data->has_error = false; + return false; + } + taglen = tmp_taglen; + + n--; + } + } else { + taglen = b; + } + + *size = (data->ofs - start_ofs) + taglen; + + data->ofs = start_ofs; + data->has_error = false; + return true; +} + +/* start reading a nested asn1 structure */ +bool asn1_start_tag(struct asn1_data *data, uint8_t tag) +{ + uint8_t b; + struct nesting *nesting; + + /* + * Check the depth of the parse tree and prevent it from growing + * too large. + */ + data->depth++; + if (data->depth > data->max_depth) { + data->has_error = true; + return false; + } + + if (!asn1_read_uint8(data, &b)) + return false; + + if (b != tag) { + data->has_error = true; + return false; + } + nesting = talloc(data, struct nesting); + if (!nesting) { + data->has_error = true; + return false; + } + + if (!asn1_read_uint8(data, &b)) { + return false; + } + + if (b & 0x80) { + int n = b & 0x7f; + if (!asn1_read_uint8(data, &b)) + return false; + nesting->taglen = b; + while (n > 1) { + size_t taglen; + + if (!asn1_read_uint8(data, &b)) + return false; + + taglen = (nesting->taglen << 8) | b; + + if ((taglen >> 8) != nesting->taglen) { + /* overflow */ + data->has_error = true; + return false; + } + nesting->taglen = taglen; + + n--; + } + } else { + nesting->taglen = b; + } + nesting->start = data->ofs; + nesting->next = data->nesting; + data->nesting = nesting; + if (asn1_tag_remaining(data) == -1) { + return false; + } + return !data->has_error; +} + +/* stop reading a tag */ +bool asn1_end_tag(struct asn1_data *data) +{ + struct nesting *nesting; + + if (data->depth == 0) { + smb_panic("Unbalanced ASN.1 Tag nesting"); + } + data->depth--; + /* make sure we read it all */ + if (asn1_tag_remaining(data) != 0) { + data->has_error = true; + return false; + } + + nesting = data->nesting; + + if (!nesting) { + data->has_error = true; + return false; + } + + data->nesting = nesting->next; + talloc_free(nesting); + return true; +} + +/* work out how many bytes are left in this nested tag */ +int asn1_tag_remaining(struct asn1_data *data) +{ + int remaining; + if (data->has_error) { + return -1; + } + + if (!data->nesting) { + data->has_error = true; + return -1; + } + remaining = data->nesting->taglen - (data->ofs - data->nesting->start); + if (remaining > (data->length - data->ofs)) { + data->has_error = true; + return -1; + } + if (remaining < 0) { + data->has_error = true; + return -1; + } + return remaining; +} + +/** + * Internal implementation for reading binary OIDs + * Reading is done as far in the buffer as valid OID + * till buffer ends or not valid sub-identifier is found. + */ +static bool _ber_read_OID_String_impl(TALLOC_CTX *mem_ctx, DATA_BLOB blob, + char **OID, size_t *bytes_eaten) +{ + int i; + uint8_t *b; + unsigned int v; + char *tmp_oid = NULL; + + if (blob.length < 2) return false; + + b = blob.data; + + tmp_oid = talloc_asprintf(mem_ctx, "%u.%u", b[0]/40, b[0]%40); + if (!tmp_oid) goto nomem; + + if (bytes_eaten != NULL) { + *bytes_eaten = 0; + } + + for(i = 1, v = 0; i < blob.length; i++) { + v = (v<<7) | (b[i]&0x7f); + if ( ! (b[i] & 0x80)) { + tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", v); + v = 0; + if (bytes_eaten) + *bytes_eaten = i+1; + } + if (!tmp_oid) goto nomem; + } + + *OID = tmp_oid; + return true; + +nomem: + return false; +} + +/* read an object ID from a data blob */ +bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, char **OID) +{ + size_t bytes_eaten; + + if (!_ber_read_OID_String_impl(mem_ctx, blob, OID, &bytes_eaten)) + return false; + + return (bytes_eaten == blob.length); +} + +/** + * Deserialize partial OID string. + * Partial OIDs are in the form: + * 1:2.5.6:0x81 + * 1:2.5.6:0x8182 + */ +bool ber_read_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, + char **partial_oid) +{ + size_t bytes_left; + size_t bytes_eaten; + char *identifier = NULL; + char *tmp_oid = NULL; + + if (!_ber_read_OID_String_impl(mem_ctx, blob, &tmp_oid, &bytes_eaten)) + return false; + + if (bytes_eaten < blob.length) { + bytes_left = blob.length - bytes_eaten; + identifier = hex_encode_talloc(mem_ctx, &blob.data[bytes_eaten], bytes_left); + if (!identifier) goto nomem; + + *partial_oid = talloc_asprintf_append_buffer(tmp_oid, ":0x%s", identifier); + if (!*partial_oid) goto nomem; + TALLOC_FREE(identifier); + } else { + *partial_oid = tmp_oid; + } + + return true; + +nomem: + TALLOC_FREE(identifier); + TALLOC_FREE(tmp_oid); + return false; +} + +/* read an object ID from a ASN1 buffer */ +bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **OID) +{ + DATA_BLOB blob; + int len; + + if (!asn1_start_tag(data, ASN1_OID)) return false; + + len = asn1_tag_remaining(data); + if (len < 0) { + data->has_error = true; + return false; + } + + blob = data_blob(NULL, len); + if (!blob.data) { + data->has_error = true; + return false; + } + + if (!asn1_read(data, blob.data, len)) return false; + if (!asn1_end_tag(data)) { + data_blob_free(&blob); + return false; + } + + if (!ber_read_OID_String(mem_ctx, blob, OID)) { + data->has_error = true; + data_blob_free(&blob); + return false; + } + + data_blob_free(&blob); + return true; +} + +/* check that the next object ID is correct */ +bool asn1_check_OID(struct asn1_data *data, const char *OID) +{ + char *id; + + if (!asn1_read_OID(data, data, &id)) return false; + + if (strcmp(id, OID) != 0) { + talloc_free(id); + data->has_error = true; + return false; + } + talloc_free(id); + return true; +} + +/* read a LDAPString from a ASN1 buffer */ +bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s) +{ + int len; + len = asn1_tag_remaining(data); + if (len < 0) { + data->has_error = true; + return false; + } + *s = talloc_array(mem_ctx, char, len+1); + if (! *s) { + data->has_error = true; + return false; + } + (*s)[len] = 0; + return asn1_read(data, *s, len); +} + + +/* read a GeneralString from a ASN1 buffer */ +bool asn1_read_GeneralString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s) +{ + if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return false; + if (!asn1_read_LDAPString(data, mem_ctx, s)) return false; + return asn1_end_tag(data); +} + + +/* read a octet string blob */ +bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob) +{ + int len; + ZERO_STRUCTP(blob); + if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return false; + len = asn1_tag_remaining(data); + if (len < 0) { + data->has_error = true; + return false; + } + *blob = data_blob_talloc(mem_ctx, NULL, len+1); + if (!blob->data || blob->length < len) { + data->has_error = true; + return false; + } + if (!asn1_read(data, blob->data, len)) goto err; + if (!asn1_end_tag(data)) goto err; + blob->length--; + blob->data[len] = 0; + return true; + + err: + + data_blob_free(blob); + *blob = data_blob_null; + return false; +} + +bool asn1_read_ContextSimple(struct asn1_data *data, TALLOC_CTX *mem_ctx, uint8_t num, + DATA_BLOB *blob) +{ + int len; + ZERO_STRUCTP(blob); + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false; + len = asn1_tag_remaining(data); + if (len < 0) { + data->has_error = true; + return false; + } + *blob = data_blob_talloc(mem_ctx, NULL, len + 1); + if ((len != 0) && (!blob->data)) { + data->has_error = true; + return false; + } + if (!asn1_read(data, blob->data, len)) return false; + blob->length--; + blob->data[len] = 0; + return asn1_end_tag(data); +} + +/* read an integer without tag*/ +bool asn1_read_implicit_Integer(struct asn1_data *data, int *i) +{ + uint8_t b; + uint32_t x = 0; + bool first_byte = true; + + *i = 0; + + while (!data->has_error && asn1_tag_remaining(data)>0) { + if (!asn1_read_uint8(data, &b)) return false; + if (first_byte) { + if (b & 0x80) { + /* Number is negative. */ + x = (uint32_t)-1; + } + first_byte = false; + } + x = (x << 8) + b; + } + *i = (int)x; + + return !data->has_error; +} + +/* read an integer */ +bool asn1_read_Integer(struct asn1_data *data, int *i) +{ + *i = 0; + + if (!asn1_start_tag(data, ASN1_INTEGER)) return false; + if (!asn1_read_implicit_Integer(data, i)) return false; + return asn1_end_tag(data); +} + +/* read a BIT STRING */ +bool asn1_read_BitString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob, uint8_t *padding) +{ + int len; + ZERO_STRUCTP(blob); + if (!asn1_start_tag(data, ASN1_BIT_STRING)) return false; + len = asn1_tag_remaining(data); + if (len < 0) { + data->has_error = true; + return false; + } + if (!asn1_read_uint8(data, padding)) return false; + + *blob = data_blob_talloc(mem_ctx, NULL, len+1); + if (!blob->data || blob->length < len) { + data->has_error = true; + return false; + } + if (asn1_read(data, blob->data, len - 1)) { + blob->length--; + blob->data[len] = 0; + asn1_end_tag(data); + } + + if (data->has_error) { + data_blob_free(blob); + *blob = data_blob_null; + *padding = 0; + return false; + } + return true; +} + +/* read a non-negative enumerated value */ +bool asn1_read_enumerated(struct asn1_data *data, int *v) +{ + unsigned int val_will_wrap = (0xFFU << ((sizeof(int)*8)-8)); + *v = 0; + + if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false; + while (!data->has_error && asn1_tag_remaining(data)>0) { + uint8_t b; + if (!asn1_read_uint8(data, &b)) { + return false; + } + if (*v & val_will_wrap) { + /* + * There is something already in + * the top byte of the int. If we + * shift left by 8 it's going to + * wrap. Prevent this. + */ + data->has_error = true; + return false; + } + /* + * To please/fool the Undefined Behaviour Sanitizer we cast to + * unsigned for the left shift. + */ + *v = ((unsigned int)*v << 8) + b; + if (*v < 0) { + /* ASN1_ENUMERATED can't be -ve. */ + data->has_error = true; + return false; + } + } + return asn1_end_tag(data); +} + +/* write an enumerated value to the stream */ +bool asn1_write_enumerated(struct asn1_data *data, uint8_t v) +{ + if (!asn1_push_tag(data, ASN1_ENUMERATED)) return false; + if (!asn1_write_uint8(data, v)) return false; + return asn1_pop_tag(data); +} + +/* + Get us the data just written without copying +*/ +bool asn1_blob(const struct asn1_data *asn1, DATA_BLOB *blob) +{ + if (asn1->has_error) { + return false; + } + if (asn1->nesting != NULL) { + return false; + } + blob->data = asn1->data; + blob->length = asn1->length; + return true; +} + +bool asn1_extract_blob(struct asn1_data *asn1, TALLOC_CTX *mem_ctx, + DATA_BLOB *pblob) +{ + DATA_BLOB blob; + + if (!asn1_blob(asn1, &blob)) { + return false; + } + + *pblob = (DATA_BLOB) { .length = blob.length }; + pblob->data = talloc_move(mem_ctx, &blob.data); + + /* + * Stop access from here on + */ + asn1->has_error = true; + + return true; +} + +/* + Fill in an asn1 struct without making a copy +*/ +void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len) +{ + /* + * Save max_depth + */ + unsigned max_depth = data->max_depth; + ZERO_STRUCTP(data); + data->data = buf; + data->length = len; + data->max_depth = max_depth; +} + +int asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size) +{ + struct asn1_data asn1; + size_t size; + bool ok; + + ZERO_STRUCT(asn1); + asn1.data = blob.data; + asn1.length = blob.length; + + ok = asn1_peek_tag_needed_size(&asn1, tag, &size); + if (!ok) { + return EMSGSIZE; + } + + if (size > blob.length) { + *packet_size = size; + return EAGAIN; + } + + *packet_size = size; + return 0; +} + +/* + * Get the length of the ASN.1 data + */ +size_t asn1_get_length(const struct asn1_data *asn1) { + return asn1->length; +} diff --git a/lib/util/asn1.h b/lib/util/asn1.h new file mode 100644 index 0000000..9043c34 --- /dev/null +++ b/lib/util/asn1.h @@ -0,0 +1,110 @@ +/* + Unix SMB/CIFS implementation. + simple ASN1 code + Copyright (C) Andrew Tridgell 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _ASN_1_H +#define _ASN_1_H + +#include "replace.h" +#include <talloc.h> +#include "lib/util/data_blob.h" + + +struct nesting; +struct asn1_data; +typedef struct asn1_data ASN1_DATA; + +#define ASN1_APPLICATION(x) ((x)+0x60) +#define ASN1_APPLICATION_SIMPLE(x) ((x)+0x40) +#define ASN1_SEQUENCE(x) ((x)+0x30) +#define ASN1_CONTEXT(x) ((x)+0xa0) +#define ASN1_CONTEXT_SIMPLE(x) ((x)+0x80) +#define ASN1_GENERAL_STRING 0x1b +#define ASN1_OCTET_STRING 0x4 +#define ASN1_OID 0x6 +#define ASN1_BOOLEAN 0x1 +#define ASN1_INTEGER 0x2 +#define ASN1_BIT_STRING 0x3 +#define ASN1_ENUMERATED 0xa +#define ASN1_SET 0x31 + +#define ASN1_MAX_OIDS 20 + +/* + * The maximum permitted depth for an ASN.1 parse tree, the limit is chosen + * to align with the value for windows. Note that this value will trigger + * ASAN stack overflow errors. + */ +#define ASN1_MAX_TREE_DEPTH 512 + +struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx, unsigned max_depth); +void asn1_free(struct asn1_data *data); +bool asn1_has_error(const struct asn1_data *data); +void asn1_set_error(struct asn1_data *data); +bool asn1_has_nesting(const struct asn1_data *data); +off_t asn1_current_ofs(const struct asn1_data *data); +bool asn1_write(struct asn1_data *data, const void *p, int len); +bool asn1_write_uint8(struct asn1_data *data, uint8_t v); +bool asn1_push_tag(struct asn1_data *data, uint8_t tag); +bool asn1_pop_tag(struct asn1_data *data); +bool asn1_write_implicit_Integer(struct asn1_data *data, int i); +bool asn1_write_Integer(struct asn1_data *data, int i); +bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, uint8_t padding); +bool ber_write_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *OID); +bool ber_write_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *partial_oid); +bool asn1_write_OID(struct asn1_data *data, const char *OID); +bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length); +bool asn1_write_LDAPString(struct asn1_data *data, const char *s); +bool asn1_write_DATA_BLOB_LDAPString(struct asn1_data *data, const DATA_BLOB *s); +bool asn1_write_GeneralString(struct asn1_data *data, const char *s); +bool asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob); +bool asn1_write_BOOLEAN(struct asn1_data *data, bool v); +bool asn1_read_BOOLEAN(struct asn1_data *data, bool *v); +bool asn1_check_BOOLEAN(struct asn1_data *data, bool v); +bool asn1_write_BOOLEAN_context(struct asn1_data *data, bool v, int context); +bool asn1_read_BOOLEAN_context(struct asn1_data *data, bool *v, int context); +bool asn1_load(struct asn1_data *data, DATA_BLOB blob); +bool asn1_peek(struct asn1_data *data, void *p, int len); +bool asn1_read(struct asn1_data *data, void *p, int len); +bool asn1_read_uint8(struct asn1_data *data, uint8_t *v); +bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v); +bool asn1_peek_tag(struct asn1_data *data, uint8_t tag); +bool asn1_start_tag(struct asn1_data *data, uint8_t tag); +bool asn1_end_tag(struct asn1_data *data); +int asn1_tag_remaining(struct asn1_data *data); +bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, char **OID); +bool ber_read_partial_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, char **partial_oid); +bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **OID); +bool asn1_check_OID(struct asn1_data *data, const char *OID); +bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s); +bool asn1_read_GeneralString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s); +bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob); +bool asn1_read_ContextSimple(struct asn1_data *data, TALLOC_CTX *mem_ctx, uint8_t num, DATA_BLOB *blob); +bool asn1_read_implicit_Integer(struct asn1_data *data, int *i); +bool asn1_read_Integer(struct asn1_data *data, int *i); +bool asn1_read_BitString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob, uint8_t *padding); +bool asn1_read_enumerated(struct asn1_data *data, int *v); +bool asn1_write_enumerated(struct asn1_data *data, uint8_t v); +bool asn1_blob(const struct asn1_data *asn1, DATA_BLOB *blob); +bool asn1_extract_blob(struct asn1_data *asn1, TALLOC_CTX *mem_ctx, + DATA_BLOB *pblob); +void asn1_load_nocopy(struct asn1_data *data, uint8_t *buf, size_t len); +int asn1_peek_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size); +size_t asn1_get_length(const struct asn1_data *asn1); + +#endif /* _ASN_1_H */ diff --git a/lib/util/attr.h b/lib/util/attr.h new file mode 100644 index 0000000..af3e244 --- /dev/null +++ b/lib/util/attr.h @@ -0,0 +1,105 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __UTIL_ATTR_H__ +#define __UTIL_ATTR_H__ + +/* for old gcc releases that don't have the feature test macro __has_attribute */ +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +#ifndef _UNUSED_ +#if __has_attribute(unused) || ( (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) ) +/** gcc attribute used on function parameters so that it does not emit + * warnings about them being unused. **/ +# define _UNUSED_ __attribute__ ((unused)) +#else +# define _UNUSED_ +#endif +#endif +#ifndef UNUSED +#define UNUSED(param) param _UNUSED_ +#endif + +#ifndef _DEPRECATED_ +#if __has_attribute(deprecated) || ( (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) ) +#define _DEPRECATED_ __attribute__ ((deprecated)) +#else +#define _DEPRECATED_ +#endif +#endif + +#ifndef _WARN_UNUSED_RESULT_ +#if __has_attribute(warn_unused_result) || ( (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) ) +#define _WARN_UNUSED_RESULT_ __attribute__ ((warn_unused_result)) +#else +#define _WARN_UNUSED_RESULT_ +#endif +#endif + +#ifndef _NORETURN_ +#if __has_attribute(noreturn) || ( (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) ) +#define _NORETURN_ __attribute__ ((noreturn)) +#else +#define _NORETURN_ +#endif +#endif + +#ifndef _PURE_ +#if __has_attribute(pure) || ( (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) ) +#define _PURE_ __attribute__((pure)) +#else +#define _PURE_ +#endif +#endif + +#ifndef NONNULL +#if __has_attribute(nonnull) || ( (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) ) +#define NONNULL(param) param __attribute__((nonnull)) +#else +#define NONNULL(param) param +#endif +#endif + +#ifndef PRINTF_ATTRIBUTE +#if __has_attribute(format) || ( (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) ) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +#ifndef FORMAT_ATTRIBUTE +#if __has_attribute(format) || ( (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) ) +/** Use gcc attribute to check printf fns. a1 is argument to format() + * in the above macro. This is needed to support Heimdal's printf + * decorations. Note that some gcc 2.x versions don't handle this + * properly. **/ +#define FORMAT_ATTRIBUTE(a) __attribute__ ((format a)) +#else +#define FORMAT_ATTRIBUTE(a) +#endif +#endif + +#endif /* __UTIL_ATTR_H__ */ diff --git a/lib/util/base64.c b/lib/util/base64.c new file mode 100644 index 0000000..7acc83d --- /dev/null +++ b/lib/util/base64.c @@ -0,0 +1,169 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Simo Sorce 2001-2002 + Copyright (C) Martin Pool 2003 + Copyright (C) James Peach 2006 + Copyright (C) Jeremy Allison 1992-2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "lib/util/base64.h" + +static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/** + * Decode a base64 string into a DATA_BLOB - simple and slow algorithm. + * + * A DATA_BLOB like {.data = NULL, length = 0} indicates memory error. + * + * Decoding stops at the first invalid character. + **/ +_PUBLIC_ DATA_BLOB base64_decode_data_blob_talloc(TALLOC_CTX *mem_ctx, const char *s) +{ + int bit_offset, byte_offset, idx, i, n; + DATA_BLOB decoded = data_blob_talloc(mem_ctx, s, strlen(s)+1); + unsigned char *d = decoded.data; + char *p; + + if (decoded.data == NULL) { + decoded.length = 0; + return decoded; + } + + n=i=0; + + while (*s && (p=strchr(b64,*s))) { + idx = (int)(p - b64); + byte_offset = (i*6)/8; + bit_offset = (i*6)%8; + d[byte_offset] &= ~((1<<(8-bit_offset))-1); + if (bit_offset < 3) { + d[byte_offset] |= (idx << (2-bit_offset)); + n = byte_offset+1; + } else { + d[byte_offset] |= (idx >> (bit_offset-2)); + d[byte_offset+1] = (idx << (8-(bit_offset-2))) & 0xFF; + n = byte_offset+2; + } + s++; i++; + } + + if ((n > 0) && (*s == '=')) { + n -= 1; + } + + /* fix up length */ + decoded.length = n; + decoded.data = talloc_realloc(mem_ctx, decoded.data, uint8_t, n); + return decoded; +} + +/** + * Decode a base64 string into a DATA_BLOB - simple and slow algorithm + **/ +_PUBLIC_ DATA_BLOB base64_decode_data_blob(const char *s) +{ + return base64_decode_data_blob_talloc(NULL, s); +} + +/** + * Decode a base64 string in-place - wrapper for the above + **/ +_PUBLIC_ void base64_decode_inplace(char *s) +{ + DATA_BLOB decoded = base64_decode_data_blob(s); + + if ( decoded.length != 0 ) { + memcpy(s, decoded.data, decoded.length); + + /* null terminate */ + s[decoded.length] = '\0'; + } else { + *s = '\0'; + } + + data_blob_free(&decoded); +} + +/** + * Encode a base64 string into a talloc()ed string caller to free. + * + * From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c + * with adjustments + **/ + +_PUBLIC_ char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data) +{ + int bits = 0; + int char_count = 0; + size_t out_cnt, len, output_len; + char *result; + + /* + * Note: we return NULL for a zero-length blob, even though it can be + * encoded as a zero length string in base64. + * + * FIXME, perhaps, but we need to check carefully before changing + * this. + */ + if (data.length == 0 || data.data == NULL) { + return NULL; + } + + out_cnt = 0; + len = data.length; + output_len = data.length * 2 + 4; /* Account for closing bytes. 4 is + * random but should be enough for + * the = and \0 */ + result = talloc_array(mem_ctx, char, output_len); /* get us plenty of space */ + if (result == NULL) { + return NULL; + } + + while (len--) { + int c = (unsigned char) *(data.data++); + bits += c; + char_count++; + if (char_count == 3) { + result[out_cnt++] = b64[bits >> 18]; + result[out_cnt++] = b64[(bits >> 12) & 0x3f]; + result[out_cnt++] = b64[(bits >> 6) & 0x3f]; + result[out_cnt++] = b64[bits & 0x3f]; + bits = 0; + char_count = 0; + } else { + bits <<= 8; + } + } + if (char_count != 0) { + bits <<= 16 - (8 * char_count); + result[out_cnt++] = b64[bits >> 18]; + result[out_cnt++] = b64[(bits >> 12) & 0x3f]; + if (char_count == 1) { + result[out_cnt++] = '='; + result[out_cnt++] = '='; + } else { + result[out_cnt++] = b64[(bits >> 6) & 0x3f]; + result[out_cnt++] = '='; + } + } + result[out_cnt] = '\0'; /* terminate */ + return result; +} + diff --git a/lib/util/base64.h b/lib/util/base64.h new file mode 100644 index 0000000..4763804 --- /dev/null +++ b/lib/util/base64.h @@ -0,0 +1,52 @@ +/* + * Unix SMB/CIFS implementation. + * Samba utility functions + * + * Copyright (C) Andrew Tridgell 1992-2001 + * Copyright (C) Simo Sorce 2001-2002 + * Copyright (C) Martin Pool 2003 + * Copyright (C) James Peach 2006 + * Copyright (C) Jeremy Allison 1992-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LIB_UTIL_BASE64_H__ +#define __LIB_UTIL_BASE64_H__ + +#include "replace.h" +#include "lib/util/data_blob.h" + +/** + Base64 decode a string, place into a data blob. Caller to + data_blob_free() the result. +**/ +DATA_BLOB base64_decode_data_blob_talloc(TALLOC_CTX *mem_ctx, const char *s); + +/** + Base64 decode a string, place into a data blob on NULL context. + Caller to data_blob_free() the result. +**/ +DATA_BLOB base64_decode_data_blob(const char *s); + +/** + Base64 decode a string, inplace +**/ +void base64_decode_inplace(char *s); +/** + Base64 encode a binary data blob into a string +**/ +char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data); + +#endif diff --git a/lib/util/become_daemon.c b/lib/util/become_daemon.c new file mode 100644 index 0000000..c6795c5 --- /dev/null +++ b/lib/util/become_daemon.c @@ -0,0 +1,151 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001-2002 + Copyright (C) Simo Sorce 2001 + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + Copyright (C) James J Myers 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/locale.h" +#if defined(HAVE_LIBSYSTEMD_DAEMON) || defined(HAVE_LIBSYSTEMD) +#include <systemd/sd-daemon.h> +#endif + +#include "close_low_fd.h" +#include "debug.h" + +#include "become_daemon.h" + +static bool sd_notifications = true; + +/******************************************************************* + Enable or disable daemon status systemd notifications +********************************************************************/ +void daemon_sd_notifications(bool enable) +{ + sd_notifications = enable; + DBG_DEBUG("Daemon status systemd notifications %s\n", + sd_notifications ? "enabled" : "disabled"); +} + +/**************************************************************************** + Become a daemon, discarding the controlling terminal. +****************************************************************************/ + +void become_daemon(bool do_fork, bool no_session, bool log_stdout) +{ + pid_t newpid; + if (do_fork) { + newpid = fork(); + if (newpid == -1) { + exit_daemon("Fork failed", errno); + } + if (newpid) { + _exit(0); + } +#if defined(HAVE_LIBSYSTEMD_DAEMON) || defined(HAVE_LIBSYSTEMD) + } else if (sd_notifications) { + sd_notify(0, "STATUS=Starting process..."); +#endif + } + + /* detach from the terminal */ +#ifdef HAVE_SETSID + if (!no_session) { + int ret = setsid(); + if (ret == -1) { + exit_daemon("Failed to create session", errno); + } + } +#elif defined(TIOCNOTTY) + if (!no_session) { + int i = open("/dev/tty", O_RDWR, 0); + if (i != -1) { + ioctl(i, (int) TIOCNOTTY, (char *)0); + close(i); + } + } +#endif /* HAVE_SETSID */ + + /* Close fd's 0,1,2 as appropriate. Needed if started by rsh. */ + /* stdin must be open if we do not fork, for monitoring for + * close. stdout must be open if we are logging there, and we + * never close stderr (but debug might dup it onto a log file) */ + if (do_fork) { + int ret = close_low_fd(0); + if (ret != 0) { + exit_daemon("close_low_fd(0) failed: %s\n", errno); + } + } + if (!log_stdout) { + int ret = close_low_fd(1); + if (ret != 0) { + exit_daemon("close_low_fd(1) failed: %s\n", errno); + } + } +} + +void exit_daemon(const char *msg, int error) +{ + if (msg == NULL) { + msg = strerror(error); + } + +#if defined(HAVE_LIBSYSTEMD_DAEMON) || defined(HAVE_LIBSYSTEMD) + if (sd_notifications) { + sd_notifyf(0, "STATUS=daemon failed to start: %s\n" + "ERRNO=%i", + msg, + error); + } +#endif + DBG_ERR("daemon failed to start: %s, error code %d\n", + msg, error); + exit(1); +} + +void daemon_ready(const char *daemon) +{ + if (daemon == NULL) { + daemon = "Samba"; + } +#if defined(HAVE_LIBSYSTEMD_DAEMON) || defined(HAVE_LIBSYSTEMD) + if (sd_notifications) { + sd_notifyf(0, + "READY=1\nSTATUS=%s: ready to serve connections...", + daemon); + } +#endif + DBG_INFO("daemon '%s' finished starting up and ready to serve " + "connections\n", daemon); +} + +void daemon_status(const char *daemon, const char *msg) +{ + if (daemon == NULL) { + daemon = "Samba"; + } +#if defined(HAVE_LIBSYSTEMD_DAEMON) || defined(HAVE_LIBSYSTEMD) + if (sd_notifications) { + sd_notifyf(0, "STATUS=%s: %s", daemon, msg); + } +#endif + DBG_STARTUP_NOTICE("daemon '%s' : %s\n", daemon, msg); +} diff --git a/lib/util/become_daemon.h b/lib/util/become_daemon.h new file mode 100644 index 0000000..e12be27 --- /dev/null +++ b/lib/util/become_daemon.h @@ -0,0 +1,89 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001-2002 + Copyright (C) Simo Sorce 2001 + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + Copyright (C) James J Myers 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _BECOME_DAEMON_H +#define _BECOME_DAEMON_H + +#include <stdbool.h> + +/** + * @file become_daemon.h + * + * @brief Utilities for demonising + */ + +/** + * @brief Enable or disable daemon status systemd notifications + * + * When samba runs as AD DC only the main 'samba' process has to + * notify systemd. Child processes started by the main 'samba', like + * smbd and winbindd should call this function to disable sd_notify() + * calls. + * + * @param[in] enable True to enable notifications, false to disable +**/ +void daemon_sd_notifications(bool enable); + +/** + * @brief Become a daemon, optionally discarding the controlling terminal + * + * @param[in] do_fork Should the process fork? + * @param[in] no_session Don't start a new session + * @param[in] log_stdour Should stdout be closed? +**/ +void become_daemon(bool do_fork, bool no_session, bool log_stdout); + +/** + * @brief Exit daemon and log an error message at ERR level + * + * Optionally report failure to systemd if systemd integration is + * enabled. + * + * @param[in] msg Message to log, generated from error if NULL + * @param[in] error Errno of error that occurred +**/ +void exit_daemon(const char *msg, int error); + +/** + * @brief Log at ERR level that the daemon is ready to serve connections + * + * Optionally report status to systemd if systemd integration is enabled. + * + * @param[in] daemon Name of daemon to include it message +**/ +void daemon_ready(const char *daemon); + +/** + * @brief Log at ERR level the specified daemon status + * + * For example if it is not ready to serve connections and is waiting + * for some event to happen. + * + * Optionally report status to systemd if systemd integration is enabled. + * + * @param[in] daemon Name of daemon to include it message + * @param[in] msg Message to log +**/ +void daemon_status(const char *daemon, const char *msg); + +#endif /* _BECOME_DAEMON_H */ diff --git a/lib/util/binsearch.h b/lib/util/binsearch.h new file mode 100644 index 0000000..8ae9da2 --- /dev/null +++ b/lib/util/binsearch.h @@ -0,0 +1,121 @@ +/* + Unix SMB/CIFS implementation. + + a generic binary search macro + + Copyright (C) Andrew Tridgell 2009 + + ** NOTE! The following LGPL license applies to the binsearch.h + ** header. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _BINSEARCH_H +#define _BINSEARCH_H + +/* a binary array search, where the array is an array of pointers to structures, + and we want to find a match for 'target' on 'field' in those structures. + + Inputs: + array: base pointer to an array of structures + arrray_size: number of elements in the array + field: the name of the field in the structure we are keying off + target: the field value we are looking for + comparison_fn: the comparison function + result: where the result of the search is put + + if the element is found, then 'result' is set to point to the found array element. If not, + then 'result' is set to NULL. + + The array is assumed to be sorted by the same comparison_fn as the + search (with, for example, qsort) + */ +#define BINARY_ARRAY_SEARCH_P(array, array_size, field, target, comparison_fn, result) do { \ + int32_t _b, _e; \ + (result) = NULL; \ + if (array_size) { for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \ + int32_t _i = (_b+_e)/2; \ + int _r = comparison_fn(target, array[_i]->field); \ + if (_r == 0) { (result) = array[_i]; break; } \ + if (_r < 0) _e = _i - 1; else _b = _i + 1; \ + }} } while (0) + +/* + like BINARY_ARRAY_SEARCH_P, but assumes that the array is an array + of structures, rather than pointers to structures + + result points to the found structure, or NULL + */ +#define BINARY_ARRAY_SEARCH(array, array_size, field, target, comparison_fn, result) do { \ + int32_t _b, _e; \ + (result) = NULL; \ + if (array_size) { for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \ + int32_t _i = (_b+_e)/2; \ + int _r = comparison_fn(target, array[_i].field); \ + if (_r == 0) { (result) = &array[_i]; break; } \ + if (_r < 0) _e = _i - 1; else _b = _i + 1; \ + }} } while (0) + +/* + like BINARY_ARRAY_SEARCH_P, but assumes that the array is an array + of elements, rather than pointers to structures + + result points to the found structure, or NULL + */ +#define BINARY_ARRAY_SEARCH_V(array, array_size, target, comparison_fn, result) do { \ + int32_t _b, _e; \ + (result) = NULL; \ + if (array_size) { for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \ + int32_t _i = (_b+_e)/2; \ + int _r = comparison_fn(target, array[_i]); \ + if (_r == 0) { (result) = &array[_i]; break; } \ + if (_r < 0) _e = _i - 1; else _b = _i + 1; \ + }} } while (0) + + +/* + like BINARY_ARRAY_SEARCH_V, but if an exact result is not found, the 'next' + argument will point to the element after the place where the exact result + would have been. If an exact result is found, 'next' will be NULL. If the + target is beyond the end of the list, both 'exact' and 'next' will be NULL. + Unlike other binsearch macros, where there are several elements that compare + the same, the exact result will always point to the first one. + + If you don't care to distinguish between the 'greater than' and 'equals' + cases, you can use the same pointer for both 'exact' and 'next'. + + As with all the binsearch macros, the comparison function is always called + with the search term first. + */ +#define BINARY_ARRAY_SEARCH_GTE(array, array_size, target, comparison_fn, \ + exact, next) do { \ + int32_t _b, _e; \ + (exact) = NULL; (next) = NULL; \ + if ((array_size) > 0) { \ + for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \ + int32_t _i = (_b + _e) / 2; \ + int _r = comparison_fn(target, &array[_i]); \ + if (_r == 0) { \ + (exact) = &array[_i]; \ + _e = _i - 1; \ + } else if (_r < 0) { _e = _i - 1; \ + } else { _b = _i + 1; } \ + } \ + if ((exact) == NULL &&_b < (array_size)) { \ + (next) = &array[_b]; \ + } } } while (0) + +#endif diff --git a/lib/util/bitmap.c b/lib/util/bitmap.c new file mode 100644 index 0000000..12cdfe4 --- /dev/null +++ b/lib/util/bitmap.c @@ -0,0 +1,144 @@ +/* + Unix SMB/CIFS implementation. + simple bitmap functions + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include <talloc.h> +#include "lib/util/bitmap.h" +#include "lib/util/debug.h" +#include "lib/util/fault.h" + +struct bitmap { + unsigned int n; + uint32_t b[1]; /* We allocate more */ +}; + +/* these functions provide a simple way to allocate integers from a + pool without repetition */ + +/**************************************************************************** +talloc a bitmap +****************************************************************************/ +struct bitmap *bitmap_talloc(TALLOC_CTX *mem_ctx, int n) +{ + struct bitmap *bm; + + bm = (struct bitmap *)talloc_zero_size( + mem_ctx, + offsetof(struct bitmap, b) + sizeof(uint32_t)*((n+31)/32)); + + if (!bm) return NULL; + + talloc_set_name_const(bm, "struct bitmap"); + + bm->n = n; + return bm; +} + +/**************************************************************************** +copy as much of the source bitmap as will fit in the destination bitmap. +****************************************************************************/ + +int bitmap_copy(struct bitmap * const dst, const struct bitmap * const src) +{ + int count = MIN(dst->n, src->n); + + SMB_ASSERT(dst->b != src->b); + memcpy(dst->b, src->b, sizeof(uint32_t)*((count+31)/32)); + + return count; +} + +/**************************************************************************** +set a bit in a bitmap +****************************************************************************/ +bool bitmap_set(struct bitmap *bm, unsigned i) +{ + if (i >= bm->n) { + DEBUG(0,("Setting invalid bitmap entry %d (of %d)\n", + i, bm->n)); + return false; + } + bm->b[i/32] |= (1U<<(i%32)); + return true; +} + +/**************************************************************************** +clear a bit in a bitmap +****************************************************************************/ +bool bitmap_clear(struct bitmap *bm, unsigned i) +{ + if (i >= bm->n) { + DEBUG(0,("clearing invalid bitmap entry %d (of %d)\n", + i, bm->n)); + return false; + } + bm->b[i/32] &= ~(1U<<(i%32)); + return true; +} + +/**************************************************************************** +query a bit in a bitmap +****************************************************************************/ +bool bitmap_query(struct bitmap *bm, unsigned i) +{ + if (i >= bm->n) return false; + if (bm->b[i/32] & (1U<<(i%32))) { + return true; + } + return false; +} + +/**************************************************************************** +find a zero bit in a bitmap starting at the specified offset, with +wraparound +****************************************************************************/ +int bitmap_find(struct bitmap *bm, unsigned ofs) +{ + unsigned int i, j; + + if (ofs > bm->n) ofs = 0; + + i = ofs; + while (i < bm->n) { + if (~(bm->b[i/32])) { + j = i; + do { + if (!bitmap_query(bm, j)) return j; + j++; + } while (j & 31 && j < bm->n); + } + i += 32; + i &= ~31; + } + + i = 0; + while (i < ofs) { + if (~(bm->b[i/32])) { + j = i; + do { + if (!bitmap_query(bm, j)) return j; + j++; + } while (j & 31 && j < bm->n); + } + i += 32; + i &= ~31; + } + + return -1; +} diff --git a/lib/util/bitmap.h b/lib/util/bitmap.h new file mode 100644 index 0000000..6d75929 --- /dev/null +++ b/lib/util/bitmap.h @@ -0,0 +1,29 @@ +/* + Unix SMB/CIFS implementation. + simple bitmap functions + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* The following definitions come from lib/bitmap.c */ + +struct bitmap; + +struct bitmap *bitmap_talloc(TALLOC_CTX *mem_ctx, int n); +int bitmap_copy(struct bitmap * const dst, const struct bitmap * const src); +bool bitmap_set(struct bitmap *bm, unsigned i); +bool bitmap_clear(struct bitmap *bm, unsigned i); +bool bitmap_query(struct bitmap *bm, unsigned i); +int bitmap_find(struct bitmap *bm, unsigned ofs); diff --git a/lib/util/blocking.c b/lib/util/blocking.c new file mode 100644 index 0000000..6d7fc91 --- /dev/null +++ b/lib/util/blocking.c @@ -0,0 +1,76 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001-2002 + Copyright (C) Simo Sorce 2001 + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + Copyright (C) James J Myers 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "blocking.h" + +/** + Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, + else + if SYSV use O_NDELAY + if BSD use FNDELAY +**/ + +_PUBLIC_ int set_blocking(int fd, bool set) +{ + int val; +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if((val = fcntl(fd, F_GETFL, 0)) == -1) + return -1; + if(set) /* Turn blocking on - ie. clear nonblock flag */ + val &= ~FLAG_TO_SET; + else + val |= FLAG_TO_SET; + return fcntl( fd, F_SETFL, val); +#undef FLAG_TO_SET +} + + +_PUBLIC_ bool smb_set_close_on_exec(int fd) +{ +#ifdef FD_CLOEXEC + int val; + + val = fcntl(fd, F_GETFD, 0); + if (val >= 0) { + val |= FD_CLOEXEC; + val = fcntl(fd, F_SETFD, val); + if (val != -1) { + return true; + } + } +#else + errno = ENOSYS; +#endif + return false; +} diff --git a/lib/util/blocking.h b/lib/util/blocking.h new file mode 100644 index 0000000..d605352 --- /dev/null +++ b/lib/util/blocking.h @@ -0,0 +1,34 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001-2002 + Copyright (C) Simo Sorce 2001 + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + Copyright (C) James J Myers 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_BLOCKING_H_ +#define _SAMBA_BLOCKING_H_ + +#include <stdbool.h> + +int set_blocking(int fd, bool set); +bool smb_set_close_on_exec(int fd); + +#define set_close_on_exec(fd) smb_set_close_on_exec(fd) + +#endif /* _SAMBA_BLOCKING_H_ */ diff --git a/lib/util/bytearray.h b/lib/util/bytearray.h new file mode 100644 index 0000000..0af8a82 --- /dev/null +++ b/lib/util/bytearray.h @@ -0,0 +1,124 @@ +/* + * Macros for handling integer types in byte arrays + * + * This file is originally from the libssh.org project + * + * Copyright (c) 2018 Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _BYTEARRAY_H +#define _BYTEARRAY_H + +#define _DATA_BYTE_CONST(data, pos) \ + ((uint8_t)(((const uint8_t *)(data))[(pos)])) + +#define _DATA_BYTE(data, pos) \ + (((uint8_t *)(data))[(pos)]) + +/* + * These macros pull or push integer values from byte arrays stored in + * little-endian byte order. + */ +#define PULL_LE_U8(data, pos) \ + (_DATA_BYTE_CONST(data, pos)) +#define PULL_LE_I8(data, pos) \ + (int8_t)PULL_LE_U8(data, pos) + +#define PULL_LE_U16(data, pos) \ + ((uint16_t)PULL_LE_U8(data, pos) | ((uint16_t)(PULL_LE_U8(data, (pos) + 1))) << 8) +#define PULL_LE_I16(data, pos) \ + (int16_t)PULL_LE_U16(data, pos) + +#define PULL_LE_U32(data, pos) \ + ((uint32_t)(PULL_LE_U16(data, pos) | ((uint32_t)PULL_LE_U16(data, (pos) + 2)) << 16)) +#define PULL_LE_I32(data, pos) \ + (int32_t)PULL_LE_U32(data, pos) + +#define PULL_LE_U64(data, pos) \ + ((uint64_t)(PULL_LE_U32(data, pos) | ((uint64_t)PULL_LE_U32(data, (pos) + 4)) << 32)) +#define PULL_LE_I64(data, pos) \ + (int64_t)PULL_LE_U64(data, pos) + + +#define PUSH_LE_U8(data, pos, val) \ + (_DATA_BYTE(data, pos) = ((uint8_t)(val))) +#define PUSH_LE_I8(data, pos, val) \ + PUSH_LE_U8(data, pos, val) + +#define PUSH_LE_U16(data, pos, val) \ + (PUSH_LE_U8(data, pos, (uint16_t)(val) & 0xff), PUSH_LE_U8(data, (pos) + 1, (uint16_t)(val) >> 8)) +#define PUSH_LE_I16(data, pos, val) \ + PUSH_LE_U16(data, pos, val) + +#define PUSH_LE_U32(data, pos, val) \ + (PUSH_LE_U16(data, pos, (uint32_t)(val) & 0xffff), PUSH_LE_U16(data, (pos) + 2, (uint32_t)(val) >> 16)) +#define PUSH_LE_I32(data, pos, val) \ + PUSH_LE_U32(data, pos, val) + +#define PUSH_LE_U64(data, pos, val) \ + (PUSH_LE_U32(data, pos, (uint64_t)(val) & 0xffffffff), PUSH_LE_U32(data, (pos) + 4, (uint64_t)(val) >> 32)) +#define PUSH_LE_I64(data, pos, val) \ + PUSH_LE_U64(data, pos, val) + + + +/* + * These macros pull or push integer values from byte arrays stored in + * big-endian byte order (network byte order). + */ +#define PULL_BE_U8(data, pos) \ + (_DATA_BYTE_CONST(data, pos)) +#define PULL_BE_I8(data, pos) \ + (int8_t)PULL_BE_U8(data, pos) + +#define PULL_BE_U16(data, pos) \ + ((((uint16_t)(PULL_BE_U8(data, pos))) << 8) | (uint16_t)PULL_BE_U8(data, (pos) + 1)) +#define PULL_BE_I16(data, pos) \ + (int16_t)PULL_BE_U16(data, pos) + +#define PULL_BE_U32(data, pos) \ + ((((uint32_t)PULL_BE_U16(data, pos)) << 16) | (uint32_t)(PULL_BE_U16(data, (pos) + 2))) +#define PULL_BE_I32(data, pos) \ + (int32_t)PULL_BE_U32(data, pos) + +#define PULL_BE_U64(data, pos) \ + ((((uint64_t)PULL_BE_U32(data, pos)) << 32) | (uint64_t)(PULL_BE_U32(data, (pos) + 4))) +#define PULL_BE_I64(data, pos) \ + (int64_t)PULL_BE_U64(data, pos) + + + +#define PUSH_BE_U8(data, pos, val) \ + (_DATA_BYTE(data, pos) = ((uint8_t)(val))) +#define PUSH_BE_I8(data, pos, val) \ + PUSH_BE_U8(data, pos, val) + +#define PUSH_BE_U16(data, pos, val) \ + (PUSH_BE_U8(data, pos, ((uint16_t)(val)) >> 8), PUSH_BE_U8(data, (pos) + 1, (uint16_t)(val) & 0xff)) +#define PUSH_BE_I16(data, pos, val) \ + PUSH_BE_U16(data, pos, val) + +#define PUSH_BE_U32(data, pos, val) \ + (PUSH_BE_U16(data, pos, (uint32_t)(val) >> 16), PUSH_BE_U16(data, (pos) + 2, (uint32_t)(val) & 0xffff)) +#define PUSH_BE_I32(data, pos, val) \ + PUSH_BE_U32(data, pos, val) + +#define PUSH_BE_U64(data, pos, val) \ + (PUSH_BE_U32(data, pos, (uint64_t)(val) >> 32), PUSH_BE_U32(data, (pos) + 4, (uint64_t)(val) & 0xffffffff)) +#define PUSH_BE_I64(data, pos, val) \ + PUSH_BE_U64(data, pos, val) + +#endif /* _BYTEARRAY_H */ diff --git a/lib/util/byteorder.h b/lib/util/byteorder.h new file mode 100644 index 0000000..65023f9 --- /dev/null +++ b/lib/util/byteorder.h @@ -0,0 +1,169 @@ +/* + Unix SMB/CIFS implementation. + SMB Byte handling + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _BYTEORDER_H +#define _BYTEORDER_H + +#include "bytearray.h" + +/* + This file implements macros for machine independent short and + int manipulation + +Here is a description of this file that I emailed to the samba list once: + +> I am confused about the way that byteorder.h works in Samba. I have +> looked at it, and I would have thought that you might make a distinction +> between LE and BE machines, but you only seem to distinguish between 386 +> and all other architectures. +> +> Can you give me a clue? + +sure. + +Ok, now to the macros themselves. I'll take a simple example, say we +want to extract a 2 byte integer from a SMB packet and put it into a +type called uint16_t that is in the local machines byte order, and you +want to do it with only the assumption that uint16_t is _at_least_ 16 +bits long (this last condition is very important for architectures +that don't have any int types that are 2 bytes long) + +You do this: + +#define CVAL(buf,pos) (((uint8_t *)(buf))[pos]) +#define PVAL(buf,pos) ((unsigned int)CVAL(buf,pos)) +#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) + +then to extract a uint16_t value at offset 25 in a buffer you do this: + +char *buffer = foo_bar(); +uint16_t xx = SVAL(buffer,25); + +We are using the byteorder independence of the ANSI C bitshifts to do +the work. A good optimising compiler should turn this into efficient +code, especially if it happens to have the right byteorder :-) + +I know these macros can be made a bit tidier by removing some of the +casts, but you need to look at byteorder.h as a whole to see the +reasoning behind them. byteorder.h defines the following macros: + +SVAL(buf,pos) - extract a 2 byte SMB value +IVAL(buf,pos) - extract a 4 byte SMB value +BVAL(buf,pos) - extract a 8 byte SMB value +SVALS(buf,pos) - signed version of SVAL() +IVALS(buf,pos) - signed version of IVAL() +BVALS(buf,pos) - signed version of BVAL() + +SSVAL(buf,pos,val) - put a 2 byte SMB value into a buffer +SIVAL(buf,pos,val) - put a 4 byte SMB value into a buffer +SBVAL(buf,pos,val) - put a 8 byte SMB value into a buffer +SSVALS(buf,pos,val) - signed version of SSVAL() +SIVALS(buf,pos,val) - signed version of SIVAL() +SBVALS(buf,pos,val) - signed version of SBVAL() + +RSVAL(buf,pos) - like SVAL() but for NMB byte ordering +RSVALS(buf,pos) - like SVALS() but for NMB byte ordering +RIVAL(buf,pos) - like IVAL() but for NMB byte ordering +RIVALS(buf,pos) - like IVALS() but for NMB byte ordering +RSSVAL(buf,pos,val) - like SSVAL() but for NMB ordering +RSIVAL(buf,pos,val) - like SIVAL() but for NMB ordering +RSIVALS(buf,pos,val) - like SIVALS() but for NMB ordering + +it also defines lots of intermediate macros, just ignore those :-) + +*/ + + +/**************************************************************************** + * + * ATTENTION: Do not use those macros anymore, use the ones from bytearray.h + * + ****************************************************************************/ + +#define CVAL(buf,pos) ((uint32_t)_DATA_BYTE_CONST(buf, pos)) +#define CVAL_NC(buf,pos) _DATA_BYTE(buf, pos) /* Non-const version of CVAL */ +#define PVAL(buf,pos) (CVAL(buf,pos)) +#define SCVAL(buf,pos,val) (CVAL_NC(buf,pos) = (val)) + +/**************************************************************************** + * + * ATTENTION: Do not use those macros anymore, use the ones from bytearray.h + * + ****************************************************************************/ + +#define SVAL(buf,pos) (uint32_t)PULL_LE_U16(buf, pos) +#define IVAL(buf,pos) PULL_LE_U32(buf, pos) +#define SSVALX(buf,pos,val) (CVAL_NC(buf,pos)=(uint8_t)((val)&0xFF),CVAL_NC(buf,(pos)+1)=(uint8_t)((val)>>8)) +#define SIVALX(buf,pos,val) (SSVALX(buf,pos,(val)&0xFFFF),SSVALX(buf,(pos)+2,(val)>>16)) +#define SVALS(buf,pos) ((int16_t)SVAL(buf,pos)) +#define IVALS(buf,pos) ((int32_t)IVAL(buf,pos)) +#define SSVAL(buf,pos,val) PUSH_LE_U16(buf, pos, val) +#define SIVAL(buf,pos,val) PUSH_LE_U32(buf, pos, val) +#define SSVALS(buf,pos,val) PUSH_LE_U16(buf, pos, val) +#define SIVALS(buf,pos,val) PUSH_LE_U32(buf, pos, val) + +/**************************************************************************** + * + * ATTENTION: Do not use those macros anymore, use the ones from bytearray.h + * + ****************************************************************************/ + +/* 64 bit macros */ +#define BVAL(p, ofs) PULL_LE_U64(p, ofs) +#define BVALS(p, ofs) ((int64_t)BVAL(p,ofs)) +#define SBVAL(p, ofs, v) PUSH_LE_U64(p, ofs, v) +#define SBVALS(p, ofs, v) (SBVAL(p,ofs,(uint64_t)(v))) + +/**************************************************************************** + * + * ATTENTION: Do not use those macros anymore, use the ones from bytearray.h + * + ****************************************************************************/ + +/* now the reverse routines - these are used in nmb packets (mostly) */ +#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) +#define IREV(x) ((SREV((uint32_t)(x))<<16) | (SREV(((uint32_t)(x))>>16))) +#define BREV(x) ((IREV((uint64_t)(x))<<32) | (IREV(((uint64_t)(x))>>32))) + +/**************************************************************************** + * + * ATTENTION: Do not use those macros anymore, use the ones from bytearray.h + * + ****************************************************************************/ + +#define RSVAL(buf,pos) (uint32_t)PULL_BE_U16(buf, pos) +#define RSVALS(buf,pos) PULL_BE_U16(buf, pos) +#define RIVAL(buf,pos) PULL_BE_U32(buf, pos) +#define RIVALS(buf,pos) PULL_BE_U32(buf, pos) +#define RBVAL(buf,pos) PULL_BE_U64(buf, pos) +#define RBVALS(buf,pos) PULL_BE_U64(buf, pos) +#define RSSVAL(buf,pos,val) PUSH_BE_U16(buf, pos, val) +#define RSSVALS(buf,pos,val) PUSH_BE_U16(buf, pos, val) +#define RSIVAL(buf,pos,val) PUSH_BE_U32(buf, pos, val) +#define RSIVALS(buf,pos,val) PUSH_BE_U32(buf, pos, val) +#define RSBVAL(buf,pos,val) PUSH_BE_U64(buf, pos, val) +#define RSBVALS(buf,pos,val) PUSH_BE_U64(buf, pos, val) + +/**************************************************************************** + * + * ATTENTION: Do not use those macros anymore, use the ones from bytearray.h + * + ****************************************************************************/ + +#endif /* _BYTEORDER_H */ diff --git a/lib/util/charset/charset.h b/lib/util/charset/charset.h new file mode 100644 index 0000000..12dc348 --- /dev/null +++ b/lib/util/charset/charset.h @@ -0,0 +1,299 @@ +/* + Unix SMB/CIFS implementation. + charset defines + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* This is a public header file that is installed as part of Samba. + * If you remove any functions or change their signature, update + * the so version number. */ + +#ifndef __CHARSET_H__ +#define __CHARSET_H__ + +#include <talloc.h> +#include <stdbool.h> +#include <stdint.h> + +/* this defines the charset types used in samba */ +typedef enum { + CH_UTF16LE = 0, + CH_UTF16 = 0, + CH_UNIX, + CH_DOS, + CH_UTF8, + CH_UTF16BE, + CH_UTF16MUNGED, + /* The number of distinct character sets. */ + NUM_CHARSETS +} charset_t; + +/* + * SMB UCS2 (16-bit unicode) internal type. + * smb_ucs2_t is *always* in little endian format. + */ + +typedef uint16_t smb_ucs2_t; + +#ifdef WORDS_BIGENDIAN +#define UCS2_SHIFT 8 +#else +#define UCS2_SHIFT 0 +#endif + +/* turn a 7 bit character into a ucs2 character */ +#define UCS2_CHAR(c) ((c) << UCS2_SHIFT) + +/* + * for each charset we have a function that pulls from that charset to + * a ucs2 buffer, and a function that pushes to a ucs2 buffer + * */ + +struct charset_functions { + const char *name; + size_t (*pull)(void *, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + size_t (*push)(void *, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + bool samba_internal_charset; +}; + +/* this type is used for manipulating unicode codepoints */ +typedef uint32_t codepoint_t; + +#define INVALID_CODEPOINT ((codepoint_t)-1) + +/* generic iconv conversion structure */ +typedef struct smb_iconv_s { + size_t (*direct)(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + size_t (*pull)(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + size_t (*push)(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + void *cd_direct, *cd_pull, *cd_push; + char *from_name, *to_name; +} *smb_iconv_t; + +/* string manipulation flags */ +#define STR_TERMINATE 1 +#define STR_UPPER 2 +#define STR_ASCII 4 +#define STR_UNICODE 8 +#define STR_NOALIGN 16 +#define STR_NO_RANGE_CHECK 32 +#define STR_LEN8BIT 64 +#define STR_TERMINATE_ASCII 128 /* only terminate if ascii */ +#define STR_LEN_NOTERM 256 /* the length field is the unterminated length */ + +struct loadparm_context; +struct smb_iconv_handle; + +size_t ucs2_align(const void *base_ptr, const void *p, int flags); + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +**/ +size_t utf16_len(const void *buf); + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination +**/ +size_t utf16_null_terminated_len(const void *buf); + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +limited by 'n' bytes +**/ +size_t utf16_len_n(const void *src, size_t n); + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination +limited by 'n' bytes +**/ +size_t utf16_null_terminated_len_n(const void *src, size_t n); + +unsigned char *talloc_utf16_strlendup(TALLOC_CTX *mem_ctx, const char *str, size_t len); +unsigned char *talloc_utf16_strdup(TALLOC_CTX *mem_ctx, const char *str); +unsigned char *talloc_utf16_strndup(TALLOC_CTX *mem_ctx, const char *str, size_t n); + +char *strchr_m(const char *s, char c); +/** + * Calculate the number of units (8 or 16-bit, depending on the + * destination charset) that would be needed to convert the input + * string, which is expected to be in src_charset encoding, to the + * destination charset (which should be a unicode charset). + */ +size_t strlen_m_ext_handle(struct smb_iconv_handle *ic, + const char *s, charset_t src_charset, charset_t dst_charset); +size_t strlen_m_ext(const char *s, charset_t src_charset, charset_t dst_charset); +size_t strlen_m_ext_term(const char *s, charset_t src_charset, + charset_t dst_charset); +size_t strlen_m_ext_term_null(const char *s, + charset_t src_charset, + charset_t dst_charset); +size_t strlen_m(const char *s); +size_t strlen_m_term(const char *s); +size_t strlen_m_term_null(const char *s); +char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength); +char *talloc_alpha_strcpy(TALLOC_CTX *mem_ctx, + const char *src, + const char *other_safe_chars); +void string_replace_m(char *s, char oldc, char newc); +bool strcsequal(const char *s1,const char *s2); +bool strequal_m(const char *s1, const char *s2); +int strncasecmp_m(const char *s1, const char *s2, size_t n); +int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle, + const char *s1, const char *s2, size_t n); +bool next_token(const char **ptr,char *buff, const char *sep, size_t bufsize); +int strcasecmp_m_handle(struct smb_iconv_handle *iconv_handle, + const char *s1, const char *s2); +int strcasecmp_m(const char *s1, const char *s2); +size_t count_chars_m(const char *s, char c); +char *strupper_talloc(TALLOC_CTX *ctx, const char *src); +char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *src); +char *strupper_talloc_n_handle(struct smb_iconv_handle *iconv_handle, + TALLOC_CTX *ctx, const char *src, size_t n); +char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n); + char *strlower_talloc_handle(struct smb_iconv_handle *iconv_handle, + TALLOC_CTX *ctx, const char *src); +char *strlower_talloc(TALLOC_CTX *ctx, const char *src); +bool strhasupper(const char *string); +bool strhaslower_handle(struct smb_iconv_handle *ic, + const char *string); +bool strhaslower(const char *string); +bool strhasupper_handle(struct smb_iconv_handle *ic, + const char *string); +char *strrchr_m(const char *s, char c); +char *strchr_m(const char *s, char c); +char *strstr_m(const char *src, const char *findstr); + +bool utf8_check(const char *input, size_t maxlen, + size_t *byte_len, + size_t *char_len, + size_t *utf16_len); + +bool push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size); +bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src, size_t *converted_size); +bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size); +bool pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size); +bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src, size_t *converted_size); +bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size); +ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags); +ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags); + +bool convert_string_talloc(TALLOC_CTX *ctx, + charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t *converted_size); + +bool convert_string(charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen, + size_t *converted_size); +bool convert_string_error(charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen, + size_t *converted_size); + +struct smb_iconv_handle *get_iconv_handle(void); +struct smb_iconv_handle *get_iconv_testing_handle(TALLOC_CTX *mem_ctx, + const char *dos_charset, + const char *unix_charset, + bool use_builtin_handlers); +struct smb_iconv_handle *reinit_iconv_handle(TALLOC_CTX *mem_ctx, + const char *dos_charset, + const char *unix_charset); +void free_iconv_handle(void); + +smb_iconv_t get_conv_handle(struct smb_iconv_handle *ic, + charset_t from, charset_t to); +const char *charset_name(struct smb_iconv_handle *ic, charset_t ch); + +codepoint_t next_codepoint_ext(const char *str, size_t len, + charset_t src_charset, size_t *size); +codepoint_t next_codepoint(const char *str, size_t *size); +ssize_t push_codepoint(char *str, codepoint_t c); + +/* codepoints */ +codepoint_t next_codepoint_handle_ext(struct smb_iconv_handle *ic, + const char *str, size_t len, + charset_t src_charset, + size_t *size); +codepoint_t next_codepoint_handle(struct smb_iconv_handle *ic, + const char *str, size_t *size); +ssize_t push_codepoint_handle(struct smb_iconv_handle *ic, + char *str, codepoint_t c); + +codepoint_t toupper_m(codepoint_t val); +codepoint_t tolower_m(codepoint_t val); +bool islower_m(codepoint_t val); +bool isupper_m(codepoint_t val); +int codepoint_cmpi(codepoint_t c1, codepoint_t c2); + +/* Iconv convenience functions */ +struct smb_iconv_handle *smb_iconv_handle_reinit(TALLOC_CTX *mem_ctx, + const char *dos_charset, + const char *unix_charset, + bool use_builtin_handlers, + struct smb_iconv_handle *old_ic); + +bool convert_string_handle(struct smb_iconv_handle *ic, + charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen, size_t *converted_size); +bool convert_string_error_handle(struct smb_iconv_handle *ic, + charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen, + size_t *converted_size); + +bool convert_string_talloc_handle(TALLOC_CTX *ctx, + struct smb_iconv_handle *ic, + charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t *converted_size); +/* iconv */ +smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode); +int smb_iconv_close(smb_iconv_t cd); +size_t smb_iconv(smb_iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); +smb_iconv_t smb_iconv_open_ex(TALLOC_CTX *mem_ctx, const char *tocode, + const char *fromcode, bool use_builtin_handlers); + +void smb_init_locale(void); + +/* The following definitions come from util_unistr_w.c */ + +size_t strlen_w(const smb_ucs2_t *src); +size_t strnlen_w(const smb_ucs2_t *src, size_t max); +smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c); +smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c); +smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c); +smb_ucs2_t *strnrchr_w(const smb_ucs2_t *s, smb_ucs2_t c, unsigned int n); +smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins); +bool strlower_w(smb_ucs2_t *s); +bool strupper_w(smb_ucs2_t *s); +int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b); +int strncasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len); +int strcmp_wa(const smb_ucs2_t *a, const char *b); +smb_ucs2_t toupper_w(smb_ucs2_t v); + +#endif /* __CHARSET_H__ */ diff --git a/lib/util/charset/charset_macosxfs.c b/lib/util/charset/charset_macosxfs.c new file mode 100644 index 0000000..2ecfdff --- /dev/null +++ b/lib/util/charset/charset_macosxfs.c @@ -0,0 +1,605 @@ +/* + Unix SMB/CIFS implementation. + Samba charset module for Mac OS X/Darwin + Copyright (C) Benjamin Riefenstahl 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * modules/charset_macosxfs.c + * + * A Samba charset module to use on Mac OS X/Darwin as the filesystem + * and display encoding. + * + * Actually two implementations are provided here. The default + * implementation is based on the official CFString API. The other is + * based on internal CFString APIs as defined in the OpenDarwin + * source. + */ + +#include "replace.h" +#include "charset.h" +#include "charset_proto.h" +#include "lib/util/debug.h" +#undef realloc + +#ifdef DARWINOS + +/* + * Include OS frameworks. These are only needed in this module. + */ +#include <CoreFoundation/CFString.h> + +/* + * See if autoconf has found us the internal headers in some form. + */ +#if defined(HAVE_COREFOUNDATION_CFSTRINGENCODINGCONVERTER_H) +# include <CoreFoundation/CFStringEncodingConverter.h> +# include <CoreFoundation/CFUnicodePrecomposition.h> +# define USE_INTERNAL_API 1 +#elif defined(HAVE_CFSTRINGENCODINGCONVERTER_H) +# include <CFStringEncodingConverter.h> +# include <CFUnicodePrecomposition.h> +# define USE_INTERNAL_API 1 +#endif + +/* + * Compile time configuration: Do we want debug output? + */ +/* #define DEBUG_STRINGS 1 */ + +/* + * A simple, but efficient memory provider for our buffers. + */ +static inline void *resize_buffer (void *buffer, size_t *size, size_t newsize) +{ + if (newsize > *size) { + *size = newsize + 128; + buffer = realloc(buffer, *size); + } + return buffer; +} + +/* + * While there is a version of OpenDarwin for intel, the usual case is + * big-endian PPC. So we need byte swapping to handle the + * little-endian byte order of the network protocol. We also need an + * additional dynamic buffer to do this work for incoming data blocks, + * because we have to consider the original data as constant. + * + * We abstract the differences away by providing a simple facade with + * these functions/macros: + * + * le_to_native(dst,src,len) + * native_to_le(cp,len) + * set_ucbuffer_with_le(buffer,bufsize,data,size) + * set_ucbuffer_with_le_copy(buffer,bufsize,data,size,reserve) + */ +#ifdef WORDS_BIGENDIAN + +static inline void swap_bytes (char * dst, const char * src, size_t len) +{ + const char *srcend = src + len; + while (src < srcend) { + dst[0] = src[1]; + dst[1] = src[0]; + dst += 2; + src += 2; + } +} +static inline void swap_bytes_inplace (char * cp, size_t len) +{ + char temp; + char *end = cp + len; + while (cp < end) { + temp = cp[1]; + cp[1] = cp[0]; + cp[0] = temp; + cp += 2; + } +} + +#define le_to_native(dst,src,len) swap_bytes(dst,src,len) +#define native_to_le(cp,len) swap_bytes_inplace(cp,len) +#define set_ucbuffer_with_le(buffer,bufsize,data,size) \ + set_ucbuffer_with_le_copy(buffer,bufsize,data,size,0) + +#else /* ! WORDS_BIGENDIAN */ + +#define le_to_native(dst,src,len) memcpy(dst,src,len) +#define native_to_le(cp,len) /* nothing */ +#define set_ucbuffer_with_le(buffer,bufsize,data,size) \ + (((void)(bufsize)),(UniChar*)(data)) + +#endif + +static inline UniChar *set_ucbuffer_with_le_copy ( + UniChar *buffer, size_t *bufsize, + const void *data, size_t size, size_t reserve) +{ + buffer = resize_buffer(buffer, bufsize, size+reserve); + le_to_native((char*)buffer,data,size); + return buffer; +} + + +/* + * A simple hexdump function for debugging error conditions. + */ +#define debug_out(s) DEBUG(0,(s)) + +#ifdef DEBUG_STRINGS + +static void hexdump( const char * label, const char * s, size_t len ) +{ + size_t restlen = len; + debug_out("<<<<<<<\n"); + debug_out(label); + debug_out("\n"); + while (restlen > 0) { + char line[100]; + size_t i, j; + char * d = line; +#undef sprintf + d += sprintf(d, "%04X ", (unsigned)(len-restlen)); + *d++ = ' '; + for( i = 0; i<restlen && i<8; ++i ) { + d += sprintf(d, "%02X ", ((unsigned)s[i]) & 0xFF); + } + for( j = i; j<8; ++j ) { + d += sprintf(d, " "); + } + *d++ = ' '; + for( i = 8; i<restlen && i<16; ++i ) { + d += sprintf(d, "%02X ", ((unsigned)s[i]) & 0xFF); + } + for( j = i; j<16; ++j ) { + d += sprintf(d, " "); + } + *d++ = ' '; + for( i = 0; i<restlen && i<16; ++i ) { + if(s[i] < ' ' || s[i] >= 0x7F || !isprint(s[i])) + *d++ = '.'; + else + *d++ = s[i]; + } + *d++ = '\n'; + *d = 0; + restlen -= i; + s += i; + debug_out(line); + } + debug_out(">>>>>>>\n"); +} + +#else /* !DEBUG_STRINGS */ + +#define hexdump(label,s,len) /* nothing */ + +#endif + + +#if !USE_INTERNAL_API + +/* + * An implementation based on documented Mac OS X APIs. + * + * This does a certain amount of memory management, creating and + * manipulating CFString objects. We try to minimize the impact by + * keeping those objects around and re-using them. We also use + * external backing store for the CFStrings where this is possible and + * benficial. + * + * The Unicode normalizations forms available at this level are + * generic, not specifically for the file system. So they may not be + * perfect fits. + */ +size_t macosxfs_encoding_pull( + void *cd, /* Encoder handle */ + const char **inbuf, size_t *inbytesleft, /* Script string */ + char **outbuf, size_t *outbytesleft) /* UTF-16-LE string */ +{ + static const int script_code = kCFStringEncodingUTF8; + static CFMutableStringRef cfstring = NULL; + size_t outsize; + CFRange range; + + (void) cd; /* UNUSED */ + + if (0 == *inbytesleft) { + return 0; + } + + if (NULL == cfstring) { + /* + * A version with an external backing store as in the + * push function should have been more efficient, but + * testing shows, that it is actually slower (!). + * Maybe kCFAllocatorDefault gets shortcut evaluation + * internally, while kCFAllocatorNull doesn't. + */ + cfstring = CFStringCreateMutable(kCFAllocatorDefault,0); + } + + /* + * Three methods of appending to a CFString, choose the most + * efficient. + */ + if (0 == (*inbuf)[*inbytesleft-1]) { + CFStringAppendCString(cfstring, *inbuf, script_code); + } else if (*inbytesleft <= 255) { + Str255 buffer; + buffer[0] = *inbytesleft; + memcpy(buffer+1, *inbuf, buffer[0]); + CFStringAppendPascalString(cfstring, buffer, script_code); + } else { + /* + * We would like to use a fixed buffer and a loop + * here, but then we can't guarantee that the input is + * well-formed UTF-8, as we are supposed to do. + */ + static char *buffer = NULL; + static size_t buflen = 0; + buffer = resize_buffer(buffer, &buflen, *inbytesleft+1); + memcpy(buffer, *inbuf, *inbytesleft); + buffer[*inbytesleft] = 0; + CFStringAppendCString(cfstring, *inbuf, script_code); + } + + /* + * Compose characters, using the non-canonical composition + * form. + */ + CFStringNormalize(cfstring, kCFStringNormalizationFormC); + + outsize = CFStringGetLength(cfstring); + range = CFRangeMake(0,outsize); + + if (outsize == 0) { + /* + * HACK: smbd/mangle_hash2.c:is_legal_name() expects + * errors here. That function will always pass 2 + * characters. smbd/open.c:check_for_pipe() cuts a + * patchname to 10 characters blindly. Suppress the + * debug output in those cases. + */ + if(2 != *inbytesleft && 10 != *inbytesleft) { + debug_out("String conversion: " + "An unknown error occurred\n"); + hexdump("UTF8->UTF16LE (old) input", + *inbuf, *inbytesleft); + } + errno = EILSEQ; /* Not sure, but this is what we have + * actually seen. */ + return -1; + } + if (outsize*2 > *outbytesleft) { + CFStringDelete(cfstring, range); + debug_out("String conversion: " + "Output buffer too small\n"); + hexdump("UTF8->UTF16LE (old) input", + *inbuf, *inbytesleft); + errno = E2BIG; + return -1; + } + + CFStringGetCharacters(cfstring, range, (UniChar*)*outbuf); + CFStringDelete(cfstring, range); + + native_to_le(*outbuf, outsize*2); + + /* + * Add a converted null byte, if the CFString conversions + * prevented that until now. + */ + if (0 == (*inbuf)[*inbytesleft-1] && + (0 != (*outbuf)[outsize*2-1] || 0 != (*outbuf)[outsize*2-2])) { + + if ((outsize*2+2) > *outbytesleft) { + debug_out("String conversion: " + "Output buffer too small\n"); + hexdump("UTF8->UTF16LE (old) input", + *inbuf, *inbytesleft); + errno = E2BIG; + return -1; + } + + (*outbuf)[outsize*2] = (*outbuf)[outsize*2+1] = 0; + outsize += 2; + } + + *inbuf += *inbytesleft; + *inbytesleft = 0; + *outbuf += outsize*2; + *outbytesleft -= outsize*2; + + return 0; +} + +size_t macosxfs_encoding_push( + void *cd, /* Encoder handle */ + const char **inbuf, size_t *inbytesleft, /* UTF-16-LE string */ + char **outbuf, size_t *outbytesleft) /* Script string */ +{ + static const int script_code = kCFStringEncodingUTF8; + static CFMutableStringRef cfstring = NULL; + static UniChar *buffer = NULL; + static size_t buflen = 0; + CFIndex outsize, cfsize, charsconverted; + + (void) cd; /* UNUSED */ + + if (0 == *inbytesleft) { + return 0; + } + + /* + * We need a buffer that can hold 4 times the original data, + * because that is the theoretical maximum that decomposition + * can create currently (in Unicode 4.0). + */ + buffer = set_ucbuffer_with_le_copy( + buffer, &buflen, *inbuf, *inbytesleft, 3 * *inbytesleft); + + if (NULL == cfstring) { + cfstring = CFStringCreateMutableWithExternalCharactersNoCopy( + kCFAllocatorDefault, + buffer, *inbytesleft/2, buflen/2, + kCFAllocatorNull); + } else { + CFStringSetExternalCharactersNoCopy( + cfstring, + buffer, *inbytesleft/2, buflen/2); + } + + /* + * Decompose characters, using the non-canonical decomposition + * form. + * + * NB: This isn't exactly what HFS+ wants (see note on + * kCFStringEncodingUseHFSPlusCanonical in + * CFStringEncodingConverter.h), but AFAIK it's the best that + * the official API can do. + */ + CFStringNormalize(cfstring, kCFStringNormalizationFormD); + + cfsize = CFStringGetLength(cfstring); + charsconverted = CFStringGetBytes( + cfstring, CFRangeMake(0,cfsize), + script_code, 0, false, + *(UInt8 **)outbuf, *outbytesleft, &outsize); + + if (0 == charsconverted) { + debug_out("String conversion: " + "Buffer too small or not convertible\n"); + hexdump("UTF16LE->UTF8 (old) input", + *inbuf, *inbytesleft); + errno = EILSEQ; /* Probably more likely. */ + return -1; + } + + /* + * Add a converted null byte, if the CFString conversions + * prevented that until now. + */ + if (0 == (*inbuf)[*inbytesleft-1] && 0 == (*inbuf)[*inbytesleft-2] && + (0 != (*outbuf)[outsize-1])) { + + if (((size_t)outsize+1) > *outbytesleft) { + debug_out("String conversion: " + "Output buffer too small\n"); + hexdump("UTF16LE->UTF8 (old) input", + *inbuf, *inbytesleft); + errno = E2BIG; + return -1; + } + + (*outbuf)[outsize] = 0; + ++outsize; + } + + *inbuf += *inbytesleft; + *inbytesleft = 0; + *outbuf += outsize; + *outbytesleft -= outsize; + + return 0; +} + +#else /* USE_INTERNAL_API */ + +/* + * An implementation based on internal code as known from the + * OpenDarwin CVS. + * + * This code doesn't need much memory management because it uses + * functions that operate on the raw memory directly. + * + * The push routine here is faster and more compatible with HFS+ than + * the other implementation above. The pull routine is only faster + * for some strings, slightly slower for others. The pull routine + * looses because it has to iterate over the data twice, once to + * decode UTF-8 and than to do the character composition required by + * Windows. + */ +static size_t macosxfs_encoding_pull( + void *cd, /* Encoder handle */ + const char **inbuf, size_t *inbytesleft, /* Script string */ + char **outbuf, size_t *outbytesleft) /* UTF-16-LE string */ +{ + static const int script_code = kCFStringEncodingUTF8; + UInt32 srcCharsUsed = 0; + UInt32 dstCharsUsed = 0; + UInt32 result; + uint32_t dstDecomposedUsed = 0; + uint32_t dstPrecomposedUsed = 0; + + (void) cd; /* UNUSED */ + + if (0 == *inbytesleft) { + return 0; + } + + result = CFStringEncodingBytesToUnicode( + script_code, kCFStringEncodingComposeCombinings, + *inbuf, *inbytesleft, &srcCharsUsed, + (UniChar*)*outbuf, *outbytesleft, &dstCharsUsed); + + switch(result) { + case kCFStringEncodingConversionSuccess: + if (*inbytesleft == srcCharsUsed) { + break; + } + + FALL_THROUGH; + case kCFStringEncodingInsufficientOutputBufferLength: + debug_out("String conversion: " + "Output buffer too small\n"); + hexdump("UTF8->UTF16LE (new) input", + *inbuf, *inbytesleft); + errno = E2BIG; + return -1; + case kCFStringEncodingInvalidInputStream: + /* + * HACK: smbd/mangle_hash2.c:is_legal_name() expects + * errors here. That function will always pass 2 + * characters. smbd/open.c:check_for_pipe() cuts a + * patchname to 10 characters blindly. Suppress the + * debug output in those cases. + */ + if(2 != *inbytesleft && 10 != *inbytesleft) { + debug_out("String conversion: " + "Invalid input sequence\n"); + hexdump("UTF8->UTF16LE (new) input", + *inbuf, *inbytesleft); + } + errno = EILSEQ; + return -1; + case kCFStringEncodingConverterUnavailable: + debug_out("String conversion: " + "Unknown encoding\n"); + hexdump("UTF8->UTF16LE (new) input", + *inbuf, *inbytesleft); + errno = EINVAL; + return -1; + } + + /* + * It doesn't look like CFStringEncodingBytesToUnicode() can + * produce precomposed characters (flags=ComposeCombinings + * doesn't do it), so we need another pass over the data here. + * We can do this in-place, as the string can only get + * shorter. + * + * (Actually in theory there should be an internal + * decomposition and reordering before the actual composition + * step. But we should be able to rely on that we always get + * fully decomposed strings for input, so this can't create + * problems in reality.) + */ + CFUniCharPrecompose( + (const UTF16Char *)*outbuf, dstCharsUsed, &dstDecomposedUsed, + (UTF16Char *)*outbuf, dstCharsUsed, &dstPrecomposedUsed); + + native_to_le(*outbuf, dstPrecomposedUsed*2); + + *inbuf += srcCharsUsed; + *inbytesleft -= srcCharsUsed; + *outbuf += dstPrecomposedUsed*2; + *outbytesleft -= dstPrecomposedUsed*2; + + return 0; +} + +static size_t macosxfs_encoding_push( + void *cd, /* Encoder handle */ + const char **inbuf, size_t *inbytesleft, /* UTF-16-LE string */ + char **outbuf, size_t *outbytesleft) /* Script string */ +{ + static const int script_code = kCFStringEncodingUTF8; + static UniChar *buffer = NULL; + static size_t buflen = 0; + UInt32 srcCharsUsed=0, dstCharsUsed=0, result; + + (void) cd; /* UNUSED */ + + if (0 == *inbytesleft) { + return 0; + } + + buffer = set_ucbuffer_with_le( + buffer, &buflen, *inbuf, *inbytesleft); + + result = CFStringEncodingUnicodeToBytes( + script_code, kCFStringEncodingUseHFSPlusCanonical, + buffer, *inbytesleft/2, &srcCharsUsed, + *outbuf, *outbytesleft, &dstCharsUsed); + + switch(result) { + case kCFStringEncodingConversionSuccess: + if (*inbytesleft/2 == srcCharsUsed) { + break; + } + + FALL_THROUGH; + case kCFStringEncodingInsufficientOutputBufferLength: + debug_out("String conversion: " + "Output buffer too small\n"); + hexdump("UTF16LE->UTF8 (new) input", + *inbuf, *inbytesleft); + errno = E2BIG; + return -1; + case kCFStringEncodingInvalidInputStream: + /* + * HACK: smbd/open.c:check_for_pipe():is_legal_name() + * cuts a pathname to 10 characters blindly. Suppress + * the debug output in those cases. + */ + if(10 != *inbytesleft) { + debug_out("String conversion: " + "Invalid input sequence\n"); + hexdump("UTF16LE->UTF8 (new) input", + *inbuf, *inbytesleft); + } + errno = EILSEQ; + return -1; + case kCFStringEncodingConverterUnavailable: + debug_out("String conversion: " + "Unknown encoding\n"); + hexdump("UTF16LE->UTF8 (new) input", + *inbuf, *inbytesleft); + errno = EINVAL; + return -1; + } + + *inbuf += srcCharsUsed*2; + *inbytesleft -= srcCharsUsed*2; + *outbuf += dstCharsUsed; + *outbytesleft -= dstCharsUsed; + + return 0; +} + +#endif /* USE_INTERNAL_API */ + +#else /* DARWIN */ + +void charset_macosfs_dummy(void); +void charset_macosfs_dummy(void) +{ + return; +} + +#endif /* DARWIN */ diff --git a/lib/util/charset/charset_proto.h b/lib/util/charset/charset_proto.h new file mode 100644 index 0000000..6da7118 --- /dev/null +++ b/lib/util/charset/charset_proto.h @@ -0,0 +1,36 @@ +/* + Unix SMB/CIFS implementation. + Samba charset modules + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002 + Copyright (C) Benjamin Riefenstahl 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +size_t weird_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); +size_t weird_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + +size_t macosxfs_encoding_pull( + void *cd, /* Encoder handle */ + const char **inbuf, size_t *inbytesleft, /* Script string */ + char **outbuf, size_t *outbytesleft); /* UTF-16-LE string */ +size_t macosxfs_encoding_push( + void *cd, /* Encoder handle */ + const char **inbuf, size_t *inbytesleft, /* UTF-16-LE string */ + char **outbuf, size_t *outbytesleft); /* Script string */ + + diff --git a/lib/util/charset/codepoints.c b/lib/util/charset/codepoints.c new file mode 100644 index 0000000..ea2c4be --- /dev/null +++ b/lib/util/charset/codepoints.c @@ -0,0 +1,16850 @@ +/* + Unix SMB/CIFS implementation. + Character set conversion Extensions + Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001 + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Simo Sorce 2001 + Copyright (C) Jelmer Vernooij 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ +#include "replace.h" +#include "lib/util/charset/charset.h" +#include "system/locale.h" +#include "dynconfig/dynconfig.h" +#include "lib/util/debug.h" +#include "lib/util/byteorder.h" + +#ifdef strcasecmp +#undef strcasecmp +#endif + +/** + * @file + * @brief Unicode string manipulation + */ + +static const uint16_t lowcase_table[] = { + 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, + 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, + 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, + 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, + 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, + 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, + 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, + 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, + 0x0040,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, + 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, + 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, + 0x0078,0x0079,0x007a,0x005b,0x005c,0x005d,0x005e,0x005f, + 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, + 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, + 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, + 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, + 0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087, + 0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f, + 0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097, + 0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f, + 0x00a0,0x00a1,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7, + 0x00a8,0x00a9,0x00aa,0x00ab,0x00ac,0x00ad,0x00ae,0x00af, + 0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7, + 0x00b8,0x00b9,0x00ba,0x00bb,0x00bc,0x00bd,0x00be,0x00bf, + 0x00e0,0x00e1,0x00e2,0x00e3,0x00e4,0x00e5,0x00e6,0x00e7, + 0x00e8,0x00e9,0x00ea,0x00eb,0x00ec,0x00ed,0x00ee,0x00ef, + 0x00f0,0x00f1,0x00f2,0x00f3,0x00f4,0x00f5,0x00f6,0x00d7, + 0x00f8,0x00f9,0x00fa,0x00fb,0x00fc,0x00fd,0x00fe,0x00df, + 0x00e0,0x00e1,0x00e2,0x00e3,0x00e4,0x00e5,0x00e6,0x00e7, + 0x00e8,0x00e9,0x00ea,0x00eb,0x00ec,0x00ed,0x00ee,0x00ef, + 0x00f0,0x00f1,0x00f2,0x00f3,0x00f4,0x00f5,0x00f6,0x00f7, + 0x00f8,0x00f9,0x00fa,0x00fb,0x00fc,0x00fd,0x00fe,0x00ff, + 0x0101,0x0101,0x0103,0x0103,0x0105,0x0105,0x0107,0x0107, + 0x0109,0x0109,0x010b,0x010b,0x010d,0x010d,0x010f,0x010f, + 0x0111,0x0111,0x0113,0x0113,0x0115,0x0115,0x0117,0x0117, + 0x0119,0x0119,0x011b,0x011b,0x011d,0x011d,0x011f,0x011f, + 0x0121,0x0121,0x0123,0x0123,0x0125,0x0125,0x0127,0x0127, + 0x0129,0x0129,0x012b,0x012b,0x012d,0x012d,0x012f,0x012f, + 0x0130,0x0131,0x0133,0x0133,0x0135,0x0135,0x0137,0x0137, + 0x0138,0x013a,0x013a,0x013c,0x013c,0x013e,0x013e,0x0140, + 0x0140,0x0142,0x0142,0x0144,0x0144,0x0146,0x0146,0x0148, + 0x0148,0x0149,0x014b,0x014b,0x014d,0x014d,0x014f,0x014f, + 0x0151,0x0151,0x0153,0x0153,0x0155,0x0155,0x0157,0x0157, + 0x0159,0x0159,0x015b,0x015b,0x015d,0x015d,0x015f,0x015f, + 0x0161,0x0161,0x0163,0x0163,0x0165,0x0165,0x0167,0x0167, + 0x0169,0x0169,0x016b,0x016b,0x016d,0x016d,0x016f,0x016f, + 0x0171,0x0171,0x0173,0x0173,0x0175,0x0175,0x0177,0x0177, + 0x00ff,0x017a,0x017a,0x017c,0x017c,0x017e,0x017e,0x017f, + 0x0180,0x0253,0x0183,0x0183,0x0185,0x0185,0x0254,0x0188, + 0x0188,0x0256,0x0257,0x018c,0x018c,0x018d,0x01dd,0x0259, + 0x025b,0x0192,0x0192,0x0260,0x0263,0x0195,0x0269,0x0268, + 0x0199,0x0199,0x019a,0x019b,0x026f,0x0272,0x019e,0x0275, + 0x01a1,0x01a1,0x01a3,0x01a3,0x01a5,0x01a5,0x01a6,0x01a8, + 0x01a8,0x0283,0x01aa,0x01ab,0x01ad,0x01ad,0x0288,0x01b0, + 0x01b0,0x028a,0x028b,0x01b4,0x01b4,0x01b6,0x01b6,0x0292, + 0x01b9,0x01b9,0x01ba,0x01bb,0x01bd,0x01bd,0x01be,0x01bf, + 0x01c0,0x01c1,0x01c2,0x01c3,0x01c6,0x01c5,0x01c6,0x01c9, + 0x01c8,0x01c9,0x01cc,0x01cb,0x01cc,0x01ce,0x01ce,0x01d0, + 0x01d0,0x01d2,0x01d2,0x01d4,0x01d4,0x01d6,0x01d6,0x01d8, + 0x01d8,0x01da,0x01da,0x01dc,0x01dc,0x01dd,0x01df,0x01df, + 0x01e1,0x01e1,0x01e3,0x01e3,0x01e5,0x01e5,0x01e7,0x01e7, + 0x01e9,0x01e9,0x01eb,0x01eb,0x01ed,0x01ed,0x01ef,0x01ef, + 0x01f0,0x01f3,0x01f2,0x01f3,0x01f5,0x01f5,0x01f6,0x01f7, + 0x01f8,0x01f9,0x01fb,0x01fb,0x01fd,0x01fd,0x01ff,0x01ff, + 0x0201,0x0201,0x0203,0x0203,0x0205,0x0205,0x0207,0x0207, + 0x0209,0x0209,0x020b,0x020b,0x020d,0x020d,0x020f,0x020f, + 0x0211,0x0211,0x0213,0x0213,0x0215,0x0215,0x0217,0x0217, + 0x0218,0x0219,0x021a,0x021b,0x021c,0x021d,0x021e,0x021f, + 0x0220,0x0221,0x0222,0x0223,0x0224,0x0225,0x0226,0x0227, + 0x0228,0x0229,0x022a,0x022b,0x022c,0x022d,0x022e,0x022f, + 0x0230,0x0231,0x0232,0x0233,0x0234,0x0235,0x0236,0x0237, + 0x0238,0x0239,0x023a,0x023b,0x023c,0x023d,0x023e,0x023f, + 0x0240,0x0241,0x0242,0x0243,0x0244,0x0245,0x0246,0x0247, + 0x0248,0x0249,0x024a,0x024b,0x024c,0x024d,0x024e,0x024f, + 0x0250,0x0251,0x0252,0x0253,0x0254,0x0255,0x0256,0x0257, + 0x0258,0x0259,0x025a,0x025b,0x025c,0x025d,0x025e,0x025f, + 0x0260,0x0261,0x0262,0x0263,0x0264,0x0265,0x0266,0x0267, + 0x0268,0x0269,0x026a,0x026b,0x026c,0x026d,0x026e,0x026f, + 0x0270,0x0271,0x0272,0x0273,0x0274,0x0275,0x0276,0x0277, + 0x0278,0x0279,0x027a,0x027b,0x027c,0x027d,0x027e,0x027f, + 0x0280,0x0281,0x0282,0x0283,0x0284,0x0285,0x0286,0x0287, + 0x0288,0x0289,0x028a,0x028b,0x028c,0x028d,0x028e,0x028f, + 0x0290,0x0291,0x0292,0x0293,0x0294,0x0295,0x0296,0x0297, + 0x0298,0x0299,0x029a,0x029b,0x029c,0x029d,0x029e,0x029f, + 0x02a0,0x02a1,0x02a2,0x02a3,0x02a4,0x02a5,0x02a6,0x02a7, + 0x02a8,0x02a9,0x02aa,0x02ab,0x02ac,0x02ad,0x02ae,0x02af, + 0x02b0,0x02b1,0x02b2,0x02b3,0x02b4,0x02b5,0x02b6,0x02b7, + 0x02b8,0x02b9,0x02ba,0x02bb,0x02bc,0x02bd,0x02be,0x02bf, + 0x02c0,0x02c1,0x02c2,0x02c3,0x02c4,0x02c5,0x02c6,0x02c7, + 0x02c8,0x02c9,0x02ca,0x02cb,0x02cc,0x02cd,0x02ce,0x02cf, + 0x02d0,0x02d1,0x02d2,0x02d3,0x02d4,0x02d5,0x02d6,0x02d7, + 0x02d8,0x02d9,0x02da,0x02db,0x02dc,0x02dd,0x02de,0x02df, + 0x02e0,0x02e1,0x02e2,0x02e3,0x02e4,0x02e5,0x02e6,0x02e7, + 0x02e8,0x02e9,0x02ea,0x02eb,0x02ec,0x02ed,0x02ee,0x02ef, + 0x02f0,0x02f1,0x02f2,0x02f3,0x02f4,0x02f5,0x02f6,0x02f7, + 0x02f8,0x02f9,0x02fa,0x02fb,0x02fc,0x02fd,0x02fe,0x02ff, + 0x0300,0x0301,0x0302,0x0303,0x0304,0x0305,0x0306,0x0307, + 0x0308,0x0309,0x030a,0x030b,0x030c,0x030d,0x030e,0x030f, + 0x0310,0x0311,0x0312,0x0313,0x0314,0x0315,0x0316,0x0317, + 0x0318,0x0319,0x031a,0x031b,0x031c,0x031d,0x031e,0x031f, + 0x0320,0x0321,0x0322,0x0323,0x0324,0x0325,0x0326,0x0327, + 0x0328,0x0329,0x032a,0x032b,0x032c,0x032d,0x032e,0x032f, + 0x0330,0x0331,0x0332,0x0333,0x0334,0x0335,0x0336,0x0337, + 0x0338,0x0339,0x033a,0x033b,0x033c,0x033d,0x033e,0x033f, + 0x0340,0x0341,0x0342,0x0343,0x0344,0x0345,0x0346,0x0347, + 0x0348,0x0349,0x034a,0x034b,0x034c,0x034d,0x034e,0x034f, + 0x0350,0x0351,0x0352,0x0353,0x0354,0x0355,0x0356,0x0357, + 0x0358,0x0359,0x035a,0x035b,0x035c,0x035d,0x035e,0x035f, + 0x0360,0x0361,0x0362,0x0363,0x0364,0x0365,0x0366,0x0367, + 0x0368,0x0369,0x036a,0x036b,0x036c,0x036d,0x036e,0x036f, + 0x0370,0x0371,0x0372,0x0373,0x0374,0x0375,0x0376,0x0377, + 0x0378,0x0379,0x037a,0x037b,0x037c,0x037d,0x037e,0x037f, + 0x0380,0x0381,0x0382,0x0383,0x0384,0x0385,0x03ac,0x0387, + 0x03ad,0x03ae,0x03af,0x038b,0x03cc,0x038d,0x03cd,0x03ce, + 0x0390,0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6,0x03b7, + 0x03b8,0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf, + 0x03c0,0x03c1,0x03a2,0x03c3,0x03c4,0x03c5,0x03c6,0x03c7, + 0x03c8,0x03c9,0x03ca,0x03cb,0x03ac,0x03ad,0x03ae,0x03af, + 0x03b0,0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6,0x03b7, + 0x03b8,0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf, + 0x03c0,0x03c1,0x03c2,0x03c3,0x03c4,0x03c5,0x03c6,0x03c7, + 0x03c8,0x03c9,0x03ca,0x03cb,0x03cc,0x03cd,0x03ce,0x03cf, + 0x03d0,0x03d1,0x03d2,0x03d3,0x03d4,0x03d5,0x03d6,0x03d7, + 0x03d8,0x03d9,0x03da,0x03db,0x03dc,0x03dd,0x03de,0x03df, + 0x03e0,0x03e1,0x03e3,0x03e3,0x03e5,0x03e5,0x03e7,0x03e7, + 0x03e9,0x03e9,0x03eb,0x03eb,0x03ed,0x03ed,0x03ef,0x03ef, + 0x03f0,0x03f1,0x03f2,0x03f3,0x03f4,0x03f5,0x03f6,0x03f7, + 0x03f8,0x03f9,0x03fa,0x03fb,0x03fc,0x03fd,0x03fe,0x03ff, + 0x0400,0x0451,0x0452,0x0453,0x0454,0x0455,0x0456,0x0457, + 0x0458,0x0459,0x045a,0x045b,0x045c,0x040d,0x045e,0x045f, + 0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437, + 0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f, + 0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447, + 0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f, + 0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437, + 0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f, + 0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447, + 0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f, + 0x0450,0x0451,0x0452,0x0453,0x0454,0x0455,0x0456,0x0457, + 0x0458,0x0459,0x045a,0x045b,0x045c,0x045d,0x045e,0x045f, + 0x0461,0x0461,0x0463,0x0463,0x0465,0x0465,0x0467,0x0467, + 0x0469,0x0469,0x046b,0x046b,0x046d,0x046d,0x046f,0x046f, + 0x0471,0x0471,0x0473,0x0473,0x0475,0x0475,0x0477,0x0477, + 0x0479,0x0479,0x047b,0x047b,0x047d,0x047d,0x047f,0x047f, + 0x0481,0x0481,0x0482,0x0483,0x0484,0x0485,0x0486,0x0487, + 0x0488,0x0489,0x048a,0x048b,0x048c,0x048d,0x048e,0x048f, + 0x0491,0x0491,0x0493,0x0493,0x0495,0x0495,0x0497,0x0497, + 0x0499,0x0499,0x049b,0x049b,0x049d,0x049d,0x049f,0x049f, + 0x04a1,0x04a1,0x04a3,0x04a3,0x04a5,0x04a5,0x04a7,0x04a7, + 0x04a9,0x04a9,0x04ab,0x04ab,0x04ad,0x04ad,0x04af,0x04af, + 0x04b1,0x04b1,0x04b3,0x04b3,0x04b5,0x04b5,0x04b7,0x04b7, + 0x04b9,0x04b9,0x04bb,0x04bb,0x04bd,0x04bd,0x04bf,0x04bf, + 0x04c0,0x04c2,0x04c2,0x04c4,0x04c4,0x04c5,0x04c6,0x04c8, + 0x04c8,0x04c9,0x04ca,0x04cc,0x04cc,0x04cd,0x04ce,0x04cf, + 0x04d1,0x04d1,0x04d3,0x04d3,0x04d5,0x04d5,0x04d7,0x04d7, + 0x04d9,0x04d9,0x04db,0x04db,0x04dd,0x04dd,0x04df,0x04df, + 0x04e1,0x04e1,0x04e3,0x04e3,0x04e5,0x04e5,0x04e7,0x04e7, + 0x04e9,0x04e9,0x04eb,0x04eb,0x04ec,0x04ed,0x04ef,0x04ef, + 0x04f1,0x04f1,0x04f3,0x04f3,0x04f5,0x04f5,0x04f6,0x04f7, + 0x04f9,0x04f9,0x04fa,0x04fb,0x04fc,0x04fd,0x04fe,0x04ff, + 0x0500,0x0501,0x0502,0x0503,0x0504,0x0505,0x0506,0x0507, + 0x0508,0x0509,0x050a,0x050b,0x050c,0x050d,0x050e,0x050f, + 0x0510,0x0511,0x0512,0x0513,0x0514,0x0515,0x0516,0x0517, + 0x0518,0x0519,0x051a,0x051b,0x051c,0x051d,0x051e,0x051f, + 0x0520,0x0521,0x0522,0x0523,0x0524,0x0525,0x0526,0x0527, + 0x0528,0x0529,0x052a,0x052b,0x052c,0x052d,0x052e,0x052f, + 0x0530,0x0561,0x0562,0x0563,0x0564,0x0565,0x0566,0x0567, + 0x0568,0x0569,0x056a,0x056b,0x056c,0x056d,0x056e,0x056f, + 0x0570,0x0571,0x0572,0x0573,0x0574,0x0575,0x0576,0x0577, + 0x0578,0x0579,0x057a,0x057b,0x057c,0x057d,0x057e,0x057f, + 0x0580,0x0581,0x0582,0x0583,0x0584,0x0585,0x0586,0x0557, + 0x0558,0x0559,0x055a,0x055b,0x055c,0x055d,0x055e,0x055f, + 0x0560,0x0561,0x0562,0x0563,0x0564,0x0565,0x0566,0x0567, + 0x0568,0x0569,0x056a,0x056b,0x056c,0x056d,0x056e,0x056f, + 0x0570,0x0571,0x0572,0x0573,0x0574,0x0575,0x0576,0x0577, + 0x0578,0x0579,0x057a,0x057b,0x057c,0x057d,0x057e,0x057f, + 0x0580,0x0581,0x0582,0x0583,0x0584,0x0585,0x0586,0x0587, + 0x0588,0x0589,0x058a,0x058b,0x058c,0x058d,0x058e,0x058f, + 0x0590,0x0591,0x0592,0x0593,0x0594,0x0595,0x0596,0x0597, + 0x0598,0x0599,0x059a,0x059b,0x059c,0x059d,0x059e,0x059f, + 0x05a0,0x05a1,0x05a2,0x05a3,0x05a4,0x05a5,0x05a6,0x05a7, + 0x05a8,0x05a9,0x05aa,0x05ab,0x05ac,0x05ad,0x05ae,0x05af, + 0x05b0,0x05b1,0x05b2,0x05b3,0x05b4,0x05b5,0x05b6,0x05b7, + 0x05b8,0x05b9,0x05ba,0x05bb,0x05bc,0x05bd,0x05be,0x05bf, + 0x05c0,0x05c1,0x05c2,0x05c3,0x05c4,0x05c5,0x05c6,0x05c7, + 0x05c8,0x05c9,0x05ca,0x05cb,0x05cc,0x05cd,0x05ce,0x05cf, + 0x05d0,0x05d1,0x05d2,0x05d3,0x05d4,0x05d5,0x05d6,0x05d7, + 0x05d8,0x05d9,0x05da,0x05db,0x05dc,0x05dd,0x05de,0x05df, + 0x05e0,0x05e1,0x05e2,0x05e3,0x05e4,0x05e5,0x05e6,0x05e7, + 0x05e8,0x05e9,0x05ea,0x05eb,0x05ec,0x05ed,0x05ee,0x05ef, + 0x05f0,0x05f1,0x05f2,0x05f3,0x05f4,0x05f5,0x05f6,0x05f7, + 0x05f8,0x05f9,0x05fa,0x05fb,0x05fc,0x05fd,0x05fe,0x05ff, + 0x0600,0x0601,0x0602,0x0603,0x0604,0x0605,0x0606,0x0607, + 0x0608,0x0609,0x060a,0x060b,0x060c,0x060d,0x060e,0x060f, + 0x0610,0x0611,0x0612,0x0613,0x0614,0x0615,0x0616,0x0617, + 0x0618,0x0619,0x061a,0x061b,0x061c,0x061d,0x061e,0x061f, + 0x0620,0x0621,0x0622,0x0623,0x0624,0x0625,0x0626,0x0627, + 0x0628,0x0629,0x062a,0x062b,0x062c,0x062d,0x062e,0x062f, + 0x0630,0x0631,0x0632,0x0633,0x0634,0x0635,0x0636,0x0637, + 0x0638,0x0639,0x063a,0x063b,0x063c,0x063d,0x063e,0x063f, + 0x0640,0x0641,0x0642,0x0643,0x0644,0x0645,0x0646,0x0647, + 0x0648,0x0649,0x064a,0x064b,0x064c,0x064d,0x064e,0x064f, + 0x0650,0x0651,0x0652,0x0653,0x0654,0x0655,0x0656,0x0657, + 0x0658,0x0659,0x065a,0x065b,0x065c,0x065d,0x065e,0x065f, + 0x0660,0x0661,0x0662,0x0663,0x0664,0x0665,0x0666,0x0667, + 0x0668,0x0669,0x066a,0x066b,0x066c,0x066d,0x066e,0x066f, + 0x0670,0x0671,0x0672,0x0673,0x0674,0x0675,0x0676,0x0677, + 0x0678,0x0679,0x067a,0x067b,0x067c,0x067d,0x067e,0x067f, + 0x0680,0x0681,0x0682,0x0683,0x0684,0x0685,0x0686,0x0687, + 0x0688,0x0689,0x068a,0x068b,0x068c,0x068d,0x068e,0x068f, + 0x0690,0x0691,0x0692,0x0693,0x0694,0x0695,0x0696,0x0697, + 0x0698,0x0699,0x069a,0x069b,0x069c,0x069d,0x069e,0x069f, + 0x06a0,0x06a1,0x06a2,0x06a3,0x06a4,0x06a5,0x06a6,0x06a7, + 0x06a8,0x06a9,0x06aa,0x06ab,0x06ac,0x06ad,0x06ae,0x06af, + 0x06b0,0x06b1,0x06b2,0x06b3,0x06b4,0x06b5,0x06b6,0x06b7, + 0x06b8,0x06b9,0x06ba,0x06bb,0x06bc,0x06bd,0x06be,0x06bf, + 0x06c0,0x06c1,0x06c2,0x06c3,0x06c4,0x06c5,0x06c6,0x06c7, + 0x06c8,0x06c9,0x06ca,0x06cb,0x06cc,0x06cd,0x06ce,0x06cf, + 0x06d0,0x06d1,0x06d2,0x06d3,0x06d4,0x06d5,0x06d6,0x06d7, + 0x06d8,0x06d9,0x06da,0x06db,0x06dc,0x06dd,0x06de,0x06df, + 0x06e0,0x06e1,0x06e2,0x06e3,0x06e4,0x06e5,0x06e6,0x06e7, + 0x06e8,0x06e9,0x06ea,0x06eb,0x06ec,0x06ed,0x06ee,0x06ef, + 0x06f0,0x06f1,0x06f2,0x06f3,0x06f4,0x06f5,0x06f6,0x06f7, + 0x06f8,0x06f9,0x06fa,0x06fb,0x06fc,0x06fd,0x06fe,0x06ff, + 0x0700,0x0701,0x0702,0x0703,0x0704,0x0705,0x0706,0x0707, + 0x0708,0x0709,0x070a,0x070b,0x070c,0x070d,0x070e,0x070f, + 0x0710,0x0711,0x0712,0x0713,0x0714,0x0715,0x0716,0x0717, + 0x0718,0x0719,0x071a,0x071b,0x071c,0x071d,0x071e,0x071f, + 0x0720,0x0721,0x0722,0x0723,0x0724,0x0725,0x0726,0x0727, + 0x0728,0x0729,0x072a,0x072b,0x072c,0x072d,0x072e,0x072f, + 0x0730,0x0731,0x0732,0x0733,0x0734,0x0735,0x0736,0x0737, + 0x0738,0x0739,0x073a,0x073b,0x073c,0x073d,0x073e,0x073f, + 0x0740,0x0741,0x0742,0x0743,0x0744,0x0745,0x0746,0x0747, + 0x0748,0x0749,0x074a,0x074b,0x074c,0x074d,0x074e,0x074f, + 0x0750,0x0751,0x0752,0x0753,0x0754,0x0755,0x0756,0x0757, + 0x0758,0x0759,0x075a,0x075b,0x075c,0x075d,0x075e,0x075f, + 0x0760,0x0761,0x0762,0x0763,0x0764,0x0765,0x0766,0x0767, + 0x0768,0x0769,0x076a,0x076b,0x076c,0x076d,0x076e,0x076f, + 0x0770,0x0771,0x0772,0x0773,0x0774,0x0775,0x0776,0x0777, + 0x0778,0x0779,0x077a,0x077b,0x077c,0x077d,0x077e,0x077f, + 0x0780,0x0781,0x0782,0x0783,0x0784,0x0785,0x0786,0x0787, + 0x0788,0x0789,0x078a,0x078b,0x078c,0x078d,0x078e,0x078f, + 0x0790,0x0791,0x0792,0x0793,0x0794,0x0795,0x0796,0x0797, + 0x0798,0x0799,0x079a,0x079b,0x079c,0x079d,0x079e,0x079f, + 0x07a0,0x07a1,0x07a2,0x07a3,0x07a4,0x07a5,0x07a6,0x07a7, + 0x07a8,0x07a9,0x07aa,0x07ab,0x07ac,0x07ad,0x07ae,0x07af, + 0x07b0,0x07b1,0x07b2,0x07b3,0x07b4,0x07b5,0x07b6,0x07b7, + 0x07b8,0x07b9,0x07ba,0x07bb,0x07bc,0x07bd,0x07be,0x07bf, + 0x07c0,0x07c1,0x07c2,0x07c3,0x07c4,0x07c5,0x07c6,0x07c7, + 0x07c8,0x07c9,0x07ca,0x07cb,0x07cc,0x07cd,0x07ce,0x07cf, + 0x07d0,0x07d1,0x07d2,0x07d3,0x07d4,0x07d5,0x07d6,0x07d7, + 0x07d8,0x07d9,0x07da,0x07db,0x07dc,0x07dd,0x07de,0x07df, + 0x07e0,0x07e1,0x07e2,0x07e3,0x07e4,0x07e5,0x07e6,0x07e7, + 0x07e8,0x07e9,0x07ea,0x07eb,0x07ec,0x07ed,0x07ee,0x07ef, + 0x07f0,0x07f1,0x07f2,0x07f3,0x07f4,0x07f5,0x07f6,0x07f7, + 0x07f8,0x07f9,0x07fa,0x07fb,0x07fc,0x07fd,0x07fe,0x07ff, + 0x0800,0x0801,0x0802,0x0803,0x0804,0x0805,0x0806,0x0807, + 0x0808,0x0809,0x080a,0x080b,0x080c,0x080d,0x080e,0x080f, + 0x0810,0x0811,0x0812,0x0813,0x0814,0x0815,0x0816,0x0817, + 0x0818,0x0819,0x081a,0x081b,0x081c,0x081d,0x081e,0x081f, + 0x0820,0x0821,0x0822,0x0823,0x0824,0x0825,0x0826,0x0827, + 0x0828,0x0829,0x082a,0x082b,0x082c,0x082d,0x082e,0x082f, + 0x0830,0x0831,0x0832,0x0833,0x0834,0x0835,0x0836,0x0837, + 0x0838,0x0839,0x083a,0x083b,0x083c,0x083d,0x083e,0x083f, + 0x0840,0x0841,0x0842,0x0843,0x0844,0x0845,0x0846,0x0847, + 0x0848,0x0849,0x084a,0x084b,0x084c,0x084d,0x084e,0x084f, + 0x0850,0x0851,0x0852,0x0853,0x0854,0x0855,0x0856,0x0857, + 0x0858,0x0859,0x085a,0x085b,0x085c,0x085d,0x085e,0x085f, + 0x0860,0x0861,0x0862,0x0863,0x0864,0x0865,0x0866,0x0867, + 0x0868,0x0869,0x086a,0x086b,0x086c,0x086d,0x086e,0x086f, + 0x0870,0x0871,0x0872,0x0873,0x0874,0x0875,0x0876,0x0877, + 0x0878,0x0879,0x087a,0x087b,0x087c,0x087d,0x087e,0x087f, + 0x0880,0x0881,0x0882,0x0883,0x0884,0x0885,0x0886,0x0887, + 0x0888,0x0889,0x088a,0x088b,0x088c,0x088d,0x088e,0x088f, + 0x0890,0x0891,0x0892,0x0893,0x0894,0x0895,0x0896,0x0897, + 0x0898,0x0899,0x089a,0x089b,0x089c,0x089d,0x089e,0x089f, + 0x08a0,0x08a1,0x08a2,0x08a3,0x08a4,0x08a5,0x08a6,0x08a7, + 0x08a8,0x08a9,0x08aa,0x08ab,0x08ac,0x08ad,0x08ae,0x08af, + 0x08b0,0x08b1,0x08b2,0x08b3,0x08b4,0x08b5,0x08b6,0x08b7, + 0x08b8,0x08b9,0x08ba,0x08bb,0x08bc,0x08bd,0x08be,0x08bf, + 0x08c0,0x08c1,0x08c2,0x08c3,0x08c4,0x08c5,0x08c6,0x08c7, + 0x08c8,0x08c9,0x08ca,0x08cb,0x08cc,0x08cd,0x08ce,0x08cf, + 0x08d0,0x08d1,0x08d2,0x08d3,0x08d4,0x08d5,0x08d6,0x08d7, + 0x08d8,0x08d9,0x08da,0x08db,0x08dc,0x08dd,0x08de,0x08df, + 0x08e0,0x08e1,0x08e2,0x08e3,0x08e4,0x08e5,0x08e6,0x08e7, + 0x08e8,0x08e9,0x08ea,0x08eb,0x08ec,0x08ed,0x08ee,0x08ef, + 0x08f0,0x08f1,0x08f2,0x08f3,0x08f4,0x08f5,0x08f6,0x08f7, + 0x08f8,0x08f9,0x08fa,0x08fb,0x08fc,0x08fd,0x08fe,0x08ff, + 0x0900,0x0901,0x0902,0x0903,0x0904,0x0905,0x0906,0x0907, + 0x0908,0x0909,0x090a,0x090b,0x090c,0x090d,0x090e,0x090f, + 0x0910,0x0911,0x0912,0x0913,0x0914,0x0915,0x0916,0x0917, + 0x0918,0x0919,0x091a,0x091b,0x091c,0x091d,0x091e,0x091f, + 0x0920,0x0921,0x0922,0x0923,0x0924,0x0925,0x0926,0x0927, + 0x0928,0x0929,0x092a,0x092b,0x092c,0x092d,0x092e,0x092f, + 0x0930,0x0931,0x0932,0x0933,0x0934,0x0935,0x0936,0x0937, + 0x0938,0x0939,0x093a,0x093b,0x093c,0x093d,0x093e,0x093f, + 0x0940,0x0941,0x0942,0x0943,0x0944,0x0945,0x0946,0x0947, + 0x0948,0x0949,0x094a,0x094b,0x094c,0x094d,0x094e,0x094f, + 0x0950,0x0951,0x0952,0x0953,0x0954,0x0955,0x0956,0x0957, + 0x0958,0x0959,0x095a,0x095b,0x095c,0x095d,0x095e,0x095f, + 0x0960,0x0961,0x0962,0x0963,0x0964,0x0965,0x0966,0x0967, + 0x0968,0x0969,0x096a,0x096b,0x096c,0x096d,0x096e,0x096f, + 0x0970,0x0971,0x0972,0x0973,0x0974,0x0975,0x0976,0x0977, + 0x0978,0x0979,0x097a,0x097b,0x097c,0x097d,0x097e,0x097f, + 0x0980,0x0981,0x0982,0x0983,0x0984,0x0985,0x0986,0x0987, + 0x0988,0x0989,0x098a,0x098b,0x098c,0x098d,0x098e,0x098f, + 0x0990,0x0991,0x0992,0x0993,0x0994,0x0995,0x0996,0x0997, + 0x0998,0x0999,0x099a,0x099b,0x099c,0x099d,0x099e,0x099f, + 0x09a0,0x09a1,0x09a2,0x09a3,0x09a4,0x09a5,0x09a6,0x09a7, + 0x09a8,0x09a9,0x09aa,0x09ab,0x09ac,0x09ad,0x09ae,0x09af, + 0x09b0,0x09b1,0x09b2,0x09b3,0x09b4,0x09b5,0x09b6,0x09b7, + 0x09b8,0x09b9,0x09ba,0x09bb,0x09bc,0x09bd,0x09be,0x09bf, + 0x09c0,0x09c1,0x09c2,0x09c3,0x09c4,0x09c5,0x09c6,0x09c7, + 0x09c8,0x09c9,0x09ca,0x09cb,0x09cc,0x09cd,0x09ce,0x09cf, + 0x09d0,0x09d1,0x09d2,0x09d3,0x09d4,0x09d5,0x09d6,0x09d7, + 0x09d8,0x09d9,0x09da,0x09db,0x09dc,0x09dd,0x09de,0x09df, + 0x09e0,0x09e1,0x09e2,0x09e3,0x09e4,0x09e5,0x09e6,0x09e7, + 0x09e8,0x09e9,0x09ea,0x09eb,0x09ec,0x09ed,0x09ee,0x09ef, + 0x09f0,0x09f1,0x09f2,0x09f3,0x09f4,0x09f5,0x09f6,0x09f7, + 0x09f8,0x09f9,0x09fa,0x09fb,0x09fc,0x09fd,0x09fe,0x09ff, + 0x0a00,0x0a01,0x0a02,0x0a03,0x0a04,0x0a05,0x0a06,0x0a07, + 0x0a08,0x0a09,0x0a0a,0x0a0b,0x0a0c,0x0a0d,0x0a0e,0x0a0f, + 0x0a10,0x0a11,0x0a12,0x0a13,0x0a14,0x0a15,0x0a16,0x0a17, + 0x0a18,0x0a19,0x0a1a,0x0a1b,0x0a1c,0x0a1d,0x0a1e,0x0a1f, + 0x0a20,0x0a21,0x0a22,0x0a23,0x0a24,0x0a25,0x0a26,0x0a27, + 0x0a28,0x0a29,0x0a2a,0x0a2b,0x0a2c,0x0a2d,0x0a2e,0x0a2f, + 0x0a30,0x0a31,0x0a32,0x0a33,0x0a34,0x0a35,0x0a36,0x0a37, + 0x0a38,0x0a39,0x0a3a,0x0a3b,0x0a3c,0x0a3d,0x0a3e,0x0a3f, + 0x0a40,0x0a41,0x0a42,0x0a43,0x0a44,0x0a45,0x0a46,0x0a47, + 0x0a48,0x0a49,0x0a4a,0x0a4b,0x0a4c,0x0a4d,0x0a4e,0x0a4f, + 0x0a50,0x0a51,0x0a52,0x0a53,0x0a54,0x0a55,0x0a56,0x0a57, + 0x0a58,0x0a59,0x0a5a,0x0a5b,0x0a5c,0x0a5d,0x0a5e,0x0a5f, + 0x0a60,0x0a61,0x0a62,0x0a63,0x0a64,0x0a65,0x0a66,0x0a67, + 0x0a68,0x0a69,0x0a6a,0x0a6b,0x0a6c,0x0a6d,0x0a6e,0x0a6f, + 0x0a70,0x0a71,0x0a72,0x0a73,0x0a74,0x0a75,0x0a76,0x0a77, + 0x0a78,0x0a79,0x0a7a,0x0a7b,0x0a7c,0x0a7d,0x0a7e,0x0a7f, + 0x0a80,0x0a81,0x0a82,0x0a83,0x0a84,0x0a85,0x0a86,0x0a87, + 0x0a88,0x0a89,0x0a8a,0x0a8b,0x0a8c,0x0a8d,0x0a8e,0x0a8f, + 0x0a90,0x0a91,0x0a92,0x0a93,0x0a94,0x0a95,0x0a96,0x0a97, + 0x0a98,0x0a99,0x0a9a,0x0a9b,0x0a9c,0x0a9d,0x0a9e,0x0a9f, + 0x0aa0,0x0aa1,0x0aa2,0x0aa3,0x0aa4,0x0aa5,0x0aa6,0x0aa7, + 0x0aa8,0x0aa9,0x0aaa,0x0aab,0x0aac,0x0aad,0x0aae,0x0aaf, + 0x0ab0,0x0ab1,0x0ab2,0x0ab3,0x0ab4,0x0ab5,0x0ab6,0x0ab7, + 0x0ab8,0x0ab9,0x0aba,0x0abb,0x0abc,0x0abd,0x0abe,0x0abf, + 0x0ac0,0x0ac1,0x0ac2,0x0ac3,0x0ac4,0x0ac5,0x0ac6,0x0ac7, + 0x0ac8,0x0ac9,0x0aca,0x0acb,0x0acc,0x0acd,0x0ace,0x0acf, + 0x0ad0,0x0ad1,0x0ad2,0x0ad3,0x0ad4,0x0ad5,0x0ad6,0x0ad7, + 0x0ad8,0x0ad9,0x0ada,0x0adb,0x0adc,0x0add,0x0ade,0x0adf, + 0x0ae0,0x0ae1,0x0ae2,0x0ae3,0x0ae4,0x0ae5,0x0ae6,0x0ae7, + 0x0ae8,0x0ae9,0x0aea,0x0aeb,0x0aec,0x0aed,0x0aee,0x0aef, + 0x0af0,0x0af1,0x0af2,0x0af3,0x0af4,0x0af5,0x0af6,0x0af7, + 0x0af8,0x0af9,0x0afa,0x0afb,0x0afc,0x0afd,0x0afe,0x0aff, + 0x0b00,0x0b01,0x0b02,0x0b03,0x0b04,0x0b05,0x0b06,0x0b07, + 0x0b08,0x0b09,0x0b0a,0x0b0b,0x0b0c,0x0b0d,0x0b0e,0x0b0f, + 0x0b10,0x0b11,0x0b12,0x0b13,0x0b14,0x0b15,0x0b16,0x0b17, + 0x0b18,0x0b19,0x0b1a,0x0b1b,0x0b1c,0x0b1d,0x0b1e,0x0b1f, + 0x0b20,0x0b21,0x0b22,0x0b23,0x0b24,0x0b25,0x0b26,0x0b27, + 0x0b28,0x0b29,0x0b2a,0x0b2b,0x0b2c,0x0b2d,0x0b2e,0x0b2f, + 0x0b30,0x0b31,0x0b32,0x0b33,0x0b34,0x0b35,0x0b36,0x0b37, + 0x0b38,0x0b39,0x0b3a,0x0b3b,0x0b3c,0x0b3d,0x0b3e,0x0b3f, + 0x0b40,0x0b41,0x0b42,0x0b43,0x0b44,0x0b45,0x0b46,0x0b47, + 0x0b48,0x0b49,0x0b4a,0x0b4b,0x0b4c,0x0b4d,0x0b4e,0x0b4f, + 0x0b50,0x0b51,0x0b52,0x0b53,0x0b54,0x0b55,0x0b56,0x0b57, + 0x0b58,0x0b59,0x0b5a,0x0b5b,0x0b5c,0x0b5d,0x0b5e,0x0b5f, + 0x0b60,0x0b61,0x0b62,0x0b63,0x0b64,0x0b65,0x0b66,0x0b67, + 0x0b68,0x0b69,0x0b6a,0x0b6b,0x0b6c,0x0b6d,0x0b6e,0x0b6f, + 0x0b70,0x0b71,0x0b72,0x0b73,0x0b74,0x0b75,0x0b76,0x0b77, + 0x0b78,0x0b79,0x0b7a,0x0b7b,0x0b7c,0x0b7d,0x0b7e,0x0b7f, + 0x0b80,0x0b81,0x0b82,0x0b83,0x0b84,0x0b85,0x0b86,0x0b87, + 0x0b88,0x0b89,0x0b8a,0x0b8b,0x0b8c,0x0b8d,0x0b8e,0x0b8f, + 0x0b90,0x0b91,0x0b92,0x0b93,0x0b94,0x0b95,0x0b96,0x0b97, + 0x0b98,0x0b99,0x0b9a,0x0b9b,0x0b9c,0x0b9d,0x0b9e,0x0b9f, + 0x0ba0,0x0ba1,0x0ba2,0x0ba3,0x0ba4,0x0ba5,0x0ba6,0x0ba7, + 0x0ba8,0x0ba9,0x0baa,0x0bab,0x0bac,0x0bad,0x0bae,0x0baf, + 0x0bb0,0x0bb1,0x0bb2,0x0bb3,0x0bb4,0x0bb5,0x0bb6,0x0bb7, + 0x0bb8,0x0bb9,0x0bba,0x0bbb,0x0bbc,0x0bbd,0x0bbe,0x0bbf, + 0x0bc0,0x0bc1,0x0bc2,0x0bc3,0x0bc4,0x0bc5,0x0bc6,0x0bc7, + 0x0bc8,0x0bc9,0x0bca,0x0bcb,0x0bcc,0x0bcd,0x0bce,0x0bcf, + 0x0bd0,0x0bd1,0x0bd2,0x0bd3,0x0bd4,0x0bd5,0x0bd6,0x0bd7, + 0x0bd8,0x0bd9,0x0bda,0x0bdb,0x0bdc,0x0bdd,0x0bde,0x0bdf, + 0x0be0,0x0be1,0x0be2,0x0be3,0x0be4,0x0be5,0x0be6,0x0be7, + 0x0be8,0x0be9,0x0bea,0x0beb,0x0bec,0x0bed,0x0bee,0x0bef, + 0x0bf0,0x0bf1,0x0bf2,0x0bf3,0x0bf4,0x0bf5,0x0bf6,0x0bf7, + 0x0bf8,0x0bf9,0x0bfa,0x0bfb,0x0bfc,0x0bfd,0x0bfe,0x0bff, + 0x0c00,0x0c01,0x0c02,0x0c03,0x0c04,0x0c05,0x0c06,0x0c07, + 0x0c08,0x0c09,0x0c0a,0x0c0b,0x0c0c,0x0c0d,0x0c0e,0x0c0f, + 0x0c10,0x0c11,0x0c12,0x0c13,0x0c14,0x0c15,0x0c16,0x0c17, + 0x0c18,0x0c19,0x0c1a,0x0c1b,0x0c1c,0x0c1d,0x0c1e,0x0c1f, + 0x0c20,0x0c21,0x0c22,0x0c23,0x0c24,0x0c25,0x0c26,0x0c27, + 0x0c28,0x0c29,0x0c2a,0x0c2b,0x0c2c,0x0c2d,0x0c2e,0x0c2f, + 0x0c30,0x0c31,0x0c32,0x0c33,0x0c34,0x0c35,0x0c36,0x0c37, + 0x0c38,0x0c39,0x0c3a,0x0c3b,0x0c3c,0x0c3d,0x0c3e,0x0c3f, + 0x0c40,0x0c41,0x0c42,0x0c43,0x0c44,0x0c45,0x0c46,0x0c47, + 0x0c48,0x0c49,0x0c4a,0x0c4b,0x0c4c,0x0c4d,0x0c4e,0x0c4f, + 0x0c50,0x0c51,0x0c52,0x0c53,0x0c54,0x0c55,0x0c56,0x0c57, + 0x0c58,0x0c59,0x0c5a,0x0c5b,0x0c5c,0x0c5d,0x0c5e,0x0c5f, + 0x0c60,0x0c61,0x0c62,0x0c63,0x0c64,0x0c65,0x0c66,0x0c67, + 0x0c68,0x0c69,0x0c6a,0x0c6b,0x0c6c,0x0c6d,0x0c6e,0x0c6f, + 0x0c70,0x0c71,0x0c72,0x0c73,0x0c74,0x0c75,0x0c76,0x0c77, + 0x0c78,0x0c79,0x0c7a,0x0c7b,0x0c7c,0x0c7d,0x0c7e,0x0c7f, + 0x0c80,0x0c81,0x0c82,0x0c83,0x0c84,0x0c85,0x0c86,0x0c87, + 0x0c88,0x0c89,0x0c8a,0x0c8b,0x0c8c,0x0c8d,0x0c8e,0x0c8f, + 0x0c90,0x0c91,0x0c92,0x0c93,0x0c94,0x0c95,0x0c96,0x0c97, + 0x0c98,0x0c99,0x0c9a,0x0c9b,0x0c9c,0x0c9d,0x0c9e,0x0c9f, + 0x0ca0,0x0ca1,0x0ca2,0x0ca3,0x0ca4,0x0ca5,0x0ca6,0x0ca7, + 0x0ca8,0x0ca9,0x0caa,0x0cab,0x0cac,0x0cad,0x0cae,0x0caf, + 0x0cb0,0x0cb1,0x0cb2,0x0cb3,0x0cb4,0x0cb5,0x0cb6,0x0cb7, + 0x0cb8,0x0cb9,0x0cba,0x0cbb,0x0cbc,0x0cbd,0x0cbe,0x0cbf, + 0x0cc0,0x0cc1,0x0cc2,0x0cc3,0x0cc4,0x0cc5,0x0cc6,0x0cc7, + 0x0cc8,0x0cc9,0x0cca,0x0ccb,0x0ccc,0x0ccd,0x0cce,0x0ccf, + 0x0cd0,0x0cd1,0x0cd2,0x0cd3,0x0cd4,0x0cd5,0x0cd6,0x0cd7, + 0x0cd8,0x0cd9,0x0cda,0x0cdb,0x0cdc,0x0cdd,0x0cde,0x0cdf, + 0x0ce0,0x0ce1,0x0ce2,0x0ce3,0x0ce4,0x0ce5,0x0ce6,0x0ce7, + 0x0ce8,0x0ce9,0x0cea,0x0ceb,0x0cec,0x0ced,0x0cee,0x0cef, + 0x0cf0,0x0cf1,0x0cf2,0x0cf3,0x0cf4,0x0cf5,0x0cf6,0x0cf7, + 0x0cf8,0x0cf9,0x0cfa,0x0cfb,0x0cfc,0x0cfd,0x0cfe,0x0cff, + 0x0d00,0x0d01,0x0d02,0x0d03,0x0d04,0x0d05,0x0d06,0x0d07, + 0x0d08,0x0d09,0x0d0a,0x0d0b,0x0d0c,0x0d0d,0x0d0e,0x0d0f, + 0x0d10,0x0d11,0x0d12,0x0d13,0x0d14,0x0d15,0x0d16,0x0d17, + 0x0d18,0x0d19,0x0d1a,0x0d1b,0x0d1c,0x0d1d,0x0d1e,0x0d1f, + 0x0d20,0x0d21,0x0d22,0x0d23,0x0d24,0x0d25,0x0d26,0x0d27, + 0x0d28,0x0d29,0x0d2a,0x0d2b,0x0d2c,0x0d2d,0x0d2e,0x0d2f, + 0x0d30,0x0d31,0x0d32,0x0d33,0x0d34,0x0d35,0x0d36,0x0d37, + 0x0d38,0x0d39,0x0d3a,0x0d3b,0x0d3c,0x0d3d,0x0d3e,0x0d3f, + 0x0d40,0x0d41,0x0d42,0x0d43,0x0d44,0x0d45,0x0d46,0x0d47, + 0x0d48,0x0d49,0x0d4a,0x0d4b,0x0d4c,0x0d4d,0x0d4e,0x0d4f, + 0x0d50,0x0d51,0x0d52,0x0d53,0x0d54,0x0d55,0x0d56,0x0d57, + 0x0d58,0x0d59,0x0d5a,0x0d5b,0x0d5c,0x0d5d,0x0d5e,0x0d5f, + 0x0d60,0x0d61,0x0d62,0x0d63,0x0d64,0x0d65,0x0d66,0x0d67, + 0x0d68,0x0d69,0x0d6a,0x0d6b,0x0d6c,0x0d6d,0x0d6e,0x0d6f, + 0x0d70,0x0d71,0x0d72,0x0d73,0x0d74,0x0d75,0x0d76,0x0d77, + 0x0d78,0x0d79,0x0d7a,0x0d7b,0x0d7c,0x0d7d,0x0d7e,0x0d7f, + 0x0d80,0x0d81,0x0d82,0x0d83,0x0d84,0x0d85,0x0d86,0x0d87, + 0x0d88,0x0d89,0x0d8a,0x0d8b,0x0d8c,0x0d8d,0x0d8e,0x0d8f, + 0x0d90,0x0d91,0x0d92,0x0d93,0x0d94,0x0d95,0x0d96,0x0d97, + 0x0d98,0x0d99,0x0d9a,0x0d9b,0x0d9c,0x0d9d,0x0d9e,0x0d9f, + 0x0da0,0x0da1,0x0da2,0x0da3,0x0da4,0x0da5,0x0da6,0x0da7, + 0x0da8,0x0da9,0x0daa,0x0dab,0x0dac,0x0dad,0x0dae,0x0daf, + 0x0db0,0x0db1,0x0db2,0x0db3,0x0db4,0x0db5,0x0db6,0x0db7, + 0x0db8,0x0db9,0x0dba,0x0dbb,0x0dbc,0x0dbd,0x0dbe,0x0dbf, + 0x0dc0,0x0dc1,0x0dc2,0x0dc3,0x0dc4,0x0dc5,0x0dc6,0x0dc7, + 0x0dc8,0x0dc9,0x0dca,0x0dcb,0x0dcc,0x0dcd,0x0dce,0x0dcf, + 0x0dd0,0x0dd1,0x0dd2,0x0dd3,0x0dd4,0x0dd5,0x0dd6,0x0dd7, + 0x0dd8,0x0dd9,0x0dda,0x0ddb,0x0ddc,0x0ddd,0x0dde,0x0ddf, + 0x0de0,0x0de1,0x0de2,0x0de3,0x0de4,0x0de5,0x0de6,0x0de7, + 0x0de8,0x0de9,0x0dea,0x0deb,0x0dec,0x0ded,0x0dee,0x0def, + 0x0df0,0x0df1,0x0df2,0x0df3,0x0df4,0x0df5,0x0df6,0x0df7, + 0x0df8,0x0df9,0x0dfa,0x0dfb,0x0dfc,0x0dfd,0x0dfe,0x0dff, + 0x0e00,0x0e01,0x0e02,0x0e03,0x0e04,0x0e05,0x0e06,0x0e07, + 0x0e08,0x0e09,0x0e0a,0x0e0b,0x0e0c,0x0e0d,0x0e0e,0x0e0f, + 0x0e10,0x0e11,0x0e12,0x0e13,0x0e14,0x0e15,0x0e16,0x0e17, + 0x0e18,0x0e19,0x0e1a,0x0e1b,0x0e1c,0x0e1d,0x0e1e,0x0e1f, + 0x0e20,0x0e21,0x0e22,0x0e23,0x0e24,0x0e25,0x0e26,0x0e27, + 0x0e28,0x0e29,0x0e2a,0x0e2b,0x0e2c,0x0e2d,0x0e2e,0x0e2f, + 0x0e30,0x0e31,0x0e32,0x0e33,0x0e34,0x0e35,0x0e36,0x0e37, + 0x0e38,0x0e39,0x0e3a,0x0e3b,0x0e3c,0x0e3d,0x0e3e,0x0e3f, + 0x0e40,0x0e41,0x0e42,0x0e43,0x0e44,0x0e45,0x0e46,0x0e47, + 0x0e48,0x0e49,0x0e4a,0x0e4b,0x0e4c,0x0e4d,0x0e4e,0x0e4f, + 0x0e50,0x0e51,0x0e52,0x0e53,0x0e54,0x0e55,0x0e56,0x0e57, + 0x0e58,0x0e59,0x0e5a,0x0e5b,0x0e5c,0x0e5d,0x0e5e,0x0e5f, + 0x0e60,0x0e61,0x0e62,0x0e63,0x0e64,0x0e65,0x0e66,0x0e67, + 0x0e68,0x0e69,0x0e6a,0x0e6b,0x0e6c,0x0e6d,0x0e6e,0x0e6f, + 0x0e70,0x0e71,0x0e72,0x0e73,0x0e74,0x0e75,0x0e76,0x0e77, + 0x0e78,0x0e79,0x0e7a,0x0e7b,0x0e7c,0x0e7d,0x0e7e,0x0e7f, + 0x0e80,0x0e81,0x0e82,0x0e83,0x0e84,0x0e85,0x0e86,0x0e87, + 0x0e88,0x0e89,0x0e8a,0x0e8b,0x0e8c,0x0e8d,0x0e8e,0x0e8f, + 0x0e90,0x0e91,0x0e92,0x0e93,0x0e94,0x0e95,0x0e96,0x0e97, + 0x0e98,0x0e99,0x0e9a,0x0e9b,0x0e9c,0x0e9d,0x0e9e,0x0e9f, + 0x0ea0,0x0ea1,0x0ea2,0x0ea3,0x0ea4,0x0ea5,0x0ea6,0x0ea7, + 0x0ea8,0x0ea9,0x0eaa,0x0eab,0x0eac,0x0ead,0x0eae,0x0eaf, + 0x0eb0,0x0eb1,0x0eb2,0x0eb3,0x0eb4,0x0eb5,0x0eb6,0x0eb7, + 0x0eb8,0x0eb9,0x0eba,0x0ebb,0x0ebc,0x0ebd,0x0ebe,0x0ebf, + 0x0ec0,0x0ec1,0x0ec2,0x0ec3,0x0ec4,0x0ec5,0x0ec6,0x0ec7, + 0x0ec8,0x0ec9,0x0eca,0x0ecb,0x0ecc,0x0ecd,0x0ece,0x0ecf, + 0x0ed0,0x0ed1,0x0ed2,0x0ed3,0x0ed4,0x0ed5,0x0ed6,0x0ed7, + 0x0ed8,0x0ed9,0x0eda,0x0edb,0x0edc,0x0edd,0x0ede,0x0edf, + 0x0ee0,0x0ee1,0x0ee2,0x0ee3,0x0ee4,0x0ee5,0x0ee6,0x0ee7, + 0x0ee8,0x0ee9,0x0eea,0x0eeb,0x0eec,0x0eed,0x0eee,0x0eef, + 0x0ef0,0x0ef1,0x0ef2,0x0ef3,0x0ef4,0x0ef5,0x0ef6,0x0ef7, + 0x0ef8,0x0ef9,0x0efa,0x0efb,0x0efc,0x0efd,0x0efe,0x0eff, + 0x0f00,0x0f01,0x0f02,0x0f03,0x0f04,0x0f05,0x0f06,0x0f07, + 0x0f08,0x0f09,0x0f0a,0x0f0b,0x0f0c,0x0f0d,0x0f0e,0x0f0f, + 0x0f10,0x0f11,0x0f12,0x0f13,0x0f14,0x0f15,0x0f16,0x0f17, + 0x0f18,0x0f19,0x0f1a,0x0f1b,0x0f1c,0x0f1d,0x0f1e,0x0f1f, + 0x0f20,0x0f21,0x0f22,0x0f23,0x0f24,0x0f25,0x0f26,0x0f27, + 0x0f28,0x0f29,0x0f2a,0x0f2b,0x0f2c,0x0f2d,0x0f2e,0x0f2f, + 0x0f30,0x0f31,0x0f32,0x0f33,0x0f34,0x0f35,0x0f36,0x0f37, + 0x0f38,0x0f39,0x0f3a,0x0f3b,0x0f3c,0x0f3d,0x0f3e,0x0f3f, + 0x0f40,0x0f41,0x0f42,0x0f43,0x0f44,0x0f45,0x0f46,0x0f47, + 0x0f48,0x0f49,0x0f4a,0x0f4b,0x0f4c,0x0f4d,0x0f4e,0x0f4f, + 0x0f50,0x0f51,0x0f52,0x0f53,0x0f54,0x0f55,0x0f56,0x0f57, + 0x0f58,0x0f59,0x0f5a,0x0f5b,0x0f5c,0x0f5d,0x0f5e,0x0f5f, + 0x0f60,0x0f61,0x0f62,0x0f63,0x0f64,0x0f65,0x0f66,0x0f67, + 0x0f68,0x0f69,0x0f6a,0x0f6b,0x0f6c,0x0f6d,0x0f6e,0x0f6f, + 0x0f70,0x0f71,0x0f72,0x0f73,0x0f74,0x0f75,0x0f76,0x0f77, + 0x0f78,0x0f79,0x0f7a,0x0f7b,0x0f7c,0x0f7d,0x0f7e,0x0f7f, + 0x0f80,0x0f81,0x0f82,0x0f83,0x0f84,0x0f85,0x0f86,0x0f87, + 0x0f88,0x0f89,0x0f8a,0x0f8b,0x0f8c,0x0f8d,0x0f8e,0x0f8f, + 0x0f90,0x0f91,0x0f92,0x0f93,0x0f94,0x0f95,0x0f96,0x0f97, + 0x0f98,0x0f99,0x0f9a,0x0f9b,0x0f9c,0x0f9d,0x0f9e,0x0f9f, + 0x0fa0,0x0fa1,0x0fa2,0x0fa3,0x0fa4,0x0fa5,0x0fa6,0x0fa7, + 0x0fa8,0x0fa9,0x0faa,0x0fab,0x0fac,0x0fad,0x0fae,0x0faf, + 0x0fb0,0x0fb1,0x0fb2,0x0fb3,0x0fb4,0x0fb5,0x0fb6,0x0fb7, + 0x0fb8,0x0fb9,0x0fba,0x0fbb,0x0fbc,0x0fbd,0x0fbe,0x0fbf, + 0x0fc0,0x0fc1,0x0fc2,0x0fc3,0x0fc4,0x0fc5,0x0fc6,0x0fc7, + 0x0fc8,0x0fc9,0x0fca,0x0fcb,0x0fcc,0x0fcd,0x0fce,0x0fcf, + 0x0fd0,0x0fd1,0x0fd2,0x0fd3,0x0fd4,0x0fd5,0x0fd6,0x0fd7, + 0x0fd8,0x0fd9,0x0fda,0x0fdb,0x0fdc,0x0fdd,0x0fde,0x0fdf, + 0x0fe0,0x0fe1,0x0fe2,0x0fe3,0x0fe4,0x0fe5,0x0fe6,0x0fe7, + 0x0fe8,0x0fe9,0x0fea,0x0feb,0x0fec,0x0fed,0x0fee,0x0fef, + 0x0ff0,0x0ff1,0x0ff2,0x0ff3,0x0ff4,0x0ff5,0x0ff6,0x0ff7, + 0x0ff8,0x0ff9,0x0ffa,0x0ffb,0x0ffc,0x0ffd,0x0ffe,0x0fff, + 0x1000,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007, + 0x1008,0x1009,0x100a,0x100b,0x100c,0x100d,0x100e,0x100f, + 0x1010,0x1011,0x1012,0x1013,0x1014,0x1015,0x1016,0x1017, + 0x1018,0x1019,0x101a,0x101b,0x101c,0x101d,0x101e,0x101f, + 0x1020,0x1021,0x1022,0x1023,0x1024,0x1025,0x1026,0x1027, + 0x1028,0x1029,0x102a,0x102b,0x102c,0x102d,0x102e,0x102f, + 0x1030,0x1031,0x1032,0x1033,0x1034,0x1035,0x1036,0x1037, + 0x1038,0x1039,0x103a,0x103b,0x103c,0x103d,0x103e,0x103f, + 0x1040,0x1041,0x1042,0x1043,0x1044,0x1045,0x1046,0x1047, + 0x1048,0x1049,0x104a,0x104b,0x104c,0x104d,0x104e,0x104f, + 0x1050,0x1051,0x1052,0x1053,0x1054,0x1055,0x1056,0x1057, + 0x1058,0x1059,0x105a,0x105b,0x105c,0x105d,0x105e,0x105f, + 0x1060,0x1061,0x1062,0x1063,0x1064,0x1065,0x1066,0x1067, + 0x1068,0x1069,0x106a,0x106b,0x106c,0x106d,0x106e,0x106f, + 0x1070,0x1071,0x1072,0x1073,0x1074,0x1075,0x1076,0x1077, + 0x1078,0x1079,0x107a,0x107b,0x107c,0x107d,0x107e,0x107f, + 0x1080,0x1081,0x1082,0x1083,0x1084,0x1085,0x1086,0x1087, + 0x1088,0x1089,0x108a,0x108b,0x108c,0x108d,0x108e,0x108f, + 0x1090,0x1091,0x1092,0x1093,0x1094,0x1095,0x1096,0x1097, + 0x1098,0x1099,0x109a,0x109b,0x109c,0x109d,0x109e,0x109f, + 0x10a0,0x10a1,0x10a2,0x10a3,0x10a4,0x10a5,0x10a6,0x10a7, + 0x10a8,0x10a9,0x10aa,0x10ab,0x10ac,0x10ad,0x10ae,0x10af, + 0x10b0,0x10b1,0x10b2,0x10b3,0x10b4,0x10b5,0x10b6,0x10b7, + 0x10b8,0x10b9,0x10ba,0x10bb,0x10bc,0x10bd,0x10be,0x10bf, + 0x10c0,0x10c1,0x10c2,0x10c3,0x10c4,0x10c5,0x10c6,0x10c7, + 0x10c8,0x10c9,0x10ca,0x10cb,0x10cc,0x10cd,0x10ce,0x10cf, + 0x10d0,0x10d1,0x10d2,0x10d3,0x10d4,0x10d5,0x10d6,0x10d7, + 0x10d8,0x10d9,0x10da,0x10db,0x10dc,0x10dd,0x10de,0x10df, + 0x10e0,0x10e1,0x10e2,0x10e3,0x10e4,0x10e5,0x10e6,0x10e7, + 0x10e8,0x10e9,0x10ea,0x10eb,0x10ec,0x10ed,0x10ee,0x10ef, + 0x10f0,0x10f1,0x10f2,0x10f3,0x10f4,0x10f5,0x10f6,0x10f7, + 0x10f8,0x10f9,0x10fa,0x10fb,0x10fc,0x10fd,0x10fe,0x10ff, + 0x1100,0x1101,0x1102,0x1103,0x1104,0x1105,0x1106,0x1107, + 0x1108,0x1109,0x110a,0x110b,0x110c,0x110d,0x110e,0x110f, + 0x1110,0x1111,0x1112,0x1113,0x1114,0x1115,0x1116,0x1117, + 0x1118,0x1119,0x111a,0x111b,0x111c,0x111d,0x111e,0x111f, + 0x1120,0x1121,0x1122,0x1123,0x1124,0x1125,0x1126,0x1127, + 0x1128,0x1129,0x112a,0x112b,0x112c,0x112d,0x112e,0x112f, + 0x1130,0x1131,0x1132,0x1133,0x1134,0x1135,0x1136,0x1137, + 0x1138,0x1139,0x113a,0x113b,0x113c,0x113d,0x113e,0x113f, + 0x1140,0x1141,0x1142,0x1143,0x1144,0x1145,0x1146,0x1147, + 0x1148,0x1149,0x114a,0x114b,0x114c,0x114d,0x114e,0x114f, + 0x1150,0x1151,0x1152,0x1153,0x1154,0x1155,0x1156,0x1157, + 0x1158,0x1159,0x115a,0x115b,0x115c,0x115d,0x115e,0x115f, + 0x1160,0x1161,0x1162,0x1163,0x1164,0x1165,0x1166,0x1167, + 0x1168,0x1169,0x116a,0x116b,0x116c,0x116d,0x116e,0x116f, + 0x1170,0x1171,0x1172,0x1173,0x1174,0x1175,0x1176,0x1177, + 0x1178,0x1179,0x117a,0x117b,0x117c,0x117d,0x117e,0x117f, + 0x1180,0x1181,0x1182,0x1183,0x1184,0x1185,0x1186,0x1187, + 0x1188,0x1189,0x118a,0x118b,0x118c,0x118d,0x118e,0x118f, + 0x1190,0x1191,0x1192,0x1193,0x1194,0x1195,0x1196,0x1197, + 0x1198,0x1199,0x119a,0x119b,0x119c,0x119d,0x119e,0x119f, + 0x11a0,0x11a1,0x11a2,0x11a3,0x11a4,0x11a5,0x11a6,0x11a7, + 0x11a8,0x11a9,0x11aa,0x11ab,0x11ac,0x11ad,0x11ae,0x11af, + 0x11b0,0x11b1,0x11b2,0x11b3,0x11b4,0x11b5,0x11b6,0x11b7, + 0x11b8,0x11b9,0x11ba,0x11bb,0x11bc,0x11bd,0x11be,0x11bf, + 0x11c0,0x11c1,0x11c2,0x11c3,0x11c4,0x11c5,0x11c6,0x11c7, + 0x11c8,0x11c9,0x11ca,0x11cb,0x11cc,0x11cd,0x11ce,0x11cf, + 0x11d0,0x11d1,0x11d2,0x11d3,0x11d4,0x11d5,0x11d6,0x11d7, + 0x11d8,0x11d9,0x11da,0x11db,0x11dc,0x11dd,0x11de,0x11df, + 0x11e0,0x11e1,0x11e2,0x11e3,0x11e4,0x11e5,0x11e6,0x11e7, + 0x11e8,0x11e9,0x11ea,0x11eb,0x11ec,0x11ed,0x11ee,0x11ef, + 0x11f0,0x11f1,0x11f2,0x11f3,0x11f4,0x11f5,0x11f6,0x11f7, + 0x11f8,0x11f9,0x11fa,0x11fb,0x11fc,0x11fd,0x11fe,0x11ff, + 0x1200,0x1201,0x1202,0x1203,0x1204,0x1205,0x1206,0x1207, + 0x1208,0x1209,0x120a,0x120b,0x120c,0x120d,0x120e,0x120f, + 0x1210,0x1211,0x1212,0x1213,0x1214,0x1215,0x1216,0x1217, + 0x1218,0x1219,0x121a,0x121b,0x121c,0x121d,0x121e,0x121f, + 0x1220,0x1221,0x1222,0x1223,0x1224,0x1225,0x1226,0x1227, + 0x1228,0x1229,0x122a,0x122b,0x122c,0x122d,0x122e,0x122f, + 0x1230,0x1231,0x1232,0x1233,0x1234,0x1235,0x1236,0x1237, + 0x1238,0x1239,0x123a,0x123b,0x123c,0x123d,0x123e,0x123f, + 0x1240,0x1241,0x1242,0x1243,0x1244,0x1245,0x1246,0x1247, + 0x1248,0x1249,0x124a,0x124b,0x124c,0x124d,0x124e,0x124f, + 0x1250,0x1251,0x1252,0x1253,0x1254,0x1255,0x1256,0x1257, + 0x1258,0x1259,0x125a,0x125b,0x125c,0x125d,0x125e,0x125f, + 0x1260,0x1261,0x1262,0x1263,0x1264,0x1265,0x1266,0x1267, + 0x1268,0x1269,0x126a,0x126b,0x126c,0x126d,0x126e,0x126f, + 0x1270,0x1271,0x1272,0x1273,0x1274,0x1275,0x1276,0x1277, + 0x1278,0x1279,0x127a,0x127b,0x127c,0x127d,0x127e,0x127f, + 0x1280,0x1281,0x1282,0x1283,0x1284,0x1285,0x1286,0x1287, + 0x1288,0x1289,0x128a,0x128b,0x128c,0x128d,0x128e,0x128f, + 0x1290,0x1291,0x1292,0x1293,0x1294,0x1295,0x1296,0x1297, + 0x1298,0x1299,0x129a,0x129b,0x129c,0x129d,0x129e,0x129f, + 0x12a0,0x12a1,0x12a2,0x12a3,0x12a4,0x12a5,0x12a6,0x12a7, + 0x12a8,0x12a9,0x12aa,0x12ab,0x12ac,0x12ad,0x12ae,0x12af, + 0x12b0,0x12b1,0x12b2,0x12b3,0x12b4,0x12b5,0x12b6,0x12b7, + 0x12b8,0x12b9,0x12ba,0x12bb,0x12bc,0x12bd,0x12be,0x12bf, + 0x12c0,0x12c1,0x12c2,0x12c3,0x12c4,0x12c5,0x12c6,0x12c7, + 0x12c8,0x12c9,0x12ca,0x12cb,0x12cc,0x12cd,0x12ce,0x12cf, + 0x12d0,0x12d1,0x12d2,0x12d3,0x12d4,0x12d5,0x12d6,0x12d7, + 0x12d8,0x12d9,0x12da,0x12db,0x12dc,0x12dd,0x12de,0x12df, + 0x12e0,0x12e1,0x12e2,0x12e3,0x12e4,0x12e5,0x12e6,0x12e7, + 0x12e8,0x12e9,0x12ea,0x12eb,0x12ec,0x12ed,0x12ee,0x12ef, + 0x12f0,0x12f1,0x12f2,0x12f3,0x12f4,0x12f5,0x12f6,0x12f7, + 0x12f8,0x12f9,0x12fa,0x12fb,0x12fc,0x12fd,0x12fe,0x12ff, + 0x1300,0x1301,0x1302,0x1303,0x1304,0x1305,0x1306,0x1307, + 0x1308,0x1309,0x130a,0x130b,0x130c,0x130d,0x130e,0x130f, + 0x1310,0x1311,0x1312,0x1313,0x1314,0x1315,0x1316,0x1317, + 0x1318,0x1319,0x131a,0x131b,0x131c,0x131d,0x131e,0x131f, + 0x1320,0x1321,0x1322,0x1323,0x1324,0x1325,0x1326,0x1327, + 0x1328,0x1329,0x132a,0x132b,0x132c,0x132d,0x132e,0x132f, + 0x1330,0x1331,0x1332,0x1333,0x1334,0x1335,0x1336,0x1337, + 0x1338,0x1339,0x133a,0x133b,0x133c,0x133d,0x133e,0x133f, + 0x1340,0x1341,0x1342,0x1343,0x1344,0x1345,0x1346,0x1347, + 0x1348,0x1349,0x134a,0x134b,0x134c,0x134d,0x134e,0x134f, + 0x1350,0x1351,0x1352,0x1353,0x1354,0x1355,0x1356,0x1357, + 0x1358,0x1359,0x135a,0x135b,0x135c,0x135d,0x135e,0x135f, + 0x1360,0x1361,0x1362,0x1363,0x1364,0x1365,0x1366,0x1367, + 0x1368,0x1369,0x136a,0x136b,0x136c,0x136d,0x136e,0x136f, + 0x1370,0x1371,0x1372,0x1373,0x1374,0x1375,0x1376,0x1377, + 0x1378,0x1379,0x137a,0x137b,0x137c,0x137d,0x137e,0x137f, + 0x1380,0x1381,0x1382,0x1383,0x1384,0x1385,0x1386,0x1387, + 0x1388,0x1389,0x138a,0x138b,0x138c,0x138d,0x138e,0x138f, + 0x1390,0x1391,0x1392,0x1393,0x1394,0x1395,0x1396,0x1397, + 0x1398,0x1399,0x139a,0x139b,0x139c,0x139d,0x139e,0x139f, + 0x13a0,0x13a1,0x13a2,0x13a3,0x13a4,0x13a5,0x13a6,0x13a7, + 0x13a8,0x13a9,0x13aa,0x13ab,0x13ac,0x13ad,0x13ae,0x13af, + 0x13b0,0x13b1,0x13b2,0x13b3,0x13b4,0x13b5,0x13b6,0x13b7, + 0x13b8,0x13b9,0x13ba,0x13bb,0x13bc,0x13bd,0x13be,0x13bf, + 0x13c0,0x13c1,0x13c2,0x13c3,0x13c4,0x13c5,0x13c6,0x13c7, + 0x13c8,0x13c9,0x13ca,0x13cb,0x13cc,0x13cd,0x13ce,0x13cf, + 0x13d0,0x13d1,0x13d2,0x13d3,0x13d4,0x13d5,0x13d6,0x13d7, + 0x13d8,0x13d9,0x13da,0x13db,0x13dc,0x13dd,0x13de,0x13df, + 0x13e0,0x13e1,0x13e2,0x13e3,0x13e4,0x13e5,0x13e6,0x13e7, + 0x13e8,0x13e9,0x13ea,0x13eb,0x13ec,0x13ed,0x13ee,0x13ef, + 0x13f0,0x13f1,0x13f2,0x13f3,0x13f4,0x13f5,0x13f6,0x13f7, + 0x13f8,0x13f9,0x13fa,0x13fb,0x13fc,0x13fd,0x13fe,0x13ff, + 0x1400,0x1401,0x1402,0x1403,0x1404,0x1405,0x1406,0x1407, + 0x1408,0x1409,0x140a,0x140b,0x140c,0x140d,0x140e,0x140f, + 0x1410,0x1411,0x1412,0x1413,0x1414,0x1415,0x1416,0x1417, + 0x1418,0x1419,0x141a,0x141b,0x141c,0x141d,0x141e,0x141f, + 0x1420,0x1421,0x1422,0x1423,0x1424,0x1425,0x1426,0x1427, + 0x1428,0x1429,0x142a,0x142b,0x142c,0x142d,0x142e,0x142f, + 0x1430,0x1431,0x1432,0x1433,0x1434,0x1435,0x1436,0x1437, + 0x1438,0x1439,0x143a,0x143b,0x143c,0x143d,0x143e,0x143f, + 0x1440,0x1441,0x1442,0x1443,0x1444,0x1445,0x1446,0x1447, + 0x1448,0x1449,0x144a,0x144b,0x144c,0x144d,0x144e,0x144f, + 0x1450,0x1451,0x1452,0x1453,0x1454,0x1455,0x1456,0x1457, + 0x1458,0x1459,0x145a,0x145b,0x145c,0x145d,0x145e,0x145f, + 0x1460,0x1461,0x1462,0x1463,0x1464,0x1465,0x1466,0x1467, + 0x1468,0x1469,0x146a,0x146b,0x146c,0x146d,0x146e,0x146f, + 0x1470,0x1471,0x1472,0x1473,0x1474,0x1475,0x1476,0x1477, + 0x1478,0x1479,0x147a,0x147b,0x147c,0x147d,0x147e,0x147f, + 0x1480,0x1481,0x1482,0x1483,0x1484,0x1485,0x1486,0x1487, + 0x1488,0x1489,0x148a,0x148b,0x148c,0x148d,0x148e,0x148f, + 0x1490,0x1491,0x1492,0x1493,0x1494,0x1495,0x1496,0x1497, + 0x1498,0x1499,0x149a,0x149b,0x149c,0x149d,0x149e,0x149f, + 0x14a0,0x14a1,0x14a2,0x14a3,0x14a4,0x14a5,0x14a6,0x14a7, + 0x14a8,0x14a9,0x14aa,0x14ab,0x14ac,0x14ad,0x14ae,0x14af, + 0x14b0,0x14b1,0x14b2,0x14b3,0x14b4,0x14b5,0x14b6,0x14b7, + 0x14b8,0x14b9,0x14ba,0x14bb,0x14bc,0x14bd,0x14be,0x14bf, + 0x14c0,0x14c1,0x14c2,0x14c3,0x14c4,0x14c5,0x14c6,0x14c7, + 0x14c8,0x14c9,0x14ca,0x14cb,0x14cc,0x14cd,0x14ce,0x14cf, + 0x14d0,0x14d1,0x14d2,0x14d3,0x14d4,0x14d5,0x14d6,0x14d7, + 0x14d8,0x14d9,0x14da,0x14db,0x14dc,0x14dd,0x14de,0x14df, + 0x14e0,0x14e1,0x14e2,0x14e3,0x14e4,0x14e5,0x14e6,0x14e7, + 0x14e8,0x14e9,0x14ea,0x14eb,0x14ec,0x14ed,0x14ee,0x14ef, + 0x14f0,0x14f1,0x14f2,0x14f3,0x14f4,0x14f5,0x14f6,0x14f7, + 0x14f8,0x14f9,0x14fa,0x14fb,0x14fc,0x14fd,0x14fe,0x14ff, + 0x1500,0x1501,0x1502,0x1503,0x1504,0x1505,0x1506,0x1507, + 0x1508,0x1509,0x150a,0x150b,0x150c,0x150d,0x150e,0x150f, + 0x1510,0x1511,0x1512,0x1513,0x1514,0x1515,0x1516,0x1517, + 0x1518,0x1519,0x151a,0x151b,0x151c,0x151d,0x151e,0x151f, + 0x1520,0x1521,0x1522,0x1523,0x1524,0x1525,0x1526,0x1527, + 0x1528,0x1529,0x152a,0x152b,0x152c,0x152d,0x152e,0x152f, + 0x1530,0x1531,0x1532,0x1533,0x1534,0x1535,0x1536,0x1537, + 0x1538,0x1539,0x153a,0x153b,0x153c,0x153d,0x153e,0x153f, + 0x1540,0x1541,0x1542,0x1543,0x1544,0x1545,0x1546,0x1547, + 0x1548,0x1549,0x154a,0x154b,0x154c,0x154d,0x154e,0x154f, + 0x1550,0x1551,0x1552,0x1553,0x1554,0x1555,0x1556,0x1557, + 0x1558,0x1559,0x155a,0x155b,0x155c,0x155d,0x155e,0x155f, + 0x1560,0x1561,0x1562,0x1563,0x1564,0x1565,0x1566,0x1567, + 0x1568,0x1569,0x156a,0x156b,0x156c,0x156d,0x156e,0x156f, + 0x1570,0x1571,0x1572,0x1573,0x1574,0x1575,0x1576,0x1577, + 0x1578,0x1579,0x157a,0x157b,0x157c,0x157d,0x157e,0x157f, + 0x1580,0x1581,0x1582,0x1583,0x1584,0x1585,0x1586,0x1587, + 0x1588,0x1589,0x158a,0x158b,0x158c,0x158d,0x158e,0x158f, + 0x1590,0x1591,0x1592,0x1593,0x1594,0x1595,0x1596,0x1597, + 0x1598,0x1599,0x159a,0x159b,0x159c,0x159d,0x159e,0x159f, + 0x15a0,0x15a1,0x15a2,0x15a3,0x15a4,0x15a5,0x15a6,0x15a7, + 0x15a8,0x15a9,0x15aa,0x15ab,0x15ac,0x15ad,0x15ae,0x15af, + 0x15b0,0x15b1,0x15b2,0x15b3,0x15b4,0x15b5,0x15b6,0x15b7, + 0x15b8,0x15b9,0x15ba,0x15bb,0x15bc,0x15bd,0x15be,0x15bf, + 0x15c0,0x15c1,0x15c2,0x15c3,0x15c4,0x15c5,0x15c6,0x15c7, + 0x15c8,0x15c9,0x15ca,0x15cb,0x15cc,0x15cd,0x15ce,0x15cf, + 0x15d0,0x15d1,0x15d2,0x15d3,0x15d4,0x15d5,0x15d6,0x15d7, + 0x15d8,0x15d9,0x15da,0x15db,0x15dc,0x15dd,0x15de,0x15df, + 0x15e0,0x15e1,0x15e2,0x15e3,0x15e4,0x15e5,0x15e6,0x15e7, + 0x15e8,0x15e9,0x15ea,0x15eb,0x15ec,0x15ed,0x15ee,0x15ef, + 0x15f0,0x15f1,0x15f2,0x15f3,0x15f4,0x15f5,0x15f6,0x15f7, + 0x15f8,0x15f9,0x15fa,0x15fb,0x15fc,0x15fd,0x15fe,0x15ff, + 0x1600,0x1601,0x1602,0x1603,0x1604,0x1605,0x1606,0x1607, + 0x1608,0x1609,0x160a,0x160b,0x160c,0x160d,0x160e,0x160f, + 0x1610,0x1611,0x1612,0x1613,0x1614,0x1615,0x1616,0x1617, + 0x1618,0x1619,0x161a,0x161b,0x161c,0x161d,0x161e,0x161f, + 0x1620,0x1621,0x1622,0x1623,0x1624,0x1625,0x1626,0x1627, + 0x1628,0x1629,0x162a,0x162b,0x162c,0x162d,0x162e,0x162f, + 0x1630,0x1631,0x1632,0x1633,0x1634,0x1635,0x1636,0x1637, + 0x1638,0x1639,0x163a,0x163b,0x163c,0x163d,0x163e,0x163f, + 0x1640,0x1641,0x1642,0x1643,0x1644,0x1645,0x1646,0x1647, + 0x1648,0x1649,0x164a,0x164b,0x164c,0x164d,0x164e,0x164f, + 0x1650,0x1651,0x1652,0x1653,0x1654,0x1655,0x1656,0x1657, + 0x1658,0x1659,0x165a,0x165b,0x165c,0x165d,0x165e,0x165f, + 0x1660,0x1661,0x1662,0x1663,0x1664,0x1665,0x1666,0x1667, + 0x1668,0x1669,0x166a,0x166b,0x166c,0x166d,0x166e,0x166f, + 0x1670,0x1671,0x1672,0x1673,0x1674,0x1675,0x1676,0x1677, + 0x1678,0x1679,0x167a,0x167b,0x167c,0x167d,0x167e,0x167f, + 0x1680,0x1681,0x1682,0x1683,0x1684,0x1685,0x1686,0x1687, + 0x1688,0x1689,0x168a,0x168b,0x168c,0x168d,0x168e,0x168f, + 0x1690,0x1691,0x1692,0x1693,0x1694,0x1695,0x1696,0x1697, + 0x1698,0x1699,0x169a,0x169b,0x169c,0x169d,0x169e,0x169f, + 0x16a0,0x16a1,0x16a2,0x16a3,0x16a4,0x16a5,0x16a6,0x16a7, + 0x16a8,0x16a9,0x16aa,0x16ab,0x16ac,0x16ad,0x16ae,0x16af, + 0x16b0,0x16b1,0x16b2,0x16b3,0x16b4,0x16b5,0x16b6,0x16b7, + 0x16b8,0x16b9,0x16ba,0x16bb,0x16bc,0x16bd,0x16be,0x16bf, + 0x16c0,0x16c1,0x16c2,0x16c3,0x16c4,0x16c5,0x16c6,0x16c7, + 0x16c8,0x16c9,0x16ca,0x16cb,0x16cc,0x16cd,0x16ce,0x16cf, + 0x16d0,0x16d1,0x16d2,0x16d3,0x16d4,0x16d5,0x16d6,0x16d7, + 0x16d8,0x16d9,0x16da,0x16db,0x16dc,0x16dd,0x16de,0x16df, + 0x16e0,0x16e1,0x16e2,0x16e3,0x16e4,0x16e5,0x16e6,0x16e7, + 0x16e8,0x16e9,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef, + 0x16f0,0x16f1,0x16f2,0x16f3,0x16f4,0x16f5,0x16f6,0x16f7, + 0x16f8,0x16f9,0x16fa,0x16fb,0x16fc,0x16fd,0x16fe,0x16ff, + 0x1700,0x1701,0x1702,0x1703,0x1704,0x1705,0x1706,0x1707, + 0x1708,0x1709,0x170a,0x170b,0x170c,0x170d,0x170e,0x170f, + 0x1710,0x1711,0x1712,0x1713,0x1714,0x1715,0x1716,0x1717, + 0x1718,0x1719,0x171a,0x171b,0x171c,0x171d,0x171e,0x171f, + 0x1720,0x1721,0x1722,0x1723,0x1724,0x1725,0x1726,0x1727, + 0x1728,0x1729,0x172a,0x172b,0x172c,0x172d,0x172e,0x172f, + 0x1730,0x1731,0x1732,0x1733,0x1734,0x1735,0x1736,0x1737, + 0x1738,0x1739,0x173a,0x173b,0x173c,0x173d,0x173e,0x173f, + 0x1740,0x1741,0x1742,0x1743,0x1744,0x1745,0x1746,0x1747, + 0x1748,0x1749,0x174a,0x174b,0x174c,0x174d,0x174e,0x174f, + 0x1750,0x1751,0x1752,0x1753,0x1754,0x1755,0x1756,0x1757, + 0x1758,0x1759,0x175a,0x175b,0x175c,0x175d,0x175e,0x175f, + 0x1760,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767, + 0x1768,0x1769,0x176a,0x176b,0x176c,0x176d,0x176e,0x176f, + 0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x1776,0x1777, + 0x1778,0x1779,0x177a,0x177b,0x177c,0x177d,0x177e,0x177f, + 0x1780,0x1781,0x1782,0x1783,0x1784,0x1785,0x1786,0x1787, + 0x1788,0x1789,0x178a,0x178b,0x178c,0x178d,0x178e,0x178f, + 0x1790,0x1791,0x1792,0x1793,0x1794,0x1795,0x1796,0x1797, + 0x1798,0x1799,0x179a,0x179b,0x179c,0x179d,0x179e,0x179f, + 0x17a0,0x17a1,0x17a2,0x17a3,0x17a4,0x17a5,0x17a6,0x17a7, + 0x17a8,0x17a9,0x17aa,0x17ab,0x17ac,0x17ad,0x17ae,0x17af, + 0x17b0,0x17b1,0x17b2,0x17b3,0x17b4,0x17b5,0x17b6,0x17b7, + 0x17b8,0x17b9,0x17ba,0x17bb,0x17bc,0x17bd,0x17be,0x17bf, + 0x17c0,0x17c1,0x17c2,0x17c3,0x17c4,0x17c5,0x17c6,0x17c7, + 0x17c8,0x17c9,0x17ca,0x17cb,0x17cc,0x17cd,0x17ce,0x17cf, + 0x17d0,0x17d1,0x17d2,0x17d3,0x17d4,0x17d5,0x17d6,0x17d7, + 0x17d8,0x17d9,0x17da,0x17db,0x17dc,0x17dd,0x17de,0x17df, + 0x17e0,0x17e1,0x17e2,0x17e3,0x17e4,0x17e5,0x17e6,0x17e7, + 0x17e8,0x17e9,0x17ea,0x17eb,0x17ec,0x17ed,0x17ee,0x17ef, + 0x17f0,0x17f1,0x17f2,0x17f3,0x17f4,0x17f5,0x17f6,0x17f7, + 0x17f8,0x17f9,0x17fa,0x17fb,0x17fc,0x17fd,0x17fe,0x17ff, + 0x1800,0x1801,0x1802,0x1803,0x1804,0x1805,0x1806,0x1807, + 0x1808,0x1809,0x180a,0x180b,0x180c,0x180d,0x180e,0x180f, + 0x1810,0x1811,0x1812,0x1813,0x1814,0x1815,0x1816,0x1817, + 0x1818,0x1819,0x181a,0x181b,0x181c,0x181d,0x181e,0x181f, + 0x1820,0x1821,0x1822,0x1823,0x1824,0x1825,0x1826,0x1827, + 0x1828,0x1829,0x182a,0x182b,0x182c,0x182d,0x182e,0x182f, + 0x1830,0x1831,0x1832,0x1833,0x1834,0x1835,0x1836,0x1837, + 0x1838,0x1839,0x183a,0x183b,0x183c,0x183d,0x183e,0x183f, + 0x1840,0x1841,0x1842,0x1843,0x1844,0x1845,0x1846,0x1847, + 0x1848,0x1849,0x184a,0x184b,0x184c,0x184d,0x184e,0x184f, + 0x1850,0x1851,0x1852,0x1853,0x1854,0x1855,0x1856,0x1857, + 0x1858,0x1859,0x185a,0x185b,0x185c,0x185d,0x185e,0x185f, + 0x1860,0x1861,0x1862,0x1863,0x1864,0x1865,0x1866,0x1867, + 0x1868,0x1869,0x186a,0x186b,0x186c,0x186d,0x186e,0x186f, + 0x1870,0x1871,0x1872,0x1873,0x1874,0x1875,0x1876,0x1877, + 0x1878,0x1879,0x187a,0x187b,0x187c,0x187d,0x187e,0x187f, + 0x1880,0x1881,0x1882,0x1883,0x1884,0x1885,0x1886,0x1887, + 0x1888,0x1889,0x188a,0x188b,0x188c,0x188d,0x188e,0x188f, + 0x1890,0x1891,0x1892,0x1893,0x1894,0x1895,0x1896,0x1897, + 0x1898,0x1899,0x189a,0x189b,0x189c,0x189d,0x189e,0x189f, + 0x18a0,0x18a1,0x18a2,0x18a3,0x18a4,0x18a5,0x18a6,0x18a7, + 0x18a8,0x18a9,0x18aa,0x18ab,0x18ac,0x18ad,0x18ae,0x18af, + 0x18b0,0x18b1,0x18b2,0x18b3,0x18b4,0x18b5,0x18b6,0x18b7, + 0x18b8,0x18b9,0x18ba,0x18bb,0x18bc,0x18bd,0x18be,0x18bf, + 0x18c0,0x18c1,0x18c2,0x18c3,0x18c4,0x18c5,0x18c6,0x18c7, + 0x18c8,0x18c9,0x18ca,0x18cb,0x18cc,0x18cd,0x18ce,0x18cf, + 0x18d0,0x18d1,0x18d2,0x18d3,0x18d4,0x18d5,0x18d6,0x18d7, + 0x18d8,0x18d9,0x18da,0x18db,0x18dc,0x18dd,0x18de,0x18df, + 0x18e0,0x18e1,0x18e2,0x18e3,0x18e4,0x18e5,0x18e6,0x18e7, + 0x18e8,0x18e9,0x18ea,0x18eb,0x18ec,0x18ed,0x18ee,0x18ef, + 0x18f0,0x18f1,0x18f2,0x18f3,0x18f4,0x18f5,0x18f6,0x18f7, + 0x18f8,0x18f9,0x18fa,0x18fb,0x18fc,0x18fd,0x18fe,0x18ff, + 0x1900,0x1901,0x1902,0x1903,0x1904,0x1905,0x1906,0x1907, + 0x1908,0x1909,0x190a,0x190b,0x190c,0x190d,0x190e,0x190f, + 0x1910,0x1911,0x1912,0x1913,0x1914,0x1915,0x1916,0x1917, + 0x1918,0x1919,0x191a,0x191b,0x191c,0x191d,0x191e,0x191f, + 0x1920,0x1921,0x1922,0x1923,0x1924,0x1925,0x1926,0x1927, + 0x1928,0x1929,0x192a,0x192b,0x192c,0x192d,0x192e,0x192f, + 0x1930,0x1931,0x1932,0x1933,0x1934,0x1935,0x1936,0x1937, + 0x1938,0x1939,0x193a,0x193b,0x193c,0x193d,0x193e,0x193f, + 0x1940,0x1941,0x1942,0x1943,0x1944,0x1945,0x1946,0x1947, + 0x1948,0x1949,0x194a,0x194b,0x194c,0x194d,0x194e,0x194f, + 0x1950,0x1951,0x1952,0x1953,0x1954,0x1955,0x1956,0x1957, + 0x1958,0x1959,0x195a,0x195b,0x195c,0x195d,0x195e,0x195f, + 0x1960,0x1961,0x1962,0x1963,0x1964,0x1965,0x1966,0x1967, + 0x1968,0x1969,0x196a,0x196b,0x196c,0x196d,0x196e,0x196f, + 0x1970,0x1971,0x1972,0x1973,0x1974,0x1975,0x1976,0x1977, + 0x1978,0x1979,0x197a,0x197b,0x197c,0x197d,0x197e,0x197f, + 0x1980,0x1981,0x1982,0x1983,0x1984,0x1985,0x1986,0x1987, + 0x1988,0x1989,0x198a,0x198b,0x198c,0x198d,0x198e,0x198f, + 0x1990,0x1991,0x1992,0x1993,0x1994,0x1995,0x1996,0x1997, + 0x1998,0x1999,0x199a,0x199b,0x199c,0x199d,0x199e,0x199f, + 0x19a0,0x19a1,0x19a2,0x19a3,0x19a4,0x19a5,0x19a6,0x19a7, + 0x19a8,0x19a9,0x19aa,0x19ab,0x19ac,0x19ad,0x19ae,0x19af, + 0x19b0,0x19b1,0x19b2,0x19b3,0x19b4,0x19b5,0x19b6,0x19b7, + 0x19b8,0x19b9,0x19ba,0x19bb,0x19bc,0x19bd,0x19be,0x19bf, + 0x19c0,0x19c1,0x19c2,0x19c3,0x19c4,0x19c5,0x19c6,0x19c7, + 0x19c8,0x19c9,0x19ca,0x19cb,0x19cc,0x19cd,0x19ce,0x19cf, + 0x19d0,0x19d1,0x19d2,0x19d3,0x19d4,0x19d5,0x19d6,0x19d7, + 0x19d8,0x19d9,0x19da,0x19db,0x19dc,0x19dd,0x19de,0x19df, + 0x19e0,0x19e1,0x19e2,0x19e3,0x19e4,0x19e5,0x19e6,0x19e7, + 0x19e8,0x19e9,0x19ea,0x19eb,0x19ec,0x19ed,0x19ee,0x19ef, + 0x19f0,0x19f1,0x19f2,0x19f3,0x19f4,0x19f5,0x19f6,0x19f7, + 0x19f8,0x19f9,0x19fa,0x19fb,0x19fc,0x19fd,0x19fe,0x19ff, + 0x1a00,0x1a01,0x1a02,0x1a03,0x1a04,0x1a05,0x1a06,0x1a07, + 0x1a08,0x1a09,0x1a0a,0x1a0b,0x1a0c,0x1a0d,0x1a0e,0x1a0f, + 0x1a10,0x1a11,0x1a12,0x1a13,0x1a14,0x1a15,0x1a16,0x1a17, + 0x1a18,0x1a19,0x1a1a,0x1a1b,0x1a1c,0x1a1d,0x1a1e,0x1a1f, + 0x1a20,0x1a21,0x1a22,0x1a23,0x1a24,0x1a25,0x1a26,0x1a27, + 0x1a28,0x1a29,0x1a2a,0x1a2b,0x1a2c,0x1a2d,0x1a2e,0x1a2f, + 0x1a30,0x1a31,0x1a32,0x1a33,0x1a34,0x1a35,0x1a36,0x1a37, + 0x1a38,0x1a39,0x1a3a,0x1a3b,0x1a3c,0x1a3d,0x1a3e,0x1a3f, + 0x1a40,0x1a41,0x1a42,0x1a43,0x1a44,0x1a45,0x1a46,0x1a47, + 0x1a48,0x1a49,0x1a4a,0x1a4b,0x1a4c,0x1a4d,0x1a4e,0x1a4f, + 0x1a50,0x1a51,0x1a52,0x1a53,0x1a54,0x1a55,0x1a56,0x1a57, + 0x1a58,0x1a59,0x1a5a,0x1a5b,0x1a5c,0x1a5d,0x1a5e,0x1a5f, + 0x1a60,0x1a61,0x1a62,0x1a63,0x1a64,0x1a65,0x1a66,0x1a67, + 0x1a68,0x1a69,0x1a6a,0x1a6b,0x1a6c,0x1a6d,0x1a6e,0x1a6f, + 0x1a70,0x1a71,0x1a72,0x1a73,0x1a74,0x1a75,0x1a76,0x1a77, + 0x1a78,0x1a79,0x1a7a,0x1a7b,0x1a7c,0x1a7d,0x1a7e,0x1a7f, + 0x1a80,0x1a81,0x1a82,0x1a83,0x1a84,0x1a85,0x1a86,0x1a87, + 0x1a88,0x1a89,0x1a8a,0x1a8b,0x1a8c,0x1a8d,0x1a8e,0x1a8f, + 0x1a90,0x1a91,0x1a92,0x1a93,0x1a94,0x1a95,0x1a96,0x1a97, + 0x1a98,0x1a99,0x1a9a,0x1a9b,0x1a9c,0x1a9d,0x1a9e,0x1a9f, + 0x1aa0,0x1aa1,0x1aa2,0x1aa3,0x1aa4,0x1aa5,0x1aa6,0x1aa7, + 0x1aa8,0x1aa9,0x1aaa,0x1aab,0x1aac,0x1aad,0x1aae,0x1aaf, + 0x1ab0,0x1ab1,0x1ab2,0x1ab3,0x1ab4,0x1ab5,0x1ab6,0x1ab7, + 0x1ab8,0x1ab9,0x1aba,0x1abb,0x1abc,0x1abd,0x1abe,0x1abf, + 0x1ac0,0x1ac1,0x1ac2,0x1ac3,0x1ac4,0x1ac5,0x1ac6,0x1ac7, + 0x1ac8,0x1ac9,0x1aca,0x1acb,0x1acc,0x1acd,0x1ace,0x1acf, + 0x1ad0,0x1ad1,0x1ad2,0x1ad3,0x1ad4,0x1ad5,0x1ad6,0x1ad7, + 0x1ad8,0x1ad9,0x1ada,0x1adb,0x1adc,0x1add,0x1ade,0x1adf, + 0x1ae0,0x1ae1,0x1ae2,0x1ae3,0x1ae4,0x1ae5,0x1ae6,0x1ae7, + 0x1ae8,0x1ae9,0x1aea,0x1aeb,0x1aec,0x1aed,0x1aee,0x1aef, + 0x1af0,0x1af1,0x1af2,0x1af3,0x1af4,0x1af5,0x1af6,0x1af7, + 0x1af8,0x1af9,0x1afa,0x1afb,0x1afc,0x1afd,0x1afe,0x1aff, + 0x1b00,0x1b01,0x1b02,0x1b03,0x1b04,0x1b05,0x1b06,0x1b07, + 0x1b08,0x1b09,0x1b0a,0x1b0b,0x1b0c,0x1b0d,0x1b0e,0x1b0f, + 0x1b10,0x1b11,0x1b12,0x1b13,0x1b14,0x1b15,0x1b16,0x1b17, + 0x1b18,0x1b19,0x1b1a,0x1b1b,0x1b1c,0x1b1d,0x1b1e,0x1b1f, + 0x1b20,0x1b21,0x1b22,0x1b23,0x1b24,0x1b25,0x1b26,0x1b27, + 0x1b28,0x1b29,0x1b2a,0x1b2b,0x1b2c,0x1b2d,0x1b2e,0x1b2f, + 0x1b30,0x1b31,0x1b32,0x1b33,0x1b34,0x1b35,0x1b36,0x1b37, + 0x1b38,0x1b39,0x1b3a,0x1b3b,0x1b3c,0x1b3d,0x1b3e,0x1b3f, + 0x1b40,0x1b41,0x1b42,0x1b43,0x1b44,0x1b45,0x1b46,0x1b47, + 0x1b48,0x1b49,0x1b4a,0x1b4b,0x1b4c,0x1b4d,0x1b4e,0x1b4f, + 0x1b50,0x1b51,0x1b52,0x1b53,0x1b54,0x1b55,0x1b56,0x1b57, + 0x1b58,0x1b59,0x1b5a,0x1b5b,0x1b5c,0x1b5d,0x1b5e,0x1b5f, + 0x1b60,0x1b61,0x1b62,0x1b63,0x1b64,0x1b65,0x1b66,0x1b67, + 0x1b68,0x1b69,0x1b6a,0x1b6b,0x1b6c,0x1b6d,0x1b6e,0x1b6f, + 0x1b70,0x1b71,0x1b72,0x1b73,0x1b74,0x1b75,0x1b76,0x1b77, + 0x1b78,0x1b79,0x1b7a,0x1b7b,0x1b7c,0x1b7d,0x1b7e,0x1b7f, + 0x1b80,0x1b81,0x1b82,0x1b83,0x1b84,0x1b85,0x1b86,0x1b87, + 0x1b88,0x1b89,0x1b8a,0x1b8b,0x1b8c,0x1b8d,0x1b8e,0x1b8f, + 0x1b90,0x1b91,0x1b92,0x1b93,0x1b94,0x1b95,0x1b96,0x1b97, + 0x1b98,0x1b99,0x1b9a,0x1b9b,0x1b9c,0x1b9d,0x1b9e,0x1b9f, + 0x1ba0,0x1ba1,0x1ba2,0x1ba3,0x1ba4,0x1ba5,0x1ba6,0x1ba7, + 0x1ba8,0x1ba9,0x1baa,0x1bab,0x1bac,0x1bad,0x1bae,0x1baf, + 0x1bb0,0x1bb1,0x1bb2,0x1bb3,0x1bb4,0x1bb5,0x1bb6,0x1bb7, + 0x1bb8,0x1bb9,0x1bba,0x1bbb,0x1bbc,0x1bbd,0x1bbe,0x1bbf, + 0x1bc0,0x1bc1,0x1bc2,0x1bc3,0x1bc4,0x1bc5,0x1bc6,0x1bc7, + 0x1bc8,0x1bc9,0x1bca,0x1bcb,0x1bcc,0x1bcd,0x1bce,0x1bcf, + 0x1bd0,0x1bd1,0x1bd2,0x1bd3,0x1bd4,0x1bd5,0x1bd6,0x1bd7, + 0x1bd8,0x1bd9,0x1bda,0x1bdb,0x1bdc,0x1bdd,0x1bde,0x1bdf, + 0x1be0,0x1be1,0x1be2,0x1be3,0x1be4,0x1be5,0x1be6,0x1be7, + 0x1be8,0x1be9,0x1bea,0x1beb,0x1bec,0x1bed,0x1bee,0x1bef, + 0x1bf0,0x1bf1,0x1bf2,0x1bf3,0x1bf4,0x1bf5,0x1bf6,0x1bf7, + 0x1bf8,0x1bf9,0x1bfa,0x1bfb,0x1bfc,0x1bfd,0x1bfe,0x1bff, + 0x1c00,0x1c01,0x1c02,0x1c03,0x1c04,0x1c05,0x1c06,0x1c07, + 0x1c08,0x1c09,0x1c0a,0x1c0b,0x1c0c,0x1c0d,0x1c0e,0x1c0f, + 0x1c10,0x1c11,0x1c12,0x1c13,0x1c14,0x1c15,0x1c16,0x1c17, + 0x1c18,0x1c19,0x1c1a,0x1c1b,0x1c1c,0x1c1d,0x1c1e,0x1c1f, + 0x1c20,0x1c21,0x1c22,0x1c23,0x1c24,0x1c25,0x1c26,0x1c27, + 0x1c28,0x1c29,0x1c2a,0x1c2b,0x1c2c,0x1c2d,0x1c2e,0x1c2f, + 0x1c30,0x1c31,0x1c32,0x1c33,0x1c34,0x1c35,0x1c36,0x1c37, + 0x1c38,0x1c39,0x1c3a,0x1c3b,0x1c3c,0x1c3d,0x1c3e,0x1c3f, + 0x1c40,0x1c41,0x1c42,0x1c43,0x1c44,0x1c45,0x1c46,0x1c47, + 0x1c48,0x1c49,0x1c4a,0x1c4b,0x1c4c,0x1c4d,0x1c4e,0x1c4f, + 0x1c50,0x1c51,0x1c52,0x1c53,0x1c54,0x1c55,0x1c56,0x1c57, + 0x1c58,0x1c59,0x1c5a,0x1c5b,0x1c5c,0x1c5d,0x1c5e,0x1c5f, + 0x1c60,0x1c61,0x1c62,0x1c63,0x1c64,0x1c65,0x1c66,0x1c67, + 0x1c68,0x1c69,0x1c6a,0x1c6b,0x1c6c,0x1c6d,0x1c6e,0x1c6f, + 0x1c70,0x1c71,0x1c72,0x1c73,0x1c74,0x1c75,0x1c76,0x1c77, + 0x1c78,0x1c79,0x1c7a,0x1c7b,0x1c7c,0x1c7d,0x1c7e,0x1c7f, + 0x1c80,0x1c81,0x1c82,0x1c83,0x1c84,0x1c85,0x1c86,0x1c87, + 0x1c88,0x1c89,0x1c8a,0x1c8b,0x1c8c,0x1c8d,0x1c8e,0x1c8f, + 0x1c90,0x1c91,0x1c92,0x1c93,0x1c94,0x1c95,0x1c96,0x1c97, + 0x1c98,0x1c99,0x1c9a,0x1c9b,0x1c9c,0x1c9d,0x1c9e,0x1c9f, + 0x1ca0,0x1ca1,0x1ca2,0x1ca3,0x1ca4,0x1ca5,0x1ca6,0x1ca7, + 0x1ca8,0x1ca9,0x1caa,0x1cab,0x1cac,0x1cad,0x1cae,0x1caf, + 0x1cb0,0x1cb1,0x1cb2,0x1cb3,0x1cb4,0x1cb5,0x1cb6,0x1cb7, + 0x1cb8,0x1cb9,0x1cba,0x1cbb,0x1cbc,0x1cbd,0x1cbe,0x1cbf, + 0x1cc0,0x1cc1,0x1cc2,0x1cc3,0x1cc4,0x1cc5,0x1cc6,0x1cc7, + 0x1cc8,0x1cc9,0x1cca,0x1ccb,0x1ccc,0x1ccd,0x1cce,0x1ccf, + 0x1cd0,0x1cd1,0x1cd2,0x1cd3,0x1cd4,0x1cd5,0x1cd6,0x1cd7, + 0x1cd8,0x1cd9,0x1cda,0x1cdb,0x1cdc,0x1cdd,0x1cde,0x1cdf, + 0x1ce0,0x1ce1,0x1ce2,0x1ce3,0x1ce4,0x1ce5,0x1ce6,0x1ce7, + 0x1ce8,0x1ce9,0x1cea,0x1ceb,0x1cec,0x1ced,0x1cee,0x1cef, + 0x1cf0,0x1cf1,0x1cf2,0x1cf3,0x1cf4,0x1cf5,0x1cf6,0x1cf7, + 0x1cf8,0x1cf9,0x1cfa,0x1cfb,0x1cfc,0x1cfd,0x1cfe,0x1cff, + 0x1d00,0x1d01,0x1d02,0x1d03,0x1d04,0x1d05,0x1d06,0x1d07, + 0x1d08,0x1d09,0x1d0a,0x1d0b,0x1d0c,0x1d0d,0x1d0e,0x1d0f, + 0x1d10,0x1d11,0x1d12,0x1d13,0x1d14,0x1d15,0x1d16,0x1d17, + 0x1d18,0x1d19,0x1d1a,0x1d1b,0x1d1c,0x1d1d,0x1d1e,0x1d1f, + 0x1d20,0x1d21,0x1d22,0x1d23,0x1d24,0x1d25,0x1d26,0x1d27, + 0x1d28,0x1d29,0x1d2a,0x1d2b,0x1d2c,0x1d2d,0x1d2e,0x1d2f, + 0x1d30,0x1d31,0x1d32,0x1d33,0x1d34,0x1d35,0x1d36,0x1d37, + 0x1d38,0x1d39,0x1d3a,0x1d3b,0x1d3c,0x1d3d,0x1d3e,0x1d3f, + 0x1d40,0x1d41,0x1d42,0x1d43,0x1d44,0x1d45,0x1d46,0x1d47, + 0x1d48,0x1d49,0x1d4a,0x1d4b,0x1d4c,0x1d4d,0x1d4e,0x1d4f, + 0x1d50,0x1d51,0x1d52,0x1d53,0x1d54,0x1d55,0x1d56,0x1d57, + 0x1d58,0x1d59,0x1d5a,0x1d5b,0x1d5c,0x1d5d,0x1d5e,0x1d5f, + 0x1d60,0x1d61,0x1d62,0x1d63,0x1d64,0x1d65,0x1d66,0x1d67, + 0x1d68,0x1d69,0x1d6a,0x1d6b,0x1d6c,0x1d6d,0x1d6e,0x1d6f, + 0x1d70,0x1d71,0x1d72,0x1d73,0x1d74,0x1d75,0x1d76,0x1d77, + 0x1d78,0x1d79,0x1d7a,0x1d7b,0x1d7c,0x1d7d,0x1d7e,0x1d7f, + 0x1d80,0x1d81,0x1d82,0x1d83,0x1d84,0x1d85,0x1d86,0x1d87, + 0x1d88,0x1d89,0x1d8a,0x1d8b,0x1d8c,0x1d8d,0x1d8e,0x1d8f, + 0x1d90,0x1d91,0x1d92,0x1d93,0x1d94,0x1d95,0x1d96,0x1d97, + 0x1d98,0x1d99,0x1d9a,0x1d9b,0x1d9c,0x1d9d,0x1d9e,0x1d9f, + 0x1da0,0x1da1,0x1da2,0x1da3,0x1da4,0x1da5,0x1da6,0x1da7, + 0x1da8,0x1da9,0x1daa,0x1dab,0x1dac,0x1dad,0x1dae,0x1daf, + 0x1db0,0x1db1,0x1db2,0x1db3,0x1db4,0x1db5,0x1db6,0x1db7, + 0x1db8,0x1db9,0x1dba,0x1dbb,0x1dbc,0x1dbd,0x1dbe,0x1dbf, + 0x1dc0,0x1dc1,0x1dc2,0x1dc3,0x1dc4,0x1dc5,0x1dc6,0x1dc7, + 0x1dc8,0x1dc9,0x1dca,0x1dcb,0x1dcc,0x1dcd,0x1dce,0x1dcf, + 0x1dd0,0x1dd1,0x1dd2,0x1dd3,0x1dd4,0x1dd5,0x1dd6,0x1dd7, + 0x1dd8,0x1dd9,0x1dda,0x1ddb,0x1ddc,0x1ddd,0x1dde,0x1ddf, + 0x1de0,0x1de1,0x1de2,0x1de3,0x1de4,0x1de5,0x1de6,0x1de7, + 0x1de8,0x1de9,0x1dea,0x1deb,0x1dec,0x1ded,0x1dee,0x1def, + 0x1df0,0x1df1,0x1df2,0x1df3,0x1df4,0x1df5,0x1df6,0x1df7, + 0x1df8,0x1df9,0x1dfa,0x1dfb,0x1dfc,0x1dfd,0x1dfe,0x1dff, + 0x1e01,0x1e01,0x1e03,0x1e03,0x1e05,0x1e05,0x1e07,0x1e07, + 0x1e09,0x1e09,0x1e0b,0x1e0b,0x1e0d,0x1e0d,0x1e0f,0x1e0f, + 0x1e11,0x1e11,0x1e13,0x1e13,0x1e15,0x1e15,0x1e17,0x1e17, + 0x1e19,0x1e19,0x1e1b,0x1e1b,0x1e1d,0x1e1d,0x1e1f,0x1e1f, + 0x1e21,0x1e21,0x1e23,0x1e23,0x1e25,0x1e25,0x1e27,0x1e27, + 0x1e29,0x1e29,0x1e2b,0x1e2b,0x1e2d,0x1e2d,0x1e2f,0x1e2f, + 0x1e31,0x1e31,0x1e33,0x1e33,0x1e35,0x1e35,0x1e37,0x1e37, + 0x1e39,0x1e39,0x1e3b,0x1e3b,0x1e3d,0x1e3d,0x1e3f,0x1e3f, + 0x1e41,0x1e41,0x1e43,0x1e43,0x1e45,0x1e45,0x1e47,0x1e47, + 0x1e49,0x1e49,0x1e4b,0x1e4b,0x1e4d,0x1e4d,0x1e4f,0x1e4f, + 0x1e51,0x1e51,0x1e53,0x1e53,0x1e55,0x1e55,0x1e57,0x1e57, + 0x1e59,0x1e59,0x1e5b,0x1e5b,0x1e5d,0x1e5d,0x1e5f,0x1e5f, + 0x1e61,0x1e61,0x1e63,0x1e63,0x1e65,0x1e65,0x1e67,0x1e67, + 0x1e69,0x1e69,0x1e6b,0x1e6b,0x1e6d,0x1e6d,0x1e6f,0x1e6f, + 0x1e71,0x1e71,0x1e73,0x1e73,0x1e75,0x1e75,0x1e77,0x1e77, + 0x1e79,0x1e79,0x1e7b,0x1e7b,0x1e7d,0x1e7d,0x1e7f,0x1e7f, + 0x1e81,0x1e81,0x1e83,0x1e83,0x1e85,0x1e85,0x1e87,0x1e87, + 0x1e89,0x1e89,0x1e8b,0x1e8b,0x1e8d,0x1e8d,0x1e8f,0x1e8f, + 0x1e91,0x1e91,0x1e93,0x1e93,0x1e95,0x1e95,0x1e96,0x1e97, + 0x1e98,0x1e99,0x1e9a,0x1e9b,0x1e9c,0x1e9d,0x1e9e,0x1e9f, + 0x1ea1,0x1ea1,0x1ea3,0x1ea3,0x1ea5,0x1ea5,0x1ea7,0x1ea7, + 0x1ea9,0x1ea9,0x1eab,0x1eab,0x1ead,0x1ead,0x1eaf,0x1eaf, + 0x1eb1,0x1eb1,0x1eb3,0x1eb3,0x1eb5,0x1eb5,0x1eb7,0x1eb7, + 0x1eb9,0x1eb9,0x1ebb,0x1ebb,0x1ebd,0x1ebd,0x1ebf,0x1ebf, + 0x1ec1,0x1ec1,0x1ec3,0x1ec3,0x1ec5,0x1ec5,0x1ec7,0x1ec7, + 0x1ec9,0x1ec9,0x1ecb,0x1ecb,0x1ecd,0x1ecd,0x1ecf,0x1ecf, + 0x1ed1,0x1ed1,0x1ed3,0x1ed3,0x1ed5,0x1ed5,0x1ed7,0x1ed7, + 0x1ed9,0x1ed9,0x1edb,0x1edb,0x1edd,0x1edd,0x1edf,0x1edf, + 0x1ee1,0x1ee1,0x1ee3,0x1ee3,0x1ee5,0x1ee5,0x1ee7,0x1ee7, + 0x1ee9,0x1ee9,0x1eeb,0x1eeb,0x1eed,0x1eed,0x1eef,0x1eef, + 0x1ef1,0x1ef1,0x1ef3,0x1ef3,0x1ef5,0x1ef5,0x1ef7,0x1ef7, + 0x1ef9,0x1ef9,0x1efa,0x1efb,0x1efc,0x1efd,0x1efe,0x1eff, + 0x1f00,0x1f01,0x1f02,0x1f03,0x1f04,0x1f05,0x1f06,0x1f07, + 0x1f00,0x1f01,0x1f02,0x1f03,0x1f04,0x1f05,0x1f06,0x1f07, + 0x1f10,0x1f11,0x1f12,0x1f13,0x1f14,0x1f15,0x1f16,0x1f17, + 0x1f10,0x1f11,0x1f12,0x1f13,0x1f14,0x1f15,0x1f1e,0x1f1f, + 0x1f20,0x1f21,0x1f22,0x1f23,0x1f24,0x1f25,0x1f26,0x1f27, + 0x1f20,0x1f21,0x1f22,0x1f23,0x1f24,0x1f25,0x1f26,0x1f27, + 0x1f30,0x1f31,0x1f32,0x1f33,0x1f34,0x1f35,0x1f36,0x1f37, + 0x1f30,0x1f31,0x1f32,0x1f33,0x1f34,0x1f35,0x1f36,0x1f37, + 0x1f40,0x1f41,0x1f42,0x1f43,0x1f44,0x1f45,0x1f46,0x1f47, + 0x1f40,0x1f41,0x1f42,0x1f43,0x1f44,0x1f45,0x1f4e,0x1f4f, + 0x1f50,0x1f51,0x1f52,0x1f53,0x1f54,0x1f55,0x1f56,0x1f57, + 0x1f58,0x1f51,0x1f5a,0x1f53,0x1f5c,0x1f55,0x1f5e,0x1f57, + 0x1f60,0x1f61,0x1f62,0x1f63,0x1f64,0x1f65,0x1f66,0x1f67, + 0x1f60,0x1f61,0x1f62,0x1f63,0x1f64,0x1f65,0x1f66,0x1f67, + 0x1f70,0x1f71,0x1f72,0x1f73,0x1f74,0x1f75,0x1f76,0x1f77, + 0x1f78,0x1f79,0x1f7a,0x1f7b,0x1f7c,0x1f7d,0x1f7e,0x1f7f, + 0x1f80,0x1f81,0x1f82,0x1f83,0x1f84,0x1f85,0x1f86,0x1f87, + 0x1f88,0x1f89,0x1f8a,0x1f8b,0x1f8c,0x1f8d,0x1f8e,0x1f8f, + 0x1f90,0x1f91,0x1f92,0x1f93,0x1f94,0x1f95,0x1f96,0x1f97, + 0x1f98,0x1f99,0x1f9a,0x1f9b,0x1f9c,0x1f9d,0x1f9e,0x1f9f, + 0x1fa0,0x1fa1,0x1fa2,0x1fa3,0x1fa4,0x1fa5,0x1fa6,0x1fa7, + 0x1fa8,0x1fa9,0x1faa,0x1fab,0x1fac,0x1fad,0x1fae,0x1faf, + 0x1fb0,0x1fb1,0x1fb2,0x1fb3,0x1fb4,0x1fb5,0x1fb6,0x1fb7, + 0x1fb0,0x1fb1,0x1f70,0x1f71,0x1fbc,0x1fbd,0x1fbe,0x1fbf, + 0x1fc0,0x1fc1,0x1fc2,0x1fc3,0x1fc4,0x1fc5,0x1fc6,0x1fc7, + 0x1f72,0x1f73,0x1f74,0x1f75,0x1fcc,0x1fcd,0x1fce,0x1fcf, + 0x1fd0,0x1fd1,0x1fd2,0x1fd3,0x1fd4,0x1fd5,0x1fd6,0x1fd7, + 0x1fd0,0x1fd1,0x1f76,0x1f77,0x1fdc,0x1fdd,0x1fde,0x1fdf, + 0x1fe0,0x1fe1,0x1fe2,0x1fe3,0x1fe4,0x1fe5,0x1fe6,0x1fe7, + 0x1fe0,0x1fe1,0x1f7a,0x1f7b,0x1fe5,0x1fed,0x1fee,0x1fef, + 0x1ff0,0x1ff1,0x1ff2,0x1ff3,0x1ff4,0x1ff5,0x1ff6,0x1ff7, + 0x1f78,0x1f79,0x1f7c,0x1f7d,0x1ffc,0x1ffd,0x1ffe,0x1fff, + 0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007, + 0x2008,0x2009,0x200a,0x200b,0x200c,0x200d,0x200e,0x200f, + 0x2010,0x2011,0x2012,0x2013,0x2014,0x2015,0x2016,0x2017, + 0x2018,0x2019,0x201a,0x201b,0x201c,0x201d,0x201e,0x201f, + 0x2020,0x2021,0x2022,0x2023,0x2024,0x2025,0x2026,0x2027, + 0x2028,0x2029,0x202a,0x202b,0x202c,0x202d,0x202e,0x202f, + 0x2030,0x2031,0x2032,0x2033,0x2034,0x2035,0x2036,0x2037, + 0x2038,0x2039,0x203a,0x203b,0x203c,0x203d,0x203e,0x203f, + 0x2040,0x2041,0x2042,0x2043,0x2044,0x2045,0x2046,0x2047, + 0x2048,0x2049,0x204a,0x204b,0x204c,0x204d,0x204e,0x204f, + 0x2050,0x2051,0x2052,0x2053,0x2054,0x2055,0x2056,0x2057, + 0x2058,0x2059,0x205a,0x205b,0x205c,0x205d,0x205e,0x205f, + 0x2060,0x2061,0x2062,0x2063,0x2064,0x2065,0x2066,0x2067, + 0x2068,0x2069,0x206a,0x206b,0x206c,0x206d,0x206e,0x206f, + 0x2070,0x2071,0x2072,0x2073,0x2074,0x2075,0x2076,0x2077, + 0x2078,0x2079,0x207a,0x207b,0x207c,0x207d,0x207e,0x207f, + 0x2080,0x2081,0x2082,0x2083,0x2084,0x2085,0x2086,0x2087, + 0x2088,0x2089,0x208a,0x208b,0x208c,0x208d,0x208e,0x208f, + 0x2090,0x2091,0x2092,0x2093,0x2094,0x2095,0x2096,0x2097, + 0x2098,0x2099,0x209a,0x209b,0x209c,0x209d,0x209e,0x209f, + 0x20a0,0x20a1,0x20a2,0x20a3,0x20a4,0x20a5,0x20a6,0x20a7, + 0x20a8,0x20a9,0x20aa,0x20ab,0x20ac,0x20ad,0x20ae,0x20af, + 0x20b0,0x20b1,0x20b2,0x20b3,0x20b4,0x20b5,0x20b6,0x20b7, + 0x20b8,0x20b9,0x20ba,0x20bb,0x20bc,0x20bd,0x20be,0x20bf, + 0x20c0,0x20c1,0x20c2,0x20c3,0x20c4,0x20c5,0x20c6,0x20c7, + 0x20c8,0x20c9,0x20ca,0x20cb,0x20cc,0x20cd,0x20ce,0x20cf, + 0x20d0,0x20d1,0x20d2,0x20d3,0x20d4,0x20d5,0x20d6,0x20d7, + 0x20d8,0x20d9,0x20da,0x20db,0x20dc,0x20dd,0x20de,0x20df, + 0x20e0,0x20e1,0x20e2,0x20e3,0x20e4,0x20e5,0x20e6,0x20e7, + 0x20e8,0x20e9,0x20ea,0x20eb,0x20ec,0x20ed,0x20ee,0x20ef, + 0x20f0,0x20f1,0x20f2,0x20f3,0x20f4,0x20f5,0x20f6,0x20f7, + 0x20f8,0x20f9,0x20fa,0x20fb,0x20fc,0x20fd,0x20fe,0x20ff, + 0x2100,0x2101,0x2102,0x2103,0x2104,0x2105,0x2106,0x2107, + 0x2108,0x2109,0x210a,0x210b,0x210c,0x210d,0x210e,0x210f, + 0x2110,0x2111,0x2112,0x2113,0x2114,0x2115,0x2116,0x2117, + 0x2118,0x2119,0x211a,0x211b,0x211c,0x211d,0x211e,0x211f, + 0x2120,0x2121,0x2122,0x2123,0x2124,0x2125,0x2126,0x2127, + 0x2128,0x2129,0x212a,0x212b,0x212c,0x212d,0x212e,0x212f, + 0x2130,0x2131,0x2132,0x2133,0x2134,0x2135,0x2136,0x2137, + 0x2138,0x2139,0x213a,0x213b,0x213c,0x213d,0x213e,0x213f, + 0x2140,0x2141,0x2142,0x2143,0x2144,0x2145,0x2146,0x2147, + 0x2148,0x2149,0x214a,0x214b,0x214c,0x214d,0x214e,0x214f, + 0x2150,0x2151,0x2152,0x2153,0x2154,0x2155,0x2156,0x2157, + 0x2158,0x2159,0x215a,0x215b,0x215c,0x215d,0x215e,0x215f, + 0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177, + 0x2178,0x2179,0x217a,0x217b,0x217c,0x217d,0x217e,0x217f, + 0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177, + 0x2178,0x2179,0x217a,0x217b,0x217c,0x217d,0x217e,0x217f, + 0x2180,0x2181,0x2182,0x2183,0x2184,0x2185,0x2186,0x2187, + 0x2188,0x2189,0x218a,0x218b,0x218c,0x218d,0x218e,0x218f, + 0x2190,0x2191,0x2192,0x2193,0x2194,0x2195,0x2196,0x2197, + 0x2198,0x2199,0x219a,0x219b,0x219c,0x219d,0x219e,0x219f, + 0x21a0,0x21a1,0x21a2,0x21a3,0x21a4,0x21a5,0x21a6,0x21a7, + 0x21a8,0x21a9,0x21aa,0x21ab,0x21ac,0x21ad,0x21ae,0x21af, + 0x21b0,0x21b1,0x21b2,0x21b3,0x21b4,0x21b5,0x21b6,0x21b7, + 0x21b8,0x21b9,0x21ba,0x21bb,0x21bc,0x21bd,0x21be,0x21bf, + 0x21c0,0x21c1,0x21c2,0x21c3,0x21c4,0x21c5,0x21c6,0x21c7, + 0x21c8,0x21c9,0x21ca,0x21cb,0x21cc,0x21cd,0x21ce,0x21cf, + 0x21d0,0x21d1,0x21d2,0x21d3,0x21d4,0x21d5,0x21d6,0x21d7, + 0x21d8,0x21d9,0x21da,0x21db,0x21dc,0x21dd,0x21de,0x21df, + 0x21e0,0x21e1,0x21e2,0x21e3,0x21e4,0x21e5,0x21e6,0x21e7, + 0x21e8,0x21e9,0x21ea,0x21eb,0x21ec,0x21ed,0x21ee,0x21ef, + 0x21f0,0x21f1,0x21f2,0x21f3,0x21f4,0x21f5,0x21f6,0x21f7, + 0x21f8,0x21f9,0x21fa,0x21fb,0x21fc,0x21fd,0x21fe,0x21ff, + 0x2200,0x2201,0x2202,0x2203,0x2204,0x2205,0x2206,0x2207, + 0x2208,0x2209,0x220a,0x220b,0x220c,0x220d,0x220e,0x220f, + 0x2210,0x2211,0x2212,0x2213,0x2214,0x2215,0x2216,0x2217, + 0x2218,0x2219,0x221a,0x221b,0x221c,0x221d,0x221e,0x221f, + 0x2220,0x2221,0x2222,0x2223,0x2224,0x2225,0x2226,0x2227, + 0x2228,0x2229,0x222a,0x222b,0x222c,0x222d,0x222e,0x222f, + 0x2230,0x2231,0x2232,0x2233,0x2234,0x2235,0x2236,0x2237, + 0x2238,0x2239,0x223a,0x223b,0x223c,0x223d,0x223e,0x223f, + 0x2240,0x2241,0x2242,0x2243,0x2244,0x2245,0x2246,0x2247, + 0x2248,0x2249,0x224a,0x224b,0x224c,0x224d,0x224e,0x224f, + 0x2250,0x2251,0x2252,0x2253,0x2254,0x2255,0x2256,0x2257, + 0x2258,0x2259,0x225a,0x225b,0x225c,0x225d,0x225e,0x225f, + 0x2260,0x2261,0x2262,0x2263,0x2264,0x2265,0x2266,0x2267, + 0x2268,0x2269,0x226a,0x226b,0x226c,0x226d,0x226e,0x226f, + 0x2270,0x2271,0x2272,0x2273,0x2274,0x2275,0x2276,0x2277, + 0x2278,0x2279,0x227a,0x227b,0x227c,0x227d,0x227e,0x227f, + 0x2280,0x2281,0x2282,0x2283,0x2284,0x2285,0x2286,0x2287, + 0x2288,0x2289,0x228a,0x228b,0x228c,0x228d,0x228e,0x228f, + 0x2290,0x2291,0x2292,0x2293,0x2294,0x2295,0x2296,0x2297, + 0x2298,0x2299,0x229a,0x229b,0x229c,0x229d,0x229e,0x229f, + 0x22a0,0x22a1,0x22a2,0x22a3,0x22a4,0x22a5,0x22a6,0x22a7, + 0x22a8,0x22a9,0x22aa,0x22ab,0x22ac,0x22ad,0x22ae,0x22af, + 0x22b0,0x22b1,0x22b2,0x22b3,0x22b4,0x22b5,0x22b6,0x22b7, + 0x22b8,0x22b9,0x22ba,0x22bb,0x22bc,0x22bd,0x22be,0x22bf, + 0x22c0,0x22c1,0x22c2,0x22c3,0x22c4,0x22c5,0x22c6,0x22c7, + 0x22c8,0x22c9,0x22ca,0x22cb,0x22cc,0x22cd,0x22ce,0x22cf, + 0x22d0,0x22d1,0x22d2,0x22d3,0x22d4,0x22d5,0x22d6,0x22d7, + 0x22d8,0x22d9,0x22da,0x22db,0x22dc,0x22dd,0x22de,0x22df, + 0x22e0,0x22e1,0x22e2,0x22e3,0x22e4,0x22e5,0x22e6,0x22e7, + 0x22e8,0x22e9,0x22ea,0x22eb,0x22ec,0x22ed,0x22ee,0x22ef, + 0x22f0,0x22f1,0x22f2,0x22f3,0x22f4,0x22f5,0x22f6,0x22f7, + 0x22f8,0x22f9,0x22fa,0x22fb,0x22fc,0x22fd,0x22fe,0x22ff, + 0x2300,0x2301,0x2302,0x2303,0x2304,0x2305,0x2306,0x2307, + 0x2308,0x2309,0x230a,0x230b,0x230c,0x230d,0x230e,0x230f, + 0x2310,0x2311,0x2312,0x2313,0x2314,0x2315,0x2316,0x2317, + 0x2318,0x2319,0x231a,0x231b,0x231c,0x231d,0x231e,0x231f, + 0x2320,0x2321,0x2322,0x2323,0x2324,0x2325,0x2326,0x2327, + 0x2328,0x2329,0x232a,0x232b,0x232c,0x232d,0x232e,0x232f, + 0x2330,0x2331,0x2332,0x2333,0x2334,0x2335,0x2336,0x2337, + 0x2338,0x2339,0x233a,0x233b,0x233c,0x233d,0x233e,0x233f, + 0x2340,0x2341,0x2342,0x2343,0x2344,0x2345,0x2346,0x2347, + 0x2348,0x2349,0x234a,0x234b,0x234c,0x234d,0x234e,0x234f, + 0x2350,0x2351,0x2352,0x2353,0x2354,0x2355,0x2356,0x2357, + 0x2358,0x2359,0x235a,0x235b,0x235c,0x235d,0x235e,0x235f, + 0x2360,0x2361,0x2362,0x2363,0x2364,0x2365,0x2366,0x2367, + 0x2368,0x2369,0x236a,0x236b,0x236c,0x236d,0x236e,0x236f, + 0x2370,0x2371,0x2372,0x2373,0x2374,0x2375,0x2376,0x2377, + 0x2378,0x2379,0x237a,0x237b,0x237c,0x237d,0x237e,0x237f, + 0x2380,0x2381,0x2382,0x2383,0x2384,0x2385,0x2386,0x2387, + 0x2388,0x2389,0x238a,0x238b,0x238c,0x238d,0x238e,0x238f, + 0x2390,0x2391,0x2392,0x2393,0x2394,0x2395,0x2396,0x2397, + 0x2398,0x2399,0x239a,0x239b,0x239c,0x239d,0x239e,0x239f, + 0x23a0,0x23a1,0x23a2,0x23a3,0x23a4,0x23a5,0x23a6,0x23a7, + 0x23a8,0x23a9,0x23aa,0x23ab,0x23ac,0x23ad,0x23ae,0x23af, + 0x23b0,0x23b1,0x23b2,0x23b3,0x23b4,0x23b5,0x23b6,0x23b7, + 0x23b8,0x23b9,0x23ba,0x23bb,0x23bc,0x23bd,0x23be,0x23bf, + 0x23c0,0x23c1,0x23c2,0x23c3,0x23c4,0x23c5,0x23c6,0x23c7, + 0x23c8,0x23c9,0x23ca,0x23cb,0x23cc,0x23cd,0x23ce,0x23cf, + 0x23d0,0x23d1,0x23d2,0x23d3,0x23d4,0x23d5,0x23d6,0x23d7, + 0x23d8,0x23d9,0x23da,0x23db,0x23dc,0x23dd,0x23de,0x23df, + 0x23e0,0x23e1,0x23e2,0x23e3,0x23e4,0x23e5,0x23e6,0x23e7, + 0x23e8,0x23e9,0x23ea,0x23eb,0x23ec,0x23ed,0x23ee,0x23ef, + 0x23f0,0x23f1,0x23f2,0x23f3,0x23f4,0x23f5,0x23f6,0x23f7, + 0x23f8,0x23f9,0x23fa,0x23fb,0x23fc,0x23fd,0x23fe,0x23ff, + 0x2400,0x2401,0x2402,0x2403,0x2404,0x2405,0x2406,0x2407, + 0x2408,0x2409,0x240a,0x240b,0x240c,0x240d,0x240e,0x240f, + 0x2410,0x2411,0x2412,0x2413,0x2414,0x2415,0x2416,0x2417, + 0x2418,0x2419,0x241a,0x241b,0x241c,0x241d,0x241e,0x241f, + 0x2420,0x2421,0x2422,0x2423,0x2424,0x2425,0x2426,0x2427, + 0x2428,0x2429,0x242a,0x242b,0x242c,0x242d,0x242e,0x242f, + 0x2430,0x2431,0x2432,0x2433,0x2434,0x2435,0x2436,0x2437, + 0x2438,0x2439,0x243a,0x243b,0x243c,0x243d,0x243e,0x243f, + 0x2440,0x2441,0x2442,0x2443,0x2444,0x2445,0x2446,0x2447, + 0x2448,0x2449,0x244a,0x244b,0x244c,0x244d,0x244e,0x244f, + 0x2450,0x2451,0x2452,0x2453,0x2454,0x2455,0x2456,0x2457, + 0x2458,0x2459,0x245a,0x245b,0x245c,0x245d,0x245e,0x245f, + 0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467, + 0x2468,0x2469,0x246a,0x246b,0x246c,0x246d,0x246e,0x246f, + 0x2470,0x2471,0x2472,0x2473,0x2474,0x2475,0x2476,0x2477, + 0x2478,0x2479,0x247a,0x247b,0x247c,0x247d,0x247e,0x247f, + 0x2480,0x2481,0x2482,0x2483,0x2484,0x2485,0x2486,0x2487, + 0x2488,0x2489,0x248a,0x248b,0x248c,0x248d,0x248e,0x248f, + 0x2490,0x2491,0x2492,0x2493,0x2494,0x2495,0x2496,0x2497, + 0x2498,0x2499,0x249a,0x249b,0x249c,0x249d,0x249e,0x249f, + 0x24a0,0x24a1,0x24a2,0x24a3,0x24a4,0x24a5,0x24a6,0x24a7, + 0x24a8,0x24a9,0x24aa,0x24ab,0x24ac,0x24ad,0x24ae,0x24af, + 0x24b0,0x24b1,0x24b2,0x24b3,0x24b4,0x24b5,0x24d0,0x24d1, + 0x24d2,0x24d3,0x24d4,0x24d5,0x24d6,0x24d7,0x24d8,0x24d9, + 0x24da,0x24db,0x24dc,0x24dd,0x24de,0x24df,0x24e0,0x24e1, + 0x24e2,0x24e3,0x24e4,0x24e5,0x24e6,0x24e7,0x24e8,0x24e9, + 0x24d0,0x24d1,0x24d2,0x24d3,0x24d4,0x24d5,0x24d6,0x24d7, + 0x24d8,0x24d9,0x24da,0x24db,0x24dc,0x24dd,0x24de,0x24df, + 0x24e0,0x24e1,0x24e2,0x24e3,0x24e4,0x24e5,0x24e6,0x24e7, + 0x24e8,0x24e9,0x24ea,0x24eb,0x24ec,0x24ed,0x24ee,0x24ef, + 0x24f0,0x24f1,0x24f2,0x24f3,0x24f4,0x24f5,0x24f6,0x24f7, + 0x24f8,0x24f9,0x24fa,0x24fb,0x24fc,0x24fd,0x24fe,0x24ff, + 0x2500,0x2501,0x2502,0x2503,0x2504,0x2505,0x2506,0x2507, + 0x2508,0x2509,0x250a,0x250b,0x250c,0x250d,0x250e,0x250f, + 0x2510,0x2511,0x2512,0x2513,0x2514,0x2515,0x2516,0x2517, + 0x2518,0x2519,0x251a,0x251b,0x251c,0x251d,0x251e,0x251f, + 0x2520,0x2521,0x2522,0x2523,0x2524,0x2525,0x2526,0x2527, + 0x2528,0x2529,0x252a,0x252b,0x252c,0x252d,0x252e,0x252f, + 0x2530,0x2531,0x2532,0x2533,0x2534,0x2535,0x2536,0x2537, + 0x2538,0x2539,0x253a,0x253b,0x253c,0x253d,0x253e,0x253f, + 0x2540,0x2541,0x2542,0x2543,0x2544,0x2545,0x2546,0x2547, + 0x2548,0x2549,0x254a,0x254b,0x254c,0x254d,0x254e,0x254f, + 0x2550,0x2551,0x2552,0x2553,0x2554,0x2555,0x2556,0x2557, + 0x2558,0x2559,0x255a,0x255b,0x255c,0x255d,0x255e,0x255f, + 0x2560,0x2561,0x2562,0x2563,0x2564,0x2565,0x2566,0x2567, + 0x2568,0x2569,0x256a,0x256b,0x256c,0x256d,0x256e,0x256f, + 0x2570,0x2571,0x2572,0x2573,0x2574,0x2575,0x2576,0x2577, + 0x2578,0x2579,0x257a,0x257b,0x257c,0x257d,0x257e,0x257f, + 0x2580,0x2581,0x2582,0x2583,0x2584,0x2585,0x2586,0x2587, + 0x2588,0x2589,0x258a,0x258b,0x258c,0x258d,0x258e,0x258f, + 0x2590,0x2591,0x2592,0x2593,0x2594,0x2595,0x2596,0x2597, + 0x2598,0x2599,0x259a,0x259b,0x259c,0x259d,0x259e,0x259f, + 0x25a0,0x25a1,0x25a2,0x25a3,0x25a4,0x25a5,0x25a6,0x25a7, + 0x25a8,0x25a9,0x25aa,0x25ab,0x25ac,0x25ad,0x25ae,0x25af, + 0x25b0,0x25b1,0x25b2,0x25b3,0x25b4,0x25b5,0x25b6,0x25b7, + 0x25b8,0x25b9,0x25ba,0x25bb,0x25bc,0x25bd,0x25be,0x25bf, + 0x25c0,0x25c1,0x25c2,0x25c3,0x25c4,0x25c5,0x25c6,0x25c7, + 0x25c8,0x25c9,0x25ca,0x25cb,0x25cc,0x25cd,0x25ce,0x25cf, + 0x25d0,0x25d1,0x25d2,0x25d3,0x25d4,0x25d5,0x25d6,0x25d7, + 0x25d8,0x25d9,0x25da,0x25db,0x25dc,0x25dd,0x25de,0x25df, + 0x25e0,0x25e1,0x25e2,0x25e3,0x25e4,0x25e5,0x25e6,0x25e7, + 0x25e8,0x25e9,0x25ea,0x25eb,0x25ec,0x25ed,0x25ee,0x25ef, + 0x25f0,0x25f1,0x25f2,0x25f3,0x25f4,0x25f5,0x25f6,0x25f7, + 0x25f8,0x25f9,0x25fa,0x25fb,0x25fc,0x25fd,0x25fe,0x25ff, + 0x2600,0x2601,0x2602,0x2603,0x2604,0x2605,0x2606,0x2607, + 0x2608,0x2609,0x260a,0x260b,0x260c,0x260d,0x260e,0x260f, + 0x2610,0x2611,0x2612,0x2613,0x2614,0x2615,0x2616,0x2617, + 0x2618,0x2619,0x261a,0x261b,0x261c,0x261d,0x261e,0x261f, + 0x2620,0x2621,0x2622,0x2623,0x2624,0x2625,0x2626,0x2627, + 0x2628,0x2629,0x262a,0x262b,0x262c,0x262d,0x262e,0x262f, + 0x2630,0x2631,0x2632,0x2633,0x2634,0x2635,0x2636,0x2637, + 0x2638,0x2639,0x263a,0x263b,0x263c,0x263d,0x263e,0x263f, + 0x2640,0x2641,0x2642,0x2643,0x2644,0x2645,0x2646,0x2647, + 0x2648,0x2649,0x264a,0x264b,0x264c,0x264d,0x264e,0x264f, + 0x2650,0x2651,0x2652,0x2653,0x2654,0x2655,0x2656,0x2657, + 0x2658,0x2659,0x265a,0x265b,0x265c,0x265d,0x265e,0x265f, + 0x2660,0x2661,0x2662,0x2663,0x2664,0x2665,0x2666,0x2667, + 0x2668,0x2669,0x266a,0x266b,0x266c,0x266d,0x266e,0x266f, + 0x2670,0x2671,0x2672,0x2673,0x2674,0x2675,0x2676,0x2677, + 0x2678,0x2679,0x267a,0x267b,0x267c,0x267d,0x267e,0x267f, + 0x2680,0x2681,0x2682,0x2683,0x2684,0x2685,0x2686,0x2687, + 0x2688,0x2689,0x268a,0x268b,0x268c,0x268d,0x268e,0x268f, + 0x2690,0x2691,0x2692,0x2693,0x2694,0x2695,0x2696,0x2697, + 0x2698,0x2699,0x269a,0x269b,0x269c,0x269d,0x269e,0x269f, + 0x26a0,0x26a1,0x26a2,0x26a3,0x26a4,0x26a5,0x26a6,0x26a7, + 0x26a8,0x26a9,0x26aa,0x26ab,0x26ac,0x26ad,0x26ae,0x26af, + 0x26b0,0x26b1,0x26b2,0x26b3,0x26b4,0x26b5,0x26b6,0x26b7, + 0x26b8,0x26b9,0x26ba,0x26bb,0x26bc,0x26bd,0x26be,0x26bf, + 0x26c0,0x26c1,0x26c2,0x26c3,0x26c4,0x26c5,0x26c6,0x26c7, + 0x26c8,0x26c9,0x26ca,0x26cb,0x26cc,0x26cd,0x26ce,0x26cf, + 0x26d0,0x26d1,0x26d2,0x26d3,0x26d4,0x26d5,0x26d6,0x26d7, + 0x26d8,0x26d9,0x26da,0x26db,0x26dc,0x26dd,0x26de,0x26df, + 0x26e0,0x26e1,0x26e2,0x26e3,0x26e4,0x26e5,0x26e6,0x26e7, + 0x26e8,0x26e9,0x26ea,0x26eb,0x26ec,0x26ed,0x26ee,0x26ef, + 0x26f0,0x26f1,0x26f2,0x26f3,0x26f4,0x26f5,0x26f6,0x26f7, + 0x26f8,0x26f9,0x26fa,0x26fb,0x26fc,0x26fd,0x26fe,0x26ff, + 0x2700,0x2701,0x2702,0x2703,0x2704,0x2705,0x2706,0x2707, + 0x2708,0x2709,0x270a,0x270b,0x270c,0x270d,0x270e,0x270f, + 0x2710,0x2711,0x2712,0x2713,0x2714,0x2715,0x2716,0x2717, + 0x2718,0x2719,0x271a,0x271b,0x271c,0x271d,0x271e,0x271f, + 0x2720,0x2721,0x2722,0x2723,0x2724,0x2725,0x2726,0x2727, + 0x2728,0x2729,0x272a,0x272b,0x272c,0x272d,0x272e,0x272f, + 0x2730,0x2731,0x2732,0x2733,0x2734,0x2735,0x2736,0x2737, + 0x2738,0x2739,0x273a,0x273b,0x273c,0x273d,0x273e,0x273f, + 0x2740,0x2741,0x2742,0x2743,0x2744,0x2745,0x2746,0x2747, + 0x2748,0x2749,0x274a,0x274b,0x274c,0x274d,0x274e,0x274f, + 0x2750,0x2751,0x2752,0x2753,0x2754,0x2755,0x2756,0x2757, + 0x2758,0x2759,0x275a,0x275b,0x275c,0x275d,0x275e,0x275f, + 0x2760,0x2761,0x2762,0x2763,0x2764,0x2765,0x2766,0x2767, + 0x2768,0x2769,0x276a,0x276b,0x276c,0x276d,0x276e,0x276f, + 0x2770,0x2771,0x2772,0x2773,0x2774,0x2775,0x2776,0x2777, + 0x2778,0x2779,0x277a,0x277b,0x277c,0x277d,0x277e,0x277f, + 0x2780,0x2781,0x2782,0x2783,0x2784,0x2785,0x2786,0x2787, + 0x2788,0x2789,0x278a,0x278b,0x278c,0x278d,0x278e,0x278f, + 0x2790,0x2791,0x2792,0x2793,0x2794,0x2795,0x2796,0x2797, + 0x2798,0x2799,0x279a,0x279b,0x279c,0x279d,0x279e,0x279f, + 0x27a0,0x27a1,0x27a2,0x27a3,0x27a4,0x27a5,0x27a6,0x27a7, + 0x27a8,0x27a9,0x27aa,0x27ab,0x27ac,0x27ad,0x27ae,0x27af, + 0x27b0,0x27b1,0x27b2,0x27b3,0x27b4,0x27b5,0x27b6,0x27b7, + 0x27b8,0x27b9,0x27ba,0x27bb,0x27bc,0x27bd,0x27be,0x27bf, + 0x27c0,0x27c1,0x27c2,0x27c3,0x27c4,0x27c5,0x27c6,0x27c7, + 0x27c8,0x27c9,0x27ca,0x27cb,0x27cc,0x27cd,0x27ce,0x27cf, + 0x27d0,0x27d1,0x27d2,0x27d3,0x27d4,0x27d5,0x27d6,0x27d7, + 0x27d8,0x27d9,0x27da,0x27db,0x27dc,0x27dd,0x27de,0x27df, + 0x27e0,0x27e1,0x27e2,0x27e3,0x27e4,0x27e5,0x27e6,0x27e7, + 0x27e8,0x27e9,0x27ea,0x27eb,0x27ec,0x27ed,0x27ee,0x27ef, + 0x27f0,0x27f1,0x27f2,0x27f3,0x27f4,0x27f5,0x27f6,0x27f7, + 0x27f8,0x27f9,0x27fa,0x27fb,0x27fc,0x27fd,0x27fe,0x27ff, + 0x2800,0x2801,0x2802,0x2803,0x2804,0x2805,0x2806,0x2807, + 0x2808,0x2809,0x280a,0x280b,0x280c,0x280d,0x280e,0x280f, + 0x2810,0x2811,0x2812,0x2813,0x2814,0x2815,0x2816,0x2817, + 0x2818,0x2819,0x281a,0x281b,0x281c,0x281d,0x281e,0x281f, + 0x2820,0x2821,0x2822,0x2823,0x2824,0x2825,0x2826,0x2827, + 0x2828,0x2829,0x282a,0x282b,0x282c,0x282d,0x282e,0x282f, + 0x2830,0x2831,0x2832,0x2833,0x2834,0x2835,0x2836,0x2837, + 0x2838,0x2839,0x283a,0x283b,0x283c,0x283d,0x283e,0x283f, + 0x2840,0x2841,0x2842,0x2843,0x2844,0x2845,0x2846,0x2847, + 0x2848,0x2849,0x284a,0x284b,0x284c,0x284d,0x284e,0x284f, + 0x2850,0x2851,0x2852,0x2853,0x2854,0x2855,0x2856,0x2857, + 0x2858,0x2859,0x285a,0x285b,0x285c,0x285d,0x285e,0x285f, + 0x2860,0x2861,0x2862,0x2863,0x2864,0x2865,0x2866,0x2867, + 0x2868,0x2869,0x286a,0x286b,0x286c,0x286d,0x286e,0x286f, + 0x2870,0x2871,0x2872,0x2873,0x2874,0x2875,0x2876,0x2877, + 0x2878,0x2879,0x287a,0x287b,0x287c,0x287d,0x287e,0x287f, + 0x2880,0x2881,0x2882,0x2883,0x2884,0x2885,0x2886,0x2887, + 0x2888,0x2889,0x288a,0x288b,0x288c,0x288d,0x288e,0x288f, + 0x2890,0x2891,0x2892,0x2893,0x2894,0x2895,0x2896,0x2897, + 0x2898,0x2899,0x289a,0x289b,0x289c,0x289d,0x289e,0x289f, + 0x28a0,0x28a1,0x28a2,0x28a3,0x28a4,0x28a5,0x28a6,0x28a7, + 0x28a8,0x28a9,0x28aa,0x28ab,0x28ac,0x28ad,0x28ae,0x28af, + 0x28b0,0x28b1,0x28b2,0x28b3,0x28b4,0x28b5,0x28b6,0x28b7, + 0x28b8,0x28b9,0x28ba,0x28bb,0x28bc,0x28bd,0x28be,0x28bf, + 0x28c0,0x28c1,0x28c2,0x28c3,0x28c4,0x28c5,0x28c6,0x28c7, + 0x28c8,0x28c9,0x28ca,0x28cb,0x28cc,0x28cd,0x28ce,0x28cf, + 0x28d0,0x28d1,0x28d2,0x28d3,0x28d4,0x28d5,0x28d6,0x28d7, + 0x28d8,0x28d9,0x28da,0x28db,0x28dc,0x28dd,0x28de,0x28df, + 0x28e0,0x28e1,0x28e2,0x28e3,0x28e4,0x28e5,0x28e6,0x28e7, + 0x28e8,0x28e9,0x28ea,0x28eb,0x28ec,0x28ed,0x28ee,0x28ef, + 0x28f0,0x28f1,0x28f2,0x28f3,0x28f4,0x28f5,0x28f6,0x28f7, + 0x28f8,0x28f9,0x28fa,0x28fb,0x28fc,0x28fd,0x28fe,0x28ff, + 0x2900,0x2901,0x2902,0x2903,0x2904,0x2905,0x2906,0x2907, + 0x2908,0x2909,0x290a,0x290b,0x290c,0x290d,0x290e,0x290f, + 0x2910,0x2911,0x2912,0x2913,0x2914,0x2915,0x2916,0x2917, + 0x2918,0x2919,0x291a,0x291b,0x291c,0x291d,0x291e,0x291f, + 0x2920,0x2921,0x2922,0x2923,0x2924,0x2925,0x2926,0x2927, + 0x2928,0x2929,0x292a,0x292b,0x292c,0x292d,0x292e,0x292f, + 0x2930,0x2931,0x2932,0x2933,0x2934,0x2935,0x2936,0x2937, + 0x2938,0x2939,0x293a,0x293b,0x293c,0x293d,0x293e,0x293f, + 0x2940,0x2941,0x2942,0x2943,0x2944,0x2945,0x2946,0x2947, + 0x2948,0x2949,0x294a,0x294b,0x294c,0x294d,0x294e,0x294f, + 0x2950,0x2951,0x2952,0x2953,0x2954,0x2955,0x2956,0x2957, + 0x2958,0x2959,0x295a,0x295b,0x295c,0x295d,0x295e,0x295f, + 0x2960,0x2961,0x2962,0x2963,0x2964,0x2965,0x2966,0x2967, + 0x2968,0x2969,0x296a,0x296b,0x296c,0x296d,0x296e,0x296f, + 0x2970,0x2971,0x2972,0x2973,0x2974,0x2975,0x2976,0x2977, + 0x2978,0x2979,0x297a,0x297b,0x297c,0x297d,0x297e,0x297f, + 0x2980,0x2981,0x2982,0x2983,0x2984,0x2985,0x2986,0x2987, + 0x2988,0x2989,0x298a,0x298b,0x298c,0x298d,0x298e,0x298f, + 0x2990,0x2991,0x2992,0x2993,0x2994,0x2995,0x2996,0x2997, + 0x2998,0x2999,0x299a,0x299b,0x299c,0x299d,0x299e,0x299f, + 0x29a0,0x29a1,0x29a2,0x29a3,0x29a4,0x29a5,0x29a6,0x29a7, + 0x29a8,0x29a9,0x29aa,0x29ab,0x29ac,0x29ad,0x29ae,0x29af, + 0x29b0,0x29b1,0x29b2,0x29b3,0x29b4,0x29b5,0x29b6,0x29b7, + 0x29b8,0x29b9,0x29ba,0x29bb,0x29bc,0x29bd,0x29be,0x29bf, + 0x29c0,0x29c1,0x29c2,0x29c3,0x29c4,0x29c5,0x29c6,0x29c7, + 0x29c8,0x29c9,0x29ca,0x29cb,0x29cc,0x29cd,0x29ce,0x29cf, + 0x29d0,0x29d1,0x29d2,0x29d3,0x29d4,0x29d5,0x29d6,0x29d7, + 0x29d8,0x29d9,0x29da,0x29db,0x29dc,0x29dd,0x29de,0x29df, + 0x29e0,0x29e1,0x29e2,0x29e3,0x29e4,0x29e5,0x29e6,0x29e7, + 0x29e8,0x29e9,0x29ea,0x29eb,0x29ec,0x29ed,0x29ee,0x29ef, + 0x29f0,0x29f1,0x29f2,0x29f3,0x29f4,0x29f5,0x29f6,0x29f7, + 0x29f8,0x29f9,0x29fa,0x29fb,0x29fc,0x29fd,0x29fe,0x29ff, + 0x2a00,0x2a01,0x2a02,0x2a03,0x2a04,0x2a05,0x2a06,0x2a07, + 0x2a08,0x2a09,0x2a0a,0x2a0b,0x2a0c,0x2a0d,0x2a0e,0x2a0f, + 0x2a10,0x2a11,0x2a12,0x2a13,0x2a14,0x2a15,0x2a16,0x2a17, + 0x2a18,0x2a19,0x2a1a,0x2a1b,0x2a1c,0x2a1d,0x2a1e,0x2a1f, + 0x2a20,0x2a21,0x2a22,0x2a23,0x2a24,0x2a25,0x2a26,0x2a27, + 0x2a28,0x2a29,0x2a2a,0x2a2b,0x2a2c,0x2a2d,0x2a2e,0x2a2f, + 0x2a30,0x2a31,0x2a32,0x2a33,0x2a34,0x2a35,0x2a36,0x2a37, + 0x2a38,0x2a39,0x2a3a,0x2a3b,0x2a3c,0x2a3d,0x2a3e,0x2a3f, + 0x2a40,0x2a41,0x2a42,0x2a43,0x2a44,0x2a45,0x2a46,0x2a47, + 0x2a48,0x2a49,0x2a4a,0x2a4b,0x2a4c,0x2a4d,0x2a4e,0x2a4f, + 0x2a50,0x2a51,0x2a52,0x2a53,0x2a54,0x2a55,0x2a56,0x2a57, + 0x2a58,0x2a59,0x2a5a,0x2a5b,0x2a5c,0x2a5d,0x2a5e,0x2a5f, + 0x2a60,0x2a61,0x2a62,0x2a63,0x2a64,0x2a65,0x2a66,0x2a67, + 0x2a68,0x2a69,0x2a6a,0x2a6b,0x2a6c,0x2a6d,0x2a6e,0x2a6f, + 0x2a70,0x2a71,0x2a72,0x2a73,0x2a74,0x2a75,0x2a76,0x2a77, + 0x2a78,0x2a79,0x2a7a,0x2a7b,0x2a7c,0x2a7d,0x2a7e,0x2a7f, + 0x2a80,0x2a81,0x2a82,0x2a83,0x2a84,0x2a85,0x2a86,0x2a87, + 0x2a88,0x2a89,0x2a8a,0x2a8b,0x2a8c,0x2a8d,0x2a8e,0x2a8f, + 0x2a90,0x2a91,0x2a92,0x2a93,0x2a94,0x2a95,0x2a96,0x2a97, + 0x2a98,0x2a99,0x2a9a,0x2a9b,0x2a9c,0x2a9d,0x2a9e,0x2a9f, + 0x2aa0,0x2aa1,0x2aa2,0x2aa3,0x2aa4,0x2aa5,0x2aa6,0x2aa7, + 0x2aa8,0x2aa9,0x2aaa,0x2aab,0x2aac,0x2aad,0x2aae,0x2aaf, + 0x2ab0,0x2ab1,0x2ab2,0x2ab3,0x2ab4,0x2ab5,0x2ab6,0x2ab7, + 0x2ab8,0x2ab9,0x2aba,0x2abb,0x2abc,0x2abd,0x2abe,0x2abf, + 0x2ac0,0x2ac1,0x2ac2,0x2ac3,0x2ac4,0x2ac5,0x2ac6,0x2ac7, + 0x2ac8,0x2ac9,0x2aca,0x2acb,0x2acc,0x2acd,0x2ace,0x2acf, + 0x2ad0,0x2ad1,0x2ad2,0x2ad3,0x2ad4,0x2ad5,0x2ad6,0x2ad7, + 0x2ad8,0x2ad9,0x2ada,0x2adb,0x2adc,0x2add,0x2ade,0x2adf, + 0x2ae0,0x2ae1,0x2ae2,0x2ae3,0x2ae4,0x2ae5,0x2ae6,0x2ae7, + 0x2ae8,0x2ae9,0x2aea,0x2aeb,0x2aec,0x2aed,0x2aee,0x2aef, + 0x2af0,0x2af1,0x2af2,0x2af3,0x2af4,0x2af5,0x2af6,0x2af7, + 0x2af8,0x2af9,0x2afa,0x2afb,0x2afc,0x2afd,0x2afe,0x2aff, + 0x2b00,0x2b01,0x2b02,0x2b03,0x2b04,0x2b05,0x2b06,0x2b07, + 0x2b08,0x2b09,0x2b0a,0x2b0b,0x2b0c,0x2b0d,0x2b0e,0x2b0f, + 0x2b10,0x2b11,0x2b12,0x2b13,0x2b14,0x2b15,0x2b16,0x2b17, + 0x2b18,0x2b19,0x2b1a,0x2b1b,0x2b1c,0x2b1d,0x2b1e,0x2b1f, + 0x2b20,0x2b21,0x2b22,0x2b23,0x2b24,0x2b25,0x2b26,0x2b27, + 0x2b28,0x2b29,0x2b2a,0x2b2b,0x2b2c,0x2b2d,0x2b2e,0x2b2f, + 0x2b30,0x2b31,0x2b32,0x2b33,0x2b34,0x2b35,0x2b36,0x2b37, + 0x2b38,0x2b39,0x2b3a,0x2b3b,0x2b3c,0x2b3d,0x2b3e,0x2b3f, + 0x2b40,0x2b41,0x2b42,0x2b43,0x2b44,0x2b45,0x2b46,0x2b47, + 0x2b48,0x2b49,0x2b4a,0x2b4b,0x2b4c,0x2b4d,0x2b4e,0x2b4f, + 0x2b50,0x2b51,0x2b52,0x2b53,0x2b54,0x2b55,0x2b56,0x2b57, + 0x2b58,0x2b59,0x2b5a,0x2b5b,0x2b5c,0x2b5d,0x2b5e,0x2b5f, + 0x2b60,0x2b61,0x2b62,0x2b63,0x2b64,0x2b65,0x2b66,0x2b67, + 0x2b68,0x2b69,0x2b6a,0x2b6b,0x2b6c,0x2b6d,0x2b6e,0x2b6f, + 0x2b70,0x2b71,0x2b72,0x2b73,0x2b74,0x2b75,0x2b76,0x2b77, + 0x2b78,0x2b79,0x2b7a,0x2b7b,0x2b7c,0x2b7d,0x2b7e,0x2b7f, + 0x2b80,0x2b81,0x2b82,0x2b83,0x2b84,0x2b85,0x2b86,0x2b87, + 0x2b88,0x2b89,0x2b8a,0x2b8b,0x2b8c,0x2b8d,0x2b8e,0x2b8f, + 0x2b90,0x2b91,0x2b92,0x2b93,0x2b94,0x2b95,0x2b96,0x2b97, + 0x2b98,0x2b99,0x2b9a,0x2b9b,0x2b9c,0x2b9d,0x2b9e,0x2b9f, + 0x2ba0,0x2ba1,0x2ba2,0x2ba3,0x2ba4,0x2ba5,0x2ba6,0x2ba7, + 0x2ba8,0x2ba9,0x2baa,0x2bab,0x2bac,0x2bad,0x2bae,0x2baf, + 0x2bb0,0x2bb1,0x2bb2,0x2bb3,0x2bb4,0x2bb5,0x2bb6,0x2bb7, + 0x2bb8,0x2bb9,0x2bba,0x2bbb,0x2bbc,0x2bbd,0x2bbe,0x2bbf, + 0x2bc0,0x2bc1,0x2bc2,0x2bc3,0x2bc4,0x2bc5,0x2bc6,0x2bc7, + 0x2bc8,0x2bc9,0x2bca,0x2bcb,0x2bcc,0x2bcd,0x2bce,0x2bcf, + 0x2bd0,0x2bd1,0x2bd2,0x2bd3,0x2bd4,0x2bd5,0x2bd6,0x2bd7, + 0x2bd8,0x2bd9,0x2bda,0x2bdb,0x2bdc,0x2bdd,0x2bde,0x2bdf, + 0x2be0,0x2be1,0x2be2,0x2be3,0x2be4,0x2be5,0x2be6,0x2be7, + 0x2be8,0x2be9,0x2bea,0x2beb,0x2bec,0x2bed,0x2bee,0x2bef, + 0x2bf0,0x2bf1,0x2bf2,0x2bf3,0x2bf4,0x2bf5,0x2bf6,0x2bf7, + 0x2bf8,0x2bf9,0x2bfa,0x2bfb,0x2bfc,0x2bfd,0x2bfe,0x2bff, + 0x2c00,0x2c01,0x2c02,0x2c03,0x2c04,0x2c05,0x2c06,0x2c07, + 0x2c08,0x2c09,0x2c0a,0x2c0b,0x2c0c,0x2c0d,0x2c0e,0x2c0f, + 0x2c10,0x2c11,0x2c12,0x2c13,0x2c14,0x2c15,0x2c16,0x2c17, + 0x2c18,0x2c19,0x2c1a,0x2c1b,0x2c1c,0x2c1d,0x2c1e,0x2c1f, + 0x2c20,0x2c21,0x2c22,0x2c23,0x2c24,0x2c25,0x2c26,0x2c27, + 0x2c28,0x2c29,0x2c2a,0x2c2b,0x2c2c,0x2c2d,0x2c2e,0x2c2f, + 0x2c30,0x2c31,0x2c32,0x2c33,0x2c34,0x2c35,0x2c36,0x2c37, + 0x2c38,0x2c39,0x2c3a,0x2c3b,0x2c3c,0x2c3d,0x2c3e,0x2c3f, + 0x2c40,0x2c41,0x2c42,0x2c43,0x2c44,0x2c45,0x2c46,0x2c47, + 0x2c48,0x2c49,0x2c4a,0x2c4b,0x2c4c,0x2c4d,0x2c4e,0x2c4f, + 0x2c50,0x2c51,0x2c52,0x2c53,0x2c54,0x2c55,0x2c56,0x2c57, + 0x2c58,0x2c59,0x2c5a,0x2c5b,0x2c5c,0x2c5d,0x2c5e,0x2c5f, + 0x2c60,0x2c61,0x2c62,0x2c63,0x2c64,0x2c65,0x2c66,0x2c67, + 0x2c68,0x2c69,0x2c6a,0x2c6b,0x2c6c,0x2c6d,0x2c6e,0x2c6f, + 0x2c70,0x2c71,0x2c72,0x2c73,0x2c74,0x2c75,0x2c76,0x2c77, + 0x2c78,0x2c79,0x2c7a,0x2c7b,0x2c7c,0x2c7d,0x2c7e,0x2c7f, + 0x2c80,0x2c81,0x2c82,0x2c83,0x2c84,0x2c85,0x2c86,0x2c87, + 0x2c88,0x2c89,0x2c8a,0x2c8b,0x2c8c,0x2c8d,0x2c8e,0x2c8f, + 0x2c90,0x2c91,0x2c92,0x2c93,0x2c94,0x2c95,0x2c96,0x2c97, + 0x2c98,0x2c99,0x2c9a,0x2c9b,0x2c9c,0x2c9d,0x2c9e,0x2c9f, + 0x2ca0,0x2ca1,0x2ca2,0x2ca3,0x2ca4,0x2ca5,0x2ca6,0x2ca7, + 0x2ca8,0x2ca9,0x2caa,0x2cab,0x2cac,0x2cad,0x2cae,0x2caf, + 0x2cb0,0x2cb1,0x2cb2,0x2cb3,0x2cb4,0x2cb5,0x2cb6,0x2cb7, + 0x2cb8,0x2cb9,0x2cba,0x2cbb,0x2cbc,0x2cbd,0x2cbe,0x2cbf, + 0x2cc0,0x2cc1,0x2cc2,0x2cc3,0x2cc4,0x2cc5,0x2cc6,0x2cc7, + 0x2cc8,0x2cc9,0x2cca,0x2ccb,0x2ccc,0x2ccd,0x2cce,0x2ccf, + 0x2cd0,0x2cd1,0x2cd2,0x2cd3,0x2cd4,0x2cd5,0x2cd6,0x2cd7, + 0x2cd8,0x2cd9,0x2cda,0x2cdb,0x2cdc,0x2cdd,0x2cde,0x2cdf, + 0x2ce0,0x2ce1,0x2ce2,0x2ce3,0x2ce4,0x2ce5,0x2ce6,0x2ce7, + 0x2ce8,0x2ce9,0x2cea,0x2ceb,0x2cec,0x2ced,0x2cee,0x2cef, + 0x2cf0,0x2cf1,0x2cf2,0x2cf3,0x2cf4,0x2cf5,0x2cf6,0x2cf7, + 0x2cf8,0x2cf9,0x2cfa,0x2cfb,0x2cfc,0x2cfd,0x2cfe,0x2cff, + 0x2d00,0x2d01,0x2d02,0x2d03,0x2d04,0x2d05,0x2d06,0x2d07, + 0x2d08,0x2d09,0x2d0a,0x2d0b,0x2d0c,0x2d0d,0x2d0e,0x2d0f, + 0x2d10,0x2d11,0x2d12,0x2d13,0x2d14,0x2d15,0x2d16,0x2d17, + 0x2d18,0x2d19,0x2d1a,0x2d1b,0x2d1c,0x2d1d,0x2d1e,0x2d1f, + 0x2d20,0x2d21,0x2d22,0x2d23,0x2d24,0x2d25,0x2d26,0x2d27, + 0x2d28,0x2d29,0x2d2a,0x2d2b,0x2d2c,0x2d2d,0x2d2e,0x2d2f, + 0x2d30,0x2d31,0x2d32,0x2d33,0x2d34,0x2d35,0x2d36,0x2d37, + 0x2d38,0x2d39,0x2d3a,0x2d3b,0x2d3c,0x2d3d,0x2d3e,0x2d3f, + 0x2d40,0x2d41,0x2d42,0x2d43,0x2d44,0x2d45,0x2d46,0x2d47, + 0x2d48,0x2d49,0x2d4a,0x2d4b,0x2d4c,0x2d4d,0x2d4e,0x2d4f, + 0x2d50,0x2d51,0x2d52,0x2d53,0x2d54,0x2d55,0x2d56,0x2d57, + 0x2d58,0x2d59,0x2d5a,0x2d5b,0x2d5c,0x2d5d,0x2d5e,0x2d5f, + 0x2d60,0x2d61,0x2d62,0x2d63,0x2d64,0x2d65,0x2d66,0x2d67, + 0x2d68,0x2d69,0x2d6a,0x2d6b,0x2d6c,0x2d6d,0x2d6e,0x2d6f, + 0x2d70,0x2d71,0x2d72,0x2d73,0x2d74,0x2d75,0x2d76,0x2d77, + 0x2d78,0x2d79,0x2d7a,0x2d7b,0x2d7c,0x2d7d,0x2d7e,0x2d7f, + 0x2d80,0x2d81,0x2d82,0x2d83,0x2d84,0x2d85,0x2d86,0x2d87, + 0x2d88,0x2d89,0x2d8a,0x2d8b,0x2d8c,0x2d8d,0x2d8e,0x2d8f, + 0x2d90,0x2d91,0x2d92,0x2d93,0x2d94,0x2d95,0x2d96,0x2d97, + 0x2d98,0x2d99,0x2d9a,0x2d9b,0x2d9c,0x2d9d,0x2d9e,0x2d9f, + 0x2da0,0x2da1,0x2da2,0x2da3,0x2da4,0x2da5,0x2da6,0x2da7, + 0x2da8,0x2da9,0x2daa,0x2dab,0x2dac,0x2dad,0x2dae,0x2daf, + 0x2db0,0x2db1,0x2db2,0x2db3,0x2db4,0x2db5,0x2db6,0x2db7, + 0x2db8,0x2db9,0x2dba,0x2dbb,0x2dbc,0x2dbd,0x2dbe,0x2dbf, + 0x2dc0,0x2dc1,0x2dc2,0x2dc3,0x2dc4,0x2dc5,0x2dc6,0x2dc7, + 0x2dc8,0x2dc9,0x2dca,0x2dcb,0x2dcc,0x2dcd,0x2dce,0x2dcf, + 0x2dd0,0x2dd1,0x2dd2,0x2dd3,0x2dd4,0x2dd5,0x2dd6,0x2dd7, + 0x2dd8,0x2dd9,0x2dda,0x2ddb,0x2ddc,0x2ddd,0x2dde,0x2ddf, + 0x2de0,0x2de1,0x2de2,0x2de3,0x2de4,0x2de5,0x2de6,0x2de7, + 0x2de8,0x2de9,0x2dea,0x2deb,0x2dec,0x2ded,0x2dee,0x2def, + 0x2df0,0x2df1,0x2df2,0x2df3,0x2df4,0x2df5,0x2df6,0x2df7, + 0x2df8,0x2df9,0x2dfa,0x2dfb,0x2dfc,0x2dfd,0x2dfe,0x2dff, + 0x2e00,0x2e01,0x2e02,0x2e03,0x2e04,0x2e05,0x2e06,0x2e07, + 0x2e08,0x2e09,0x2e0a,0x2e0b,0x2e0c,0x2e0d,0x2e0e,0x2e0f, + 0x2e10,0x2e11,0x2e12,0x2e13,0x2e14,0x2e15,0x2e16,0x2e17, + 0x2e18,0x2e19,0x2e1a,0x2e1b,0x2e1c,0x2e1d,0x2e1e,0x2e1f, + 0x2e20,0x2e21,0x2e22,0x2e23,0x2e24,0x2e25,0x2e26,0x2e27, + 0x2e28,0x2e29,0x2e2a,0x2e2b,0x2e2c,0x2e2d,0x2e2e,0x2e2f, + 0x2e30,0x2e31,0x2e32,0x2e33,0x2e34,0x2e35,0x2e36,0x2e37, + 0x2e38,0x2e39,0x2e3a,0x2e3b,0x2e3c,0x2e3d,0x2e3e,0x2e3f, + 0x2e40,0x2e41,0x2e42,0x2e43,0x2e44,0x2e45,0x2e46,0x2e47, + 0x2e48,0x2e49,0x2e4a,0x2e4b,0x2e4c,0x2e4d,0x2e4e,0x2e4f, + 0x2e50,0x2e51,0x2e52,0x2e53,0x2e54,0x2e55,0x2e56,0x2e57, + 0x2e58,0x2e59,0x2e5a,0x2e5b,0x2e5c,0x2e5d,0x2e5e,0x2e5f, + 0x2e60,0x2e61,0x2e62,0x2e63,0x2e64,0x2e65,0x2e66,0x2e67, + 0x2e68,0x2e69,0x2e6a,0x2e6b,0x2e6c,0x2e6d,0x2e6e,0x2e6f, + 0x2e70,0x2e71,0x2e72,0x2e73,0x2e74,0x2e75,0x2e76,0x2e77, + 0x2e78,0x2e79,0x2e7a,0x2e7b,0x2e7c,0x2e7d,0x2e7e,0x2e7f, + 0x2e80,0x2e81,0x2e82,0x2e83,0x2e84,0x2e85,0x2e86,0x2e87, + 0x2e88,0x2e89,0x2e8a,0x2e8b,0x2e8c,0x2e8d,0x2e8e,0x2e8f, + 0x2e90,0x2e91,0x2e92,0x2e93,0x2e94,0x2e95,0x2e96,0x2e97, + 0x2e98,0x2e99,0x2e9a,0x2e9b,0x2e9c,0x2e9d,0x2e9e,0x2e9f, + 0x2ea0,0x2ea1,0x2ea2,0x2ea3,0x2ea4,0x2ea5,0x2ea6,0x2ea7, + 0x2ea8,0x2ea9,0x2eaa,0x2eab,0x2eac,0x2ead,0x2eae,0x2eaf, + 0x2eb0,0x2eb1,0x2eb2,0x2eb3,0x2eb4,0x2eb5,0x2eb6,0x2eb7, + 0x2eb8,0x2eb9,0x2eba,0x2ebb,0x2ebc,0x2ebd,0x2ebe,0x2ebf, + 0x2ec0,0x2ec1,0x2ec2,0x2ec3,0x2ec4,0x2ec5,0x2ec6,0x2ec7, + 0x2ec8,0x2ec9,0x2eca,0x2ecb,0x2ecc,0x2ecd,0x2ece,0x2ecf, + 0x2ed0,0x2ed1,0x2ed2,0x2ed3,0x2ed4,0x2ed5,0x2ed6,0x2ed7, + 0x2ed8,0x2ed9,0x2eda,0x2edb,0x2edc,0x2edd,0x2ede,0x2edf, + 0x2ee0,0x2ee1,0x2ee2,0x2ee3,0x2ee4,0x2ee5,0x2ee6,0x2ee7, + 0x2ee8,0x2ee9,0x2eea,0x2eeb,0x2eec,0x2eed,0x2eee,0x2eef, + 0x2ef0,0x2ef1,0x2ef2,0x2ef3,0x2ef4,0x2ef5,0x2ef6,0x2ef7, + 0x2ef8,0x2ef9,0x2efa,0x2efb,0x2efc,0x2efd,0x2efe,0x2eff, + 0x2f00,0x2f01,0x2f02,0x2f03,0x2f04,0x2f05,0x2f06,0x2f07, + 0x2f08,0x2f09,0x2f0a,0x2f0b,0x2f0c,0x2f0d,0x2f0e,0x2f0f, + 0x2f10,0x2f11,0x2f12,0x2f13,0x2f14,0x2f15,0x2f16,0x2f17, + 0x2f18,0x2f19,0x2f1a,0x2f1b,0x2f1c,0x2f1d,0x2f1e,0x2f1f, + 0x2f20,0x2f21,0x2f22,0x2f23,0x2f24,0x2f25,0x2f26,0x2f27, + 0x2f28,0x2f29,0x2f2a,0x2f2b,0x2f2c,0x2f2d,0x2f2e,0x2f2f, + 0x2f30,0x2f31,0x2f32,0x2f33,0x2f34,0x2f35,0x2f36,0x2f37, + 0x2f38,0x2f39,0x2f3a,0x2f3b,0x2f3c,0x2f3d,0x2f3e,0x2f3f, + 0x2f40,0x2f41,0x2f42,0x2f43,0x2f44,0x2f45,0x2f46,0x2f47, + 0x2f48,0x2f49,0x2f4a,0x2f4b,0x2f4c,0x2f4d,0x2f4e,0x2f4f, + 0x2f50,0x2f51,0x2f52,0x2f53,0x2f54,0x2f55,0x2f56,0x2f57, + 0x2f58,0x2f59,0x2f5a,0x2f5b,0x2f5c,0x2f5d,0x2f5e,0x2f5f, + 0x2f60,0x2f61,0x2f62,0x2f63,0x2f64,0x2f65,0x2f66,0x2f67, + 0x2f68,0x2f69,0x2f6a,0x2f6b,0x2f6c,0x2f6d,0x2f6e,0x2f6f, + 0x2f70,0x2f71,0x2f72,0x2f73,0x2f74,0x2f75,0x2f76,0x2f77, + 0x2f78,0x2f79,0x2f7a,0x2f7b,0x2f7c,0x2f7d,0x2f7e,0x2f7f, + 0x2f80,0x2f81,0x2f82,0x2f83,0x2f84,0x2f85,0x2f86,0x2f87, + 0x2f88,0x2f89,0x2f8a,0x2f8b,0x2f8c,0x2f8d,0x2f8e,0x2f8f, + 0x2f90,0x2f91,0x2f92,0x2f93,0x2f94,0x2f95,0x2f96,0x2f97, + 0x2f98,0x2f99,0x2f9a,0x2f9b,0x2f9c,0x2f9d,0x2f9e,0x2f9f, + 0x2fa0,0x2fa1,0x2fa2,0x2fa3,0x2fa4,0x2fa5,0x2fa6,0x2fa7, + 0x2fa8,0x2fa9,0x2faa,0x2fab,0x2fac,0x2fad,0x2fae,0x2faf, + 0x2fb0,0x2fb1,0x2fb2,0x2fb3,0x2fb4,0x2fb5,0x2fb6,0x2fb7, + 0x2fb8,0x2fb9,0x2fba,0x2fbb,0x2fbc,0x2fbd,0x2fbe,0x2fbf, + 0x2fc0,0x2fc1,0x2fc2,0x2fc3,0x2fc4,0x2fc5,0x2fc6,0x2fc7, + 0x2fc8,0x2fc9,0x2fca,0x2fcb,0x2fcc,0x2fcd,0x2fce,0x2fcf, + 0x2fd0,0x2fd1,0x2fd2,0x2fd3,0x2fd4,0x2fd5,0x2fd6,0x2fd7, + 0x2fd8,0x2fd9,0x2fda,0x2fdb,0x2fdc,0x2fdd,0x2fde,0x2fdf, + 0x2fe0,0x2fe1,0x2fe2,0x2fe3,0x2fe4,0x2fe5,0x2fe6,0x2fe7, + 0x2fe8,0x2fe9,0x2fea,0x2feb,0x2fec,0x2fed,0x2fee,0x2fef, + 0x2ff0,0x2ff1,0x2ff2,0x2ff3,0x2ff4,0x2ff5,0x2ff6,0x2ff7, + 0x2ff8,0x2ff9,0x2ffa,0x2ffb,0x2ffc,0x2ffd,0x2ffe,0x2fff, + 0x3000,0x3001,0x3002,0x3003,0x3004,0x3005,0x3006,0x3007, + 0x3008,0x3009,0x300a,0x300b,0x300c,0x300d,0x300e,0x300f, + 0x3010,0x3011,0x3012,0x3013,0x3014,0x3015,0x3016,0x3017, + 0x3018,0x3019,0x301a,0x301b,0x301c,0x301d,0x301e,0x301f, + 0x3020,0x3021,0x3022,0x3023,0x3024,0x3025,0x3026,0x3027, + 0x3028,0x3029,0x302a,0x302b,0x302c,0x302d,0x302e,0x302f, + 0x3030,0x3031,0x3032,0x3033,0x3034,0x3035,0x3036,0x3037, + 0x3038,0x3039,0x303a,0x303b,0x303c,0x303d,0x303e,0x303f, + 0x3040,0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047, + 0x3048,0x3049,0x304a,0x304b,0x304c,0x304d,0x304e,0x304f, + 0x3050,0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057, + 0x3058,0x3059,0x305a,0x305b,0x305c,0x305d,0x305e,0x305f, + 0x3060,0x3061,0x3062,0x3063,0x3064,0x3065,0x3066,0x3067, + 0x3068,0x3069,0x306a,0x306b,0x306c,0x306d,0x306e,0x306f, + 0x3070,0x3071,0x3072,0x3073,0x3074,0x3075,0x3076,0x3077, + 0x3078,0x3079,0x307a,0x307b,0x307c,0x307d,0x307e,0x307f, + 0x3080,0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087, + 0x3088,0x3089,0x308a,0x308b,0x308c,0x308d,0x308e,0x308f, + 0x3090,0x3091,0x3092,0x3093,0x3094,0x3095,0x3096,0x3097, + 0x3098,0x3099,0x309a,0x309b,0x309c,0x309d,0x309e,0x309f, + 0x30a0,0x30a1,0x30a2,0x30a3,0x30a4,0x30a5,0x30a6,0x30a7, + 0x30a8,0x30a9,0x30aa,0x30ab,0x30ac,0x30ad,0x30ae,0x30af, + 0x30b0,0x30b1,0x30b2,0x30b3,0x30b4,0x30b5,0x30b6,0x30b7, + 0x30b8,0x30b9,0x30ba,0x30bb,0x30bc,0x30bd,0x30be,0x30bf, + 0x30c0,0x30c1,0x30c2,0x30c3,0x30c4,0x30c5,0x30c6,0x30c7, + 0x30c8,0x30c9,0x30ca,0x30cb,0x30cc,0x30cd,0x30ce,0x30cf, + 0x30d0,0x30d1,0x30d2,0x30d3,0x30d4,0x30d5,0x30d6,0x30d7, + 0x30d8,0x30d9,0x30da,0x30db,0x30dc,0x30dd,0x30de,0x30df, + 0x30e0,0x30e1,0x30e2,0x30e3,0x30e4,0x30e5,0x30e6,0x30e7, + 0x30e8,0x30e9,0x30ea,0x30eb,0x30ec,0x30ed,0x30ee,0x30ef, + 0x30f0,0x30f1,0x30f2,0x30f3,0x30f4,0x30f5,0x30f6,0x30f7, + 0x30f8,0x30f9,0x30fa,0x30fb,0x30fc,0x30fd,0x30fe,0x30ff, + 0x3100,0x3101,0x3102,0x3103,0x3104,0x3105,0x3106,0x3107, + 0x3108,0x3109,0x310a,0x310b,0x310c,0x310d,0x310e,0x310f, + 0x3110,0x3111,0x3112,0x3113,0x3114,0x3115,0x3116,0x3117, + 0x3118,0x3119,0x311a,0x311b,0x311c,0x311d,0x311e,0x311f, + 0x3120,0x3121,0x3122,0x3123,0x3124,0x3125,0x3126,0x3127, + 0x3128,0x3129,0x312a,0x312b,0x312c,0x312d,0x312e,0x312f, + 0x3130,0x3131,0x3132,0x3133,0x3134,0x3135,0x3136,0x3137, + 0x3138,0x3139,0x313a,0x313b,0x313c,0x313d,0x313e,0x313f, + 0x3140,0x3141,0x3142,0x3143,0x3144,0x3145,0x3146,0x3147, + 0x3148,0x3149,0x314a,0x314b,0x314c,0x314d,0x314e,0x314f, + 0x3150,0x3151,0x3152,0x3153,0x3154,0x3155,0x3156,0x3157, + 0x3158,0x3159,0x315a,0x315b,0x315c,0x315d,0x315e,0x315f, + 0x3160,0x3161,0x3162,0x3163,0x3164,0x3165,0x3166,0x3167, + 0x3168,0x3169,0x316a,0x316b,0x316c,0x316d,0x316e,0x316f, + 0x3170,0x3171,0x3172,0x3173,0x3174,0x3175,0x3176,0x3177, + 0x3178,0x3179,0x317a,0x317b,0x317c,0x317d,0x317e,0x317f, + 0x3180,0x3181,0x3182,0x3183,0x3184,0x3185,0x3186,0x3187, + 0x3188,0x3189,0x318a,0x318b,0x318c,0x318d,0x318e,0x318f, + 0x3190,0x3191,0x3192,0x3193,0x3194,0x3195,0x3196,0x3197, + 0x3198,0x3199,0x319a,0x319b,0x319c,0x319d,0x319e,0x319f, + 0x31a0,0x31a1,0x31a2,0x31a3,0x31a4,0x31a5,0x31a6,0x31a7, + 0x31a8,0x31a9,0x31aa,0x31ab,0x31ac,0x31ad,0x31ae,0x31af, + 0x31b0,0x31b1,0x31b2,0x31b3,0x31b4,0x31b5,0x31b6,0x31b7, + 0x31b8,0x31b9,0x31ba,0x31bb,0x31bc,0x31bd,0x31be,0x31bf, + 0x31c0,0x31c1,0x31c2,0x31c3,0x31c4,0x31c5,0x31c6,0x31c7, + 0x31c8,0x31c9,0x31ca,0x31cb,0x31cc,0x31cd,0x31ce,0x31cf, + 0x31d0,0x31d1,0x31d2,0x31d3,0x31d4,0x31d5,0x31d6,0x31d7, + 0x31d8,0x31d9,0x31da,0x31db,0x31dc,0x31dd,0x31de,0x31df, + 0x31e0,0x31e1,0x31e2,0x31e3,0x31e4,0x31e5,0x31e6,0x31e7, + 0x31e8,0x31e9,0x31ea,0x31eb,0x31ec,0x31ed,0x31ee,0x31ef, + 0x31f0,0x31f1,0x31f2,0x31f3,0x31f4,0x31f5,0x31f6,0x31f7, + 0x31f8,0x31f9,0x31fa,0x31fb,0x31fc,0x31fd,0x31fe,0x31ff, + 0x3200,0x3201,0x3202,0x3203,0x3204,0x3205,0x3206,0x3207, + 0x3208,0x3209,0x320a,0x320b,0x320c,0x320d,0x320e,0x320f, + 0x3210,0x3211,0x3212,0x3213,0x3214,0x3215,0x3216,0x3217, + 0x3218,0x3219,0x321a,0x321b,0x321c,0x321d,0x321e,0x321f, + 0x3220,0x3221,0x3222,0x3223,0x3224,0x3225,0x3226,0x3227, + 0x3228,0x3229,0x322a,0x322b,0x322c,0x322d,0x322e,0x322f, + 0x3230,0x3231,0x3232,0x3233,0x3234,0x3235,0x3236,0x3237, + 0x3238,0x3239,0x323a,0x323b,0x323c,0x323d,0x323e,0x323f, + 0x3240,0x3241,0x3242,0x3243,0x3244,0x3245,0x3246,0x3247, + 0x3248,0x3249,0x324a,0x324b,0x324c,0x324d,0x324e,0x324f, + 0x3250,0x3251,0x3252,0x3253,0x3254,0x3255,0x3256,0x3257, + 0x3258,0x3259,0x325a,0x325b,0x325c,0x325d,0x325e,0x325f, + 0x3260,0x3261,0x3262,0x3263,0x3264,0x3265,0x3266,0x3267, + 0x3268,0x3269,0x326a,0x326b,0x326c,0x326d,0x326e,0x326f, + 0x3270,0x3271,0x3272,0x3273,0x3274,0x3275,0x3276,0x3277, + 0x3278,0x3279,0x327a,0x327b,0x327c,0x327d,0x327e,0x327f, + 0x3280,0x3281,0x3282,0x3283,0x3284,0x3285,0x3286,0x3287, + 0x3288,0x3289,0x328a,0x328b,0x328c,0x328d,0x328e,0x328f, + 0x3290,0x3291,0x3292,0x3293,0x3294,0x3295,0x3296,0x3297, + 0x3298,0x3299,0x329a,0x329b,0x329c,0x329d,0x329e,0x329f, + 0x32a0,0x32a1,0x32a2,0x32a3,0x32a4,0x32a5,0x32a6,0x32a7, + 0x32a8,0x32a9,0x32aa,0x32ab,0x32ac,0x32ad,0x32ae,0x32af, + 0x32b0,0x32b1,0x32b2,0x32b3,0x32b4,0x32b5,0x32b6,0x32b7, + 0x32b8,0x32b9,0x32ba,0x32bb,0x32bc,0x32bd,0x32be,0x32bf, + 0x32c0,0x32c1,0x32c2,0x32c3,0x32c4,0x32c5,0x32c6,0x32c7, + 0x32c8,0x32c9,0x32ca,0x32cb,0x32cc,0x32cd,0x32ce,0x32cf, + 0x32d0,0x32d1,0x32d2,0x32d3,0x32d4,0x32d5,0x32d6,0x32d7, + 0x32d8,0x32d9,0x32da,0x32db,0x32dc,0x32dd,0x32de,0x32df, + 0x32e0,0x32e1,0x32e2,0x32e3,0x32e4,0x32e5,0x32e6,0x32e7, + 0x32e8,0x32e9,0x32ea,0x32eb,0x32ec,0x32ed,0x32ee,0x32ef, + 0x32f0,0x32f1,0x32f2,0x32f3,0x32f4,0x32f5,0x32f6,0x32f7, + 0x32f8,0x32f9,0x32fa,0x32fb,0x32fc,0x32fd,0x32fe,0x32ff, + 0x3300,0x3301,0x3302,0x3303,0x3304,0x3305,0x3306,0x3307, + 0x3308,0x3309,0x330a,0x330b,0x330c,0x330d,0x330e,0x330f, + 0x3310,0x3311,0x3312,0x3313,0x3314,0x3315,0x3316,0x3317, + 0x3318,0x3319,0x331a,0x331b,0x331c,0x331d,0x331e,0x331f, + 0x3320,0x3321,0x3322,0x3323,0x3324,0x3325,0x3326,0x3327, + 0x3328,0x3329,0x332a,0x332b,0x332c,0x332d,0x332e,0x332f, + 0x3330,0x3331,0x3332,0x3333,0x3334,0x3335,0x3336,0x3337, + 0x3338,0x3339,0x333a,0x333b,0x333c,0x333d,0x333e,0x333f, + 0x3340,0x3341,0x3342,0x3343,0x3344,0x3345,0x3346,0x3347, + 0x3348,0x3349,0x334a,0x334b,0x334c,0x334d,0x334e,0x334f, + 0x3350,0x3351,0x3352,0x3353,0x3354,0x3355,0x3356,0x3357, + 0x3358,0x3359,0x335a,0x335b,0x335c,0x335d,0x335e,0x335f, + 0x3360,0x3361,0x3362,0x3363,0x3364,0x3365,0x3366,0x3367, + 0x3368,0x3369,0x336a,0x336b,0x336c,0x336d,0x336e,0x336f, + 0x3370,0x3371,0x3372,0x3373,0x3374,0x3375,0x3376,0x3377, + 0x3378,0x3379,0x337a,0x337b,0x337c,0x337d,0x337e,0x337f, + 0x3380,0x3381,0x3382,0x3383,0x3384,0x3385,0x3386,0x3387, + 0x3388,0x3389,0x338a,0x338b,0x338c,0x338d,0x338e,0x338f, + 0x3390,0x3391,0x3392,0x3393,0x3394,0x3395,0x3396,0x3397, + 0x3398,0x3399,0x339a,0x339b,0x339c,0x339d,0x339e,0x339f, + 0x33a0,0x33a1,0x33a2,0x33a3,0x33a4,0x33a5,0x33a6,0x33a7, + 0x33a8,0x33a9,0x33aa,0x33ab,0x33ac,0x33ad,0x33ae,0x33af, + 0x33b0,0x33b1,0x33b2,0x33b3,0x33b4,0x33b5,0x33b6,0x33b7, + 0x33b8,0x33b9,0x33ba,0x33bb,0x33bc,0x33bd,0x33be,0x33bf, + 0x33c0,0x33c1,0x33c2,0x33c3,0x33c4,0x33c5,0x33c6,0x33c7, + 0x33c8,0x33c9,0x33ca,0x33cb,0x33cc,0x33cd,0x33ce,0x33cf, + 0x33d0,0x33d1,0x33d2,0x33d3,0x33d4,0x33d5,0x33d6,0x33d7, + 0x33d8,0x33d9,0x33da,0x33db,0x33dc,0x33dd,0x33de,0x33df, + 0x33e0,0x33e1,0x33e2,0x33e3,0x33e4,0x33e5,0x33e6,0x33e7, + 0x33e8,0x33e9,0x33ea,0x33eb,0x33ec,0x33ed,0x33ee,0x33ef, + 0x33f0,0x33f1,0x33f2,0x33f3,0x33f4,0x33f5,0x33f6,0x33f7, + 0x33f8,0x33f9,0x33fa,0x33fb,0x33fc,0x33fd,0x33fe,0x33ff, + 0x3400,0x3401,0x3402,0x3403,0x3404,0x3405,0x3406,0x3407, + 0x3408,0x3409,0x340a,0x340b,0x340c,0x340d,0x340e,0x340f, + 0x3410,0x3411,0x3412,0x3413,0x3414,0x3415,0x3416,0x3417, + 0x3418,0x3419,0x341a,0x341b,0x341c,0x341d,0x341e,0x341f, + 0x3420,0x3421,0x3422,0x3423,0x3424,0x3425,0x3426,0x3427, + 0x3428,0x3429,0x342a,0x342b,0x342c,0x342d,0x342e,0x342f, + 0x3430,0x3431,0x3432,0x3433,0x3434,0x3435,0x3436,0x3437, + 0x3438,0x3439,0x343a,0x343b,0x343c,0x343d,0x343e,0x343f, + 0x3440,0x3441,0x3442,0x3443,0x3444,0x3445,0x3446,0x3447, + 0x3448,0x3449,0x344a,0x344b,0x344c,0x344d,0x344e,0x344f, + 0x3450,0x3451,0x3452,0x3453,0x3454,0x3455,0x3456,0x3457, + 0x3458,0x3459,0x345a,0x345b,0x345c,0x345d,0x345e,0x345f, + 0x3460,0x3461,0x3462,0x3463,0x3464,0x3465,0x3466,0x3467, + 0x3468,0x3469,0x346a,0x346b,0x346c,0x346d,0x346e,0x346f, + 0x3470,0x3471,0x3472,0x3473,0x3474,0x3475,0x3476,0x3477, + 0x3478,0x3479,0x347a,0x347b,0x347c,0x347d,0x347e,0x347f, + 0x3480,0x3481,0x3482,0x3483,0x3484,0x3485,0x3486,0x3487, + 0x3488,0x3489,0x348a,0x348b,0x348c,0x348d,0x348e,0x348f, + 0x3490,0x3491,0x3492,0x3493,0x3494,0x3495,0x3496,0x3497, + 0x3498,0x3499,0x349a,0x349b,0x349c,0x349d,0x349e,0x349f, + 0x34a0,0x34a1,0x34a2,0x34a3,0x34a4,0x34a5,0x34a6,0x34a7, + 0x34a8,0x34a9,0x34aa,0x34ab,0x34ac,0x34ad,0x34ae,0x34af, + 0x34b0,0x34b1,0x34b2,0x34b3,0x34b4,0x34b5,0x34b6,0x34b7, + 0x34b8,0x34b9,0x34ba,0x34bb,0x34bc,0x34bd,0x34be,0x34bf, + 0x34c0,0x34c1,0x34c2,0x34c3,0x34c4,0x34c5,0x34c6,0x34c7, + 0x34c8,0x34c9,0x34ca,0x34cb,0x34cc,0x34cd,0x34ce,0x34cf, + 0x34d0,0x34d1,0x34d2,0x34d3,0x34d4,0x34d5,0x34d6,0x34d7, + 0x34d8,0x34d9,0x34da,0x34db,0x34dc,0x34dd,0x34de,0x34df, + 0x34e0,0x34e1,0x34e2,0x34e3,0x34e4,0x34e5,0x34e6,0x34e7, + 0x34e8,0x34e9,0x34ea,0x34eb,0x34ec,0x34ed,0x34ee,0x34ef, + 0x34f0,0x34f1,0x34f2,0x34f3,0x34f4,0x34f5,0x34f6,0x34f7, + 0x34f8,0x34f9,0x34fa,0x34fb,0x34fc,0x34fd,0x34fe,0x34ff, + 0x3500,0x3501,0x3502,0x3503,0x3504,0x3505,0x3506,0x3507, + 0x3508,0x3509,0x350a,0x350b,0x350c,0x350d,0x350e,0x350f, + 0x3510,0x3511,0x3512,0x3513,0x3514,0x3515,0x3516,0x3517, + 0x3518,0x3519,0x351a,0x351b,0x351c,0x351d,0x351e,0x351f, + 0x3520,0x3521,0x3522,0x3523,0x3524,0x3525,0x3526,0x3527, + 0x3528,0x3529,0x352a,0x352b,0x352c,0x352d,0x352e,0x352f, + 0x3530,0x3531,0x3532,0x3533,0x3534,0x3535,0x3536,0x3537, + 0x3538,0x3539,0x353a,0x353b,0x353c,0x353d,0x353e,0x353f, + 0x3540,0x3541,0x3542,0x3543,0x3544,0x3545,0x3546,0x3547, + 0x3548,0x3549,0x354a,0x354b,0x354c,0x354d,0x354e,0x354f, + 0x3550,0x3551,0x3552,0x3553,0x3554,0x3555,0x3556,0x3557, + 0x3558,0x3559,0x355a,0x355b,0x355c,0x355d,0x355e,0x355f, + 0x3560,0x3561,0x3562,0x3563,0x3564,0x3565,0x3566,0x3567, + 0x3568,0x3569,0x356a,0x356b,0x356c,0x356d,0x356e,0x356f, + 0x3570,0x3571,0x3572,0x3573,0x3574,0x3575,0x3576,0x3577, + 0x3578,0x3579,0x357a,0x357b,0x357c,0x357d,0x357e,0x357f, + 0x3580,0x3581,0x3582,0x3583,0x3584,0x3585,0x3586,0x3587, + 0x3588,0x3589,0x358a,0x358b,0x358c,0x358d,0x358e,0x358f, + 0x3590,0x3591,0x3592,0x3593,0x3594,0x3595,0x3596,0x3597, + 0x3598,0x3599,0x359a,0x359b,0x359c,0x359d,0x359e,0x359f, + 0x35a0,0x35a1,0x35a2,0x35a3,0x35a4,0x35a5,0x35a6,0x35a7, + 0x35a8,0x35a9,0x35aa,0x35ab,0x35ac,0x35ad,0x35ae,0x35af, + 0x35b0,0x35b1,0x35b2,0x35b3,0x35b4,0x35b5,0x35b6,0x35b7, + 0x35b8,0x35b9,0x35ba,0x35bb,0x35bc,0x35bd,0x35be,0x35bf, + 0x35c0,0x35c1,0x35c2,0x35c3,0x35c4,0x35c5,0x35c6,0x35c7, + 0x35c8,0x35c9,0x35ca,0x35cb,0x35cc,0x35cd,0x35ce,0x35cf, + 0x35d0,0x35d1,0x35d2,0x35d3,0x35d4,0x35d5,0x35d6,0x35d7, + 0x35d8,0x35d9,0x35da,0x35db,0x35dc,0x35dd,0x35de,0x35df, + 0x35e0,0x35e1,0x35e2,0x35e3,0x35e4,0x35e5,0x35e6,0x35e7, + 0x35e8,0x35e9,0x35ea,0x35eb,0x35ec,0x35ed,0x35ee,0x35ef, + 0x35f0,0x35f1,0x35f2,0x35f3,0x35f4,0x35f5,0x35f6,0x35f7, + 0x35f8,0x35f9,0x35fa,0x35fb,0x35fc,0x35fd,0x35fe,0x35ff, + 0x3600,0x3601,0x3602,0x3603,0x3604,0x3605,0x3606,0x3607, + 0x3608,0x3609,0x360a,0x360b,0x360c,0x360d,0x360e,0x360f, + 0x3610,0x3611,0x3612,0x3613,0x3614,0x3615,0x3616,0x3617, + 0x3618,0x3619,0x361a,0x361b,0x361c,0x361d,0x361e,0x361f, + 0x3620,0x3621,0x3622,0x3623,0x3624,0x3625,0x3626,0x3627, + 0x3628,0x3629,0x362a,0x362b,0x362c,0x362d,0x362e,0x362f, + 0x3630,0x3631,0x3632,0x3633,0x3634,0x3635,0x3636,0x3637, + 0x3638,0x3639,0x363a,0x363b,0x363c,0x363d,0x363e,0x363f, + 0x3640,0x3641,0x3642,0x3643,0x3644,0x3645,0x3646,0x3647, + 0x3648,0x3649,0x364a,0x364b,0x364c,0x364d,0x364e,0x364f, + 0x3650,0x3651,0x3652,0x3653,0x3654,0x3655,0x3656,0x3657, + 0x3658,0x3659,0x365a,0x365b,0x365c,0x365d,0x365e,0x365f, + 0x3660,0x3661,0x3662,0x3663,0x3664,0x3665,0x3666,0x3667, + 0x3668,0x3669,0x366a,0x366b,0x366c,0x366d,0x366e,0x366f, + 0x3670,0x3671,0x3672,0x3673,0x3674,0x3675,0x3676,0x3677, + 0x3678,0x3679,0x367a,0x367b,0x367c,0x367d,0x367e,0x367f, + 0x3680,0x3681,0x3682,0x3683,0x3684,0x3685,0x3686,0x3687, + 0x3688,0x3689,0x368a,0x368b,0x368c,0x368d,0x368e,0x368f, + 0x3690,0x3691,0x3692,0x3693,0x3694,0x3695,0x3696,0x3697, + 0x3698,0x3699,0x369a,0x369b,0x369c,0x369d,0x369e,0x369f, + 0x36a0,0x36a1,0x36a2,0x36a3,0x36a4,0x36a5,0x36a6,0x36a7, + 0x36a8,0x36a9,0x36aa,0x36ab,0x36ac,0x36ad,0x36ae,0x36af, + 0x36b0,0x36b1,0x36b2,0x36b3,0x36b4,0x36b5,0x36b6,0x36b7, + 0x36b8,0x36b9,0x36ba,0x36bb,0x36bc,0x36bd,0x36be,0x36bf, + 0x36c0,0x36c1,0x36c2,0x36c3,0x36c4,0x36c5,0x36c6,0x36c7, + 0x36c8,0x36c9,0x36ca,0x36cb,0x36cc,0x36cd,0x36ce,0x36cf, + 0x36d0,0x36d1,0x36d2,0x36d3,0x36d4,0x36d5,0x36d6,0x36d7, + 0x36d8,0x36d9,0x36da,0x36db,0x36dc,0x36dd,0x36de,0x36df, + 0x36e0,0x36e1,0x36e2,0x36e3,0x36e4,0x36e5,0x36e6,0x36e7, + 0x36e8,0x36e9,0x36ea,0x36eb,0x36ec,0x36ed,0x36ee,0x36ef, + 0x36f0,0x36f1,0x36f2,0x36f3,0x36f4,0x36f5,0x36f6,0x36f7, + 0x36f8,0x36f9,0x36fa,0x36fb,0x36fc,0x36fd,0x36fe,0x36ff, + 0x3700,0x3701,0x3702,0x3703,0x3704,0x3705,0x3706,0x3707, + 0x3708,0x3709,0x370a,0x370b,0x370c,0x370d,0x370e,0x370f, + 0x3710,0x3711,0x3712,0x3713,0x3714,0x3715,0x3716,0x3717, + 0x3718,0x3719,0x371a,0x371b,0x371c,0x371d,0x371e,0x371f, + 0x3720,0x3721,0x3722,0x3723,0x3724,0x3725,0x3726,0x3727, + 0x3728,0x3729,0x372a,0x372b,0x372c,0x372d,0x372e,0x372f, + 0x3730,0x3731,0x3732,0x3733,0x3734,0x3735,0x3736,0x3737, + 0x3738,0x3739,0x373a,0x373b,0x373c,0x373d,0x373e,0x373f, + 0x3740,0x3741,0x3742,0x3743,0x3744,0x3745,0x3746,0x3747, + 0x3748,0x3749,0x374a,0x374b,0x374c,0x374d,0x374e,0x374f, + 0x3750,0x3751,0x3752,0x3753,0x3754,0x3755,0x3756,0x3757, + 0x3758,0x3759,0x375a,0x375b,0x375c,0x375d,0x375e,0x375f, + 0x3760,0x3761,0x3762,0x3763,0x3764,0x3765,0x3766,0x3767, + 0x3768,0x3769,0x376a,0x376b,0x376c,0x376d,0x376e,0x376f, + 0x3770,0x3771,0x3772,0x3773,0x3774,0x3775,0x3776,0x3777, + 0x3778,0x3779,0x377a,0x377b,0x377c,0x377d,0x377e,0x377f, + 0x3780,0x3781,0x3782,0x3783,0x3784,0x3785,0x3786,0x3787, + 0x3788,0x3789,0x378a,0x378b,0x378c,0x378d,0x378e,0x378f, + 0x3790,0x3791,0x3792,0x3793,0x3794,0x3795,0x3796,0x3797, + 0x3798,0x3799,0x379a,0x379b,0x379c,0x379d,0x379e,0x379f, + 0x37a0,0x37a1,0x37a2,0x37a3,0x37a4,0x37a5,0x37a6,0x37a7, + 0x37a8,0x37a9,0x37aa,0x37ab,0x37ac,0x37ad,0x37ae,0x37af, + 0x37b0,0x37b1,0x37b2,0x37b3,0x37b4,0x37b5,0x37b6,0x37b7, + 0x37b8,0x37b9,0x37ba,0x37bb,0x37bc,0x37bd,0x37be,0x37bf, + 0x37c0,0x37c1,0x37c2,0x37c3,0x37c4,0x37c5,0x37c6,0x37c7, + 0x37c8,0x37c9,0x37ca,0x37cb,0x37cc,0x37cd,0x37ce,0x37cf, + 0x37d0,0x37d1,0x37d2,0x37d3,0x37d4,0x37d5,0x37d6,0x37d7, + 0x37d8,0x37d9,0x37da,0x37db,0x37dc,0x37dd,0x37de,0x37df, + 0x37e0,0x37e1,0x37e2,0x37e3,0x37e4,0x37e5,0x37e6,0x37e7, + 0x37e8,0x37e9,0x37ea,0x37eb,0x37ec,0x37ed,0x37ee,0x37ef, + 0x37f0,0x37f1,0x37f2,0x37f3,0x37f4,0x37f5,0x37f6,0x37f7, + 0x37f8,0x37f9,0x37fa,0x37fb,0x37fc,0x37fd,0x37fe,0x37ff, + 0x3800,0x3801,0x3802,0x3803,0x3804,0x3805,0x3806,0x3807, + 0x3808,0x3809,0x380a,0x380b,0x380c,0x380d,0x380e,0x380f, + 0x3810,0x3811,0x3812,0x3813,0x3814,0x3815,0x3816,0x3817, + 0x3818,0x3819,0x381a,0x381b,0x381c,0x381d,0x381e,0x381f, + 0x3820,0x3821,0x3822,0x3823,0x3824,0x3825,0x3826,0x3827, + 0x3828,0x3829,0x382a,0x382b,0x382c,0x382d,0x382e,0x382f, + 0x3830,0x3831,0x3832,0x3833,0x3834,0x3835,0x3836,0x3837, + 0x3838,0x3839,0x383a,0x383b,0x383c,0x383d,0x383e,0x383f, + 0x3840,0x3841,0x3842,0x3843,0x3844,0x3845,0x3846,0x3847, + 0x3848,0x3849,0x384a,0x384b,0x384c,0x384d,0x384e,0x384f, + 0x3850,0x3851,0x3852,0x3853,0x3854,0x3855,0x3856,0x3857, + 0x3858,0x3859,0x385a,0x385b,0x385c,0x385d,0x385e,0x385f, + 0x3860,0x3861,0x3862,0x3863,0x3864,0x3865,0x3866,0x3867, + 0x3868,0x3869,0x386a,0x386b,0x386c,0x386d,0x386e,0x386f, + 0x3870,0x3871,0x3872,0x3873,0x3874,0x3875,0x3876,0x3877, + 0x3878,0x3879,0x387a,0x387b,0x387c,0x387d,0x387e,0x387f, + 0x3880,0x3881,0x3882,0x3883,0x3884,0x3885,0x3886,0x3887, + 0x3888,0x3889,0x388a,0x388b,0x388c,0x388d,0x388e,0x388f, + 0x3890,0x3891,0x3892,0x3893,0x3894,0x3895,0x3896,0x3897, + 0x3898,0x3899,0x389a,0x389b,0x389c,0x389d,0x389e,0x389f, + 0x38a0,0x38a1,0x38a2,0x38a3,0x38a4,0x38a5,0x38a6,0x38a7, + 0x38a8,0x38a9,0x38aa,0x38ab,0x38ac,0x38ad,0x38ae,0x38af, + 0x38b0,0x38b1,0x38b2,0x38b3,0x38b4,0x38b5,0x38b6,0x38b7, + 0x38b8,0x38b9,0x38ba,0x38bb,0x38bc,0x38bd,0x38be,0x38bf, + 0x38c0,0x38c1,0x38c2,0x38c3,0x38c4,0x38c5,0x38c6,0x38c7, + 0x38c8,0x38c9,0x38ca,0x38cb,0x38cc,0x38cd,0x38ce,0x38cf, + 0x38d0,0x38d1,0x38d2,0x38d3,0x38d4,0x38d5,0x38d6,0x38d7, + 0x38d8,0x38d9,0x38da,0x38db,0x38dc,0x38dd,0x38de,0x38df, + 0x38e0,0x38e1,0x38e2,0x38e3,0x38e4,0x38e5,0x38e6,0x38e7, + 0x38e8,0x38e9,0x38ea,0x38eb,0x38ec,0x38ed,0x38ee,0x38ef, + 0x38f0,0x38f1,0x38f2,0x38f3,0x38f4,0x38f5,0x38f6,0x38f7, + 0x38f8,0x38f9,0x38fa,0x38fb,0x38fc,0x38fd,0x38fe,0x38ff, + 0x3900,0x3901,0x3902,0x3903,0x3904,0x3905,0x3906,0x3907, + 0x3908,0x3909,0x390a,0x390b,0x390c,0x390d,0x390e,0x390f, + 0x3910,0x3911,0x3912,0x3913,0x3914,0x3915,0x3916,0x3917, + 0x3918,0x3919,0x391a,0x391b,0x391c,0x391d,0x391e,0x391f, + 0x3920,0x3921,0x3922,0x3923,0x3924,0x3925,0x3926,0x3927, + 0x3928,0x3929,0x392a,0x392b,0x392c,0x392d,0x392e,0x392f, + 0x3930,0x3931,0x3932,0x3933,0x3934,0x3935,0x3936,0x3937, + 0x3938,0x3939,0x393a,0x393b,0x393c,0x393d,0x393e,0x393f, + 0x3940,0x3941,0x3942,0x3943,0x3944,0x3945,0x3946,0x3947, + 0x3948,0x3949,0x394a,0x394b,0x394c,0x394d,0x394e,0x394f, + 0x3950,0x3951,0x3952,0x3953,0x3954,0x3955,0x3956,0x3957, + 0x3958,0x3959,0x395a,0x395b,0x395c,0x395d,0x395e,0x395f, + 0x3960,0x3961,0x3962,0x3963,0x3964,0x3965,0x3966,0x3967, + 0x3968,0x3969,0x396a,0x396b,0x396c,0x396d,0x396e,0x396f, + 0x3970,0x3971,0x3972,0x3973,0x3974,0x3975,0x3976,0x3977, + 0x3978,0x3979,0x397a,0x397b,0x397c,0x397d,0x397e,0x397f, + 0x3980,0x3981,0x3982,0x3983,0x3984,0x3985,0x3986,0x3987, + 0x3988,0x3989,0x398a,0x398b,0x398c,0x398d,0x398e,0x398f, + 0x3990,0x3991,0x3992,0x3993,0x3994,0x3995,0x3996,0x3997, + 0x3998,0x3999,0x399a,0x399b,0x399c,0x399d,0x399e,0x399f, + 0x39a0,0x39a1,0x39a2,0x39a3,0x39a4,0x39a5,0x39a6,0x39a7, + 0x39a8,0x39a9,0x39aa,0x39ab,0x39ac,0x39ad,0x39ae,0x39af, + 0x39b0,0x39b1,0x39b2,0x39b3,0x39b4,0x39b5,0x39b6,0x39b7, + 0x39b8,0x39b9,0x39ba,0x39bb,0x39bc,0x39bd,0x39be,0x39bf, + 0x39c0,0x39c1,0x39c2,0x39c3,0x39c4,0x39c5,0x39c6,0x39c7, + 0x39c8,0x39c9,0x39ca,0x39cb,0x39cc,0x39cd,0x39ce,0x39cf, + 0x39d0,0x39d1,0x39d2,0x39d3,0x39d4,0x39d5,0x39d6,0x39d7, + 0x39d8,0x39d9,0x39da,0x39db,0x39dc,0x39dd,0x39de,0x39df, + 0x39e0,0x39e1,0x39e2,0x39e3,0x39e4,0x39e5,0x39e6,0x39e7, + 0x39e8,0x39e9,0x39ea,0x39eb,0x39ec,0x39ed,0x39ee,0x39ef, + 0x39f0,0x39f1,0x39f2,0x39f3,0x39f4,0x39f5,0x39f6,0x39f7, + 0x39f8,0x39f9,0x39fa,0x39fb,0x39fc,0x39fd,0x39fe,0x39ff, + 0x3a00,0x3a01,0x3a02,0x3a03,0x3a04,0x3a05,0x3a06,0x3a07, + 0x3a08,0x3a09,0x3a0a,0x3a0b,0x3a0c,0x3a0d,0x3a0e,0x3a0f, + 0x3a10,0x3a11,0x3a12,0x3a13,0x3a14,0x3a15,0x3a16,0x3a17, + 0x3a18,0x3a19,0x3a1a,0x3a1b,0x3a1c,0x3a1d,0x3a1e,0x3a1f, + 0x3a20,0x3a21,0x3a22,0x3a23,0x3a24,0x3a25,0x3a26,0x3a27, + 0x3a28,0x3a29,0x3a2a,0x3a2b,0x3a2c,0x3a2d,0x3a2e,0x3a2f, + 0x3a30,0x3a31,0x3a32,0x3a33,0x3a34,0x3a35,0x3a36,0x3a37, + 0x3a38,0x3a39,0x3a3a,0x3a3b,0x3a3c,0x3a3d,0x3a3e,0x3a3f, + 0x3a40,0x3a41,0x3a42,0x3a43,0x3a44,0x3a45,0x3a46,0x3a47, + 0x3a48,0x3a49,0x3a4a,0x3a4b,0x3a4c,0x3a4d,0x3a4e,0x3a4f, + 0x3a50,0x3a51,0x3a52,0x3a53,0x3a54,0x3a55,0x3a56,0x3a57, + 0x3a58,0x3a59,0x3a5a,0x3a5b,0x3a5c,0x3a5d,0x3a5e,0x3a5f, + 0x3a60,0x3a61,0x3a62,0x3a63,0x3a64,0x3a65,0x3a66,0x3a67, + 0x3a68,0x3a69,0x3a6a,0x3a6b,0x3a6c,0x3a6d,0x3a6e,0x3a6f, + 0x3a70,0x3a71,0x3a72,0x3a73,0x3a74,0x3a75,0x3a76,0x3a77, + 0x3a78,0x3a79,0x3a7a,0x3a7b,0x3a7c,0x3a7d,0x3a7e,0x3a7f, + 0x3a80,0x3a81,0x3a82,0x3a83,0x3a84,0x3a85,0x3a86,0x3a87, + 0x3a88,0x3a89,0x3a8a,0x3a8b,0x3a8c,0x3a8d,0x3a8e,0x3a8f, + 0x3a90,0x3a91,0x3a92,0x3a93,0x3a94,0x3a95,0x3a96,0x3a97, + 0x3a98,0x3a99,0x3a9a,0x3a9b,0x3a9c,0x3a9d,0x3a9e,0x3a9f, + 0x3aa0,0x3aa1,0x3aa2,0x3aa3,0x3aa4,0x3aa5,0x3aa6,0x3aa7, + 0x3aa8,0x3aa9,0x3aaa,0x3aab,0x3aac,0x3aad,0x3aae,0x3aaf, + 0x3ab0,0x3ab1,0x3ab2,0x3ab3,0x3ab4,0x3ab5,0x3ab6,0x3ab7, + 0x3ab8,0x3ab9,0x3aba,0x3abb,0x3abc,0x3abd,0x3abe,0x3abf, + 0x3ac0,0x3ac1,0x3ac2,0x3ac3,0x3ac4,0x3ac5,0x3ac6,0x3ac7, + 0x3ac8,0x3ac9,0x3aca,0x3acb,0x3acc,0x3acd,0x3ace,0x3acf, + 0x3ad0,0x3ad1,0x3ad2,0x3ad3,0x3ad4,0x3ad5,0x3ad6,0x3ad7, + 0x3ad8,0x3ad9,0x3ada,0x3adb,0x3adc,0x3add,0x3ade,0x3adf, + 0x3ae0,0x3ae1,0x3ae2,0x3ae3,0x3ae4,0x3ae5,0x3ae6,0x3ae7, + 0x3ae8,0x3ae9,0x3aea,0x3aeb,0x3aec,0x3aed,0x3aee,0x3aef, + 0x3af0,0x3af1,0x3af2,0x3af3,0x3af4,0x3af5,0x3af6,0x3af7, + 0x3af8,0x3af9,0x3afa,0x3afb,0x3afc,0x3afd,0x3afe,0x3aff, + 0x3b00,0x3b01,0x3b02,0x3b03,0x3b04,0x3b05,0x3b06,0x3b07, + 0x3b08,0x3b09,0x3b0a,0x3b0b,0x3b0c,0x3b0d,0x3b0e,0x3b0f, + 0x3b10,0x3b11,0x3b12,0x3b13,0x3b14,0x3b15,0x3b16,0x3b17, + 0x3b18,0x3b19,0x3b1a,0x3b1b,0x3b1c,0x3b1d,0x3b1e,0x3b1f, + 0x3b20,0x3b21,0x3b22,0x3b23,0x3b24,0x3b25,0x3b26,0x3b27, + 0x3b28,0x3b29,0x3b2a,0x3b2b,0x3b2c,0x3b2d,0x3b2e,0x3b2f, + 0x3b30,0x3b31,0x3b32,0x3b33,0x3b34,0x3b35,0x3b36,0x3b37, + 0x3b38,0x3b39,0x3b3a,0x3b3b,0x3b3c,0x3b3d,0x3b3e,0x3b3f, + 0x3b40,0x3b41,0x3b42,0x3b43,0x3b44,0x3b45,0x3b46,0x3b47, + 0x3b48,0x3b49,0x3b4a,0x3b4b,0x3b4c,0x3b4d,0x3b4e,0x3b4f, + 0x3b50,0x3b51,0x3b52,0x3b53,0x3b54,0x3b55,0x3b56,0x3b57, + 0x3b58,0x3b59,0x3b5a,0x3b5b,0x3b5c,0x3b5d,0x3b5e,0x3b5f, + 0x3b60,0x3b61,0x3b62,0x3b63,0x3b64,0x3b65,0x3b66,0x3b67, + 0x3b68,0x3b69,0x3b6a,0x3b6b,0x3b6c,0x3b6d,0x3b6e,0x3b6f, + 0x3b70,0x3b71,0x3b72,0x3b73,0x3b74,0x3b75,0x3b76,0x3b77, + 0x3b78,0x3b79,0x3b7a,0x3b7b,0x3b7c,0x3b7d,0x3b7e,0x3b7f, + 0x3b80,0x3b81,0x3b82,0x3b83,0x3b84,0x3b85,0x3b86,0x3b87, + 0x3b88,0x3b89,0x3b8a,0x3b8b,0x3b8c,0x3b8d,0x3b8e,0x3b8f, + 0x3b90,0x3b91,0x3b92,0x3b93,0x3b94,0x3b95,0x3b96,0x3b97, + 0x3b98,0x3b99,0x3b9a,0x3b9b,0x3b9c,0x3b9d,0x3b9e,0x3b9f, + 0x3ba0,0x3ba1,0x3ba2,0x3ba3,0x3ba4,0x3ba5,0x3ba6,0x3ba7, + 0x3ba8,0x3ba9,0x3baa,0x3bab,0x3bac,0x3bad,0x3bae,0x3baf, + 0x3bb0,0x3bb1,0x3bb2,0x3bb3,0x3bb4,0x3bb5,0x3bb6,0x3bb7, + 0x3bb8,0x3bb9,0x3bba,0x3bbb,0x3bbc,0x3bbd,0x3bbe,0x3bbf, + 0x3bc0,0x3bc1,0x3bc2,0x3bc3,0x3bc4,0x3bc5,0x3bc6,0x3bc7, + 0x3bc8,0x3bc9,0x3bca,0x3bcb,0x3bcc,0x3bcd,0x3bce,0x3bcf, + 0x3bd0,0x3bd1,0x3bd2,0x3bd3,0x3bd4,0x3bd5,0x3bd6,0x3bd7, + 0x3bd8,0x3bd9,0x3bda,0x3bdb,0x3bdc,0x3bdd,0x3bde,0x3bdf, + 0x3be0,0x3be1,0x3be2,0x3be3,0x3be4,0x3be5,0x3be6,0x3be7, + 0x3be8,0x3be9,0x3bea,0x3beb,0x3bec,0x3bed,0x3bee,0x3bef, + 0x3bf0,0x3bf1,0x3bf2,0x3bf3,0x3bf4,0x3bf5,0x3bf6,0x3bf7, + 0x3bf8,0x3bf9,0x3bfa,0x3bfb,0x3bfc,0x3bfd,0x3bfe,0x3bff, + 0x3c00,0x3c01,0x3c02,0x3c03,0x3c04,0x3c05,0x3c06,0x3c07, + 0x3c08,0x3c09,0x3c0a,0x3c0b,0x3c0c,0x3c0d,0x3c0e,0x3c0f, + 0x3c10,0x3c11,0x3c12,0x3c13,0x3c14,0x3c15,0x3c16,0x3c17, + 0x3c18,0x3c19,0x3c1a,0x3c1b,0x3c1c,0x3c1d,0x3c1e,0x3c1f, + 0x3c20,0x3c21,0x3c22,0x3c23,0x3c24,0x3c25,0x3c26,0x3c27, + 0x3c28,0x3c29,0x3c2a,0x3c2b,0x3c2c,0x3c2d,0x3c2e,0x3c2f, + 0x3c30,0x3c31,0x3c32,0x3c33,0x3c34,0x3c35,0x3c36,0x3c37, + 0x3c38,0x3c39,0x3c3a,0x3c3b,0x3c3c,0x3c3d,0x3c3e,0x3c3f, + 0x3c40,0x3c41,0x3c42,0x3c43,0x3c44,0x3c45,0x3c46,0x3c47, + 0x3c48,0x3c49,0x3c4a,0x3c4b,0x3c4c,0x3c4d,0x3c4e,0x3c4f, + 0x3c50,0x3c51,0x3c52,0x3c53,0x3c54,0x3c55,0x3c56,0x3c57, + 0x3c58,0x3c59,0x3c5a,0x3c5b,0x3c5c,0x3c5d,0x3c5e,0x3c5f, + 0x3c60,0x3c61,0x3c62,0x3c63,0x3c64,0x3c65,0x3c66,0x3c67, + 0x3c68,0x3c69,0x3c6a,0x3c6b,0x3c6c,0x3c6d,0x3c6e,0x3c6f, + 0x3c70,0x3c71,0x3c72,0x3c73,0x3c74,0x3c75,0x3c76,0x3c77, + 0x3c78,0x3c79,0x3c7a,0x3c7b,0x3c7c,0x3c7d,0x3c7e,0x3c7f, + 0x3c80,0x3c81,0x3c82,0x3c83,0x3c84,0x3c85,0x3c86,0x3c87, + 0x3c88,0x3c89,0x3c8a,0x3c8b,0x3c8c,0x3c8d,0x3c8e,0x3c8f, + 0x3c90,0x3c91,0x3c92,0x3c93,0x3c94,0x3c95,0x3c96,0x3c97, + 0x3c98,0x3c99,0x3c9a,0x3c9b,0x3c9c,0x3c9d,0x3c9e,0x3c9f, + 0x3ca0,0x3ca1,0x3ca2,0x3ca3,0x3ca4,0x3ca5,0x3ca6,0x3ca7, + 0x3ca8,0x3ca9,0x3caa,0x3cab,0x3cac,0x3cad,0x3cae,0x3caf, + 0x3cb0,0x3cb1,0x3cb2,0x3cb3,0x3cb4,0x3cb5,0x3cb6,0x3cb7, + 0x3cb8,0x3cb9,0x3cba,0x3cbb,0x3cbc,0x3cbd,0x3cbe,0x3cbf, + 0x3cc0,0x3cc1,0x3cc2,0x3cc3,0x3cc4,0x3cc5,0x3cc6,0x3cc7, + 0x3cc8,0x3cc9,0x3cca,0x3ccb,0x3ccc,0x3ccd,0x3cce,0x3ccf, + 0x3cd0,0x3cd1,0x3cd2,0x3cd3,0x3cd4,0x3cd5,0x3cd6,0x3cd7, + 0x3cd8,0x3cd9,0x3cda,0x3cdb,0x3cdc,0x3cdd,0x3cde,0x3cdf, + 0x3ce0,0x3ce1,0x3ce2,0x3ce3,0x3ce4,0x3ce5,0x3ce6,0x3ce7, + 0x3ce8,0x3ce9,0x3cea,0x3ceb,0x3cec,0x3ced,0x3cee,0x3cef, + 0x3cf0,0x3cf1,0x3cf2,0x3cf3,0x3cf4,0x3cf5,0x3cf6,0x3cf7, + 0x3cf8,0x3cf9,0x3cfa,0x3cfb,0x3cfc,0x3cfd,0x3cfe,0x3cff, + 0x3d00,0x3d01,0x3d02,0x3d03,0x3d04,0x3d05,0x3d06,0x3d07, + 0x3d08,0x3d09,0x3d0a,0x3d0b,0x3d0c,0x3d0d,0x3d0e,0x3d0f, + 0x3d10,0x3d11,0x3d12,0x3d13,0x3d14,0x3d15,0x3d16,0x3d17, + 0x3d18,0x3d19,0x3d1a,0x3d1b,0x3d1c,0x3d1d,0x3d1e,0x3d1f, + 0x3d20,0x3d21,0x3d22,0x3d23,0x3d24,0x3d25,0x3d26,0x3d27, + 0x3d28,0x3d29,0x3d2a,0x3d2b,0x3d2c,0x3d2d,0x3d2e,0x3d2f, + 0x3d30,0x3d31,0x3d32,0x3d33,0x3d34,0x3d35,0x3d36,0x3d37, + 0x3d38,0x3d39,0x3d3a,0x3d3b,0x3d3c,0x3d3d,0x3d3e,0x3d3f, + 0x3d40,0x3d41,0x3d42,0x3d43,0x3d44,0x3d45,0x3d46,0x3d47, + 0x3d48,0x3d49,0x3d4a,0x3d4b,0x3d4c,0x3d4d,0x3d4e,0x3d4f, + 0x3d50,0x3d51,0x3d52,0x3d53,0x3d54,0x3d55,0x3d56,0x3d57, + 0x3d58,0x3d59,0x3d5a,0x3d5b,0x3d5c,0x3d5d,0x3d5e,0x3d5f, + 0x3d60,0x3d61,0x3d62,0x3d63,0x3d64,0x3d65,0x3d66,0x3d67, + 0x3d68,0x3d69,0x3d6a,0x3d6b,0x3d6c,0x3d6d,0x3d6e,0x3d6f, + 0x3d70,0x3d71,0x3d72,0x3d73,0x3d74,0x3d75,0x3d76,0x3d77, + 0x3d78,0x3d79,0x3d7a,0x3d7b,0x3d7c,0x3d7d,0x3d7e,0x3d7f, + 0x3d80,0x3d81,0x3d82,0x3d83,0x3d84,0x3d85,0x3d86,0x3d87, + 0x3d88,0x3d89,0x3d8a,0x3d8b,0x3d8c,0x3d8d,0x3d8e,0x3d8f, + 0x3d90,0x3d91,0x3d92,0x3d93,0x3d94,0x3d95,0x3d96,0x3d97, + 0x3d98,0x3d99,0x3d9a,0x3d9b,0x3d9c,0x3d9d,0x3d9e,0x3d9f, + 0x3da0,0x3da1,0x3da2,0x3da3,0x3da4,0x3da5,0x3da6,0x3da7, + 0x3da8,0x3da9,0x3daa,0x3dab,0x3dac,0x3dad,0x3dae,0x3daf, + 0x3db0,0x3db1,0x3db2,0x3db3,0x3db4,0x3db5,0x3db6,0x3db7, + 0x3db8,0x3db9,0x3dba,0x3dbb,0x3dbc,0x3dbd,0x3dbe,0x3dbf, + 0x3dc0,0x3dc1,0x3dc2,0x3dc3,0x3dc4,0x3dc5,0x3dc6,0x3dc7, + 0x3dc8,0x3dc9,0x3dca,0x3dcb,0x3dcc,0x3dcd,0x3dce,0x3dcf, + 0x3dd0,0x3dd1,0x3dd2,0x3dd3,0x3dd4,0x3dd5,0x3dd6,0x3dd7, + 0x3dd8,0x3dd9,0x3dda,0x3ddb,0x3ddc,0x3ddd,0x3dde,0x3ddf, + 0x3de0,0x3de1,0x3de2,0x3de3,0x3de4,0x3de5,0x3de6,0x3de7, + 0x3de8,0x3de9,0x3dea,0x3deb,0x3dec,0x3ded,0x3dee,0x3def, + 0x3df0,0x3df1,0x3df2,0x3df3,0x3df4,0x3df5,0x3df6,0x3df7, + 0x3df8,0x3df9,0x3dfa,0x3dfb,0x3dfc,0x3dfd,0x3dfe,0x3dff, + 0x3e00,0x3e01,0x3e02,0x3e03,0x3e04,0x3e05,0x3e06,0x3e07, + 0x3e08,0x3e09,0x3e0a,0x3e0b,0x3e0c,0x3e0d,0x3e0e,0x3e0f, + 0x3e10,0x3e11,0x3e12,0x3e13,0x3e14,0x3e15,0x3e16,0x3e17, + 0x3e18,0x3e19,0x3e1a,0x3e1b,0x3e1c,0x3e1d,0x3e1e,0x3e1f, + 0x3e20,0x3e21,0x3e22,0x3e23,0x3e24,0x3e25,0x3e26,0x3e27, + 0x3e28,0x3e29,0x3e2a,0x3e2b,0x3e2c,0x3e2d,0x3e2e,0x3e2f, + 0x3e30,0x3e31,0x3e32,0x3e33,0x3e34,0x3e35,0x3e36,0x3e37, + 0x3e38,0x3e39,0x3e3a,0x3e3b,0x3e3c,0x3e3d,0x3e3e,0x3e3f, + 0x3e40,0x3e41,0x3e42,0x3e43,0x3e44,0x3e45,0x3e46,0x3e47, + 0x3e48,0x3e49,0x3e4a,0x3e4b,0x3e4c,0x3e4d,0x3e4e,0x3e4f, + 0x3e50,0x3e51,0x3e52,0x3e53,0x3e54,0x3e55,0x3e56,0x3e57, + 0x3e58,0x3e59,0x3e5a,0x3e5b,0x3e5c,0x3e5d,0x3e5e,0x3e5f, + 0x3e60,0x3e61,0x3e62,0x3e63,0x3e64,0x3e65,0x3e66,0x3e67, + 0x3e68,0x3e69,0x3e6a,0x3e6b,0x3e6c,0x3e6d,0x3e6e,0x3e6f, + 0x3e70,0x3e71,0x3e72,0x3e73,0x3e74,0x3e75,0x3e76,0x3e77, + 0x3e78,0x3e79,0x3e7a,0x3e7b,0x3e7c,0x3e7d,0x3e7e,0x3e7f, + 0x3e80,0x3e81,0x3e82,0x3e83,0x3e84,0x3e85,0x3e86,0x3e87, + 0x3e88,0x3e89,0x3e8a,0x3e8b,0x3e8c,0x3e8d,0x3e8e,0x3e8f, + 0x3e90,0x3e91,0x3e92,0x3e93,0x3e94,0x3e95,0x3e96,0x3e97, + 0x3e98,0x3e99,0x3e9a,0x3e9b,0x3e9c,0x3e9d,0x3e9e,0x3e9f, + 0x3ea0,0x3ea1,0x3ea2,0x3ea3,0x3ea4,0x3ea5,0x3ea6,0x3ea7, + 0x3ea8,0x3ea9,0x3eaa,0x3eab,0x3eac,0x3ead,0x3eae,0x3eaf, + 0x3eb0,0x3eb1,0x3eb2,0x3eb3,0x3eb4,0x3eb5,0x3eb6,0x3eb7, + 0x3eb8,0x3eb9,0x3eba,0x3ebb,0x3ebc,0x3ebd,0x3ebe,0x3ebf, + 0x3ec0,0x3ec1,0x3ec2,0x3ec3,0x3ec4,0x3ec5,0x3ec6,0x3ec7, + 0x3ec8,0x3ec9,0x3eca,0x3ecb,0x3ecc,0x3ecd,0x3ece,0x3ecf, + 0x3ed0,0x3ed1,0x3ed2,0x3ed3,0x3ed4,0x3ed5,0x3ed6,0x3ed7, + 0x3ed8,0x3ed9,0x3eda,0x3edb,0x3edc,0x3edd,0x3ede,0x3edf, + 0x3ee0,0x3ee1,0x3ee2,0x3ee3,0x3ee4,0x3ee5,0x3ee6,0x3ee7, + 0x3ee8,0x3ee9,0x3eea,0x3eeb,0x3eec,0x3eed,0x3eee,0x3eef, + 0x3ef0,0x3ef1,0x3ef2,0x3ef3,0x3ef4,0x3ef5,0x3ef6,0x3ef7, + 0x3ef8,0x3ef9,0x3efa,0x3efb,0x3efc,0x3efd,0x3efe,0x3eff, + 0x3f00,0x3f01,0x3f02,0x3f03,0x3f04,0x3f05,0x3f06,0x3f07, + 0x3f08,0x3f09,0x3f0a,0x3f0b,0x3f0c,0x3f0d,0x3f0e,0x3f0f, + 0x3f10,0x3f11,0x3f12,0x3f13,0x3f14,0x3f15,0x3f16,0x3f17, + 0x3f18,0x3f19,0x3f1a,0x3f1b,0x3f1c,0x3f1d,0x3f1e,0x3f1f, + 0x3f20,0x3f21,0x3f22,0x3f23,0x3f24,0x3f25,0x3f26,0x3f27, + 0x3f28,0x3f29,0x3f2a,0x3f2b,0x3f2c,0x3f2d,0x3f2e,0x3f2f, + 0x3f30,0x3f31,0x3f32,0x3f33,0x3f34,0x3f35,0x3f36,0x3f37, + 0x3f38,0x3f39,0x3f3a,0x3f3b,0x3f3c,0x3f3d,0x3f3e,0x3f3f, + 0x3f40,0x3f41,0x3f42,0x3f43,0x3f44,0x3f45,0x3f46,0x3f47, + 0x3f48,0x3f49,0x3f4a,0x3f4b,0x3f4c,0x3f4d,0x3f4e,0x3f4f, + 0x3f50,0x3f51,0x3f52,0x3f53,0x3f54,0x3f55,0x3f56,0x3f57, + 0x3f58,0x3f59,0x3f5a,0x3f5b,0x3f5c,0x3f5d,0x3f5e,0x3f5f, + 0x3f60,0x3f61,0x3f62,0x3f63,0x3f64,0x3f65,0x3f66,0x3f67, + 0x3f68,0x3f69,0x3f6a,0x3f6b,0x3f6c,0x3f6d,0x3f6e,0x3f6f, + 0x3f70,0x3f71,0x3f72,0x3f73,0x3f74,0x3f75,0x3f76,0x3f77, + 0x3f78,0x3f79,0x3f7a,0x3f7b,0x3f7c,0x3f7d,0x3f7e,0x3f7f, + 0x3f80,0x3f81,0x3f82,0x3f83,0x3f84,0x3f85,0x3f86,0x3f87, + 0x3f88,0x3f89,0x3f8a,0x3f8b,0x3f8c,0x3f8d,0x3f8e,0x3f8f, + 0x3f90,0x3f91,0x3f92,0x3f93,0x3f94,0x3f95,0x3f96,0x3f97, + 0x3f98,0x3f99,0x3f9a,0x3f9b,0x3f9c,0x3f9d,0x3f9e,0x3f9f, + 0x3fa0,0x3fa1,0x3fa2,0x3fa3,0x3fa4,0x3fa5,0x3fa6,0x3fa7, + 0x3fa8,0x3fa9,0x3faa,0x3fab,0x3fac,0x3fad,0x3fae,0x3faf, + 0x3fb0,0x3fb1,0x3fb2,0x3fb3,0x3fb4,0x3fb5,0x3fb6,0x3fb7, + 0x3fb8,0x3fb9,0x3fba,0x3fbb,0x3fbc,0x3fbd,0x3fbe,0x3fbf, + 0x3fc0,0x3fc1,0x3fc2,0x3fc3,0x3fc4,0x3fc5,0x3fc6,0x3fc7, + 0x3fc8,0x3fc9,0x3fca,0x3fcb,0x3fcc,0x3fcd,0x3fce,0x3fcf, + 0x3fd0,0x3fd1,0x3fd2,0x3fd3,0x3fd4,0x3fd5,0x3fd6,0x3fd7, + 0x3fd8,0x3fd9,0x3fda,0x3fdb,0x3fdc,0x3fdd,0x3fde,0x3fdf, + 0x3fe0,0x3fe1,0x3fe2,0x3fe3,0x3fe4,0x3fe5,0x3fe6,0x3fe7, + 0x3fe8,0x3fe9,0x3fea,0x3feb,0x3fec,0x3fed,0x3fee,0x3fef, + 0x3ff0,0x3ff1,0x3ff2,0x3ff3,0x3ff4,0x3ff5,0x3ff6,0x3ff7, + 0x3ff8,0x3ff9,0x3ffa,0x3ffb,0x3ffc,0x3ffd,0x3ffe,0x3fff, + 0x4000,0x4001,0x4002,0x4003,0x4004,0x4005,0x4006,0x4007, + 0x4008,0x4009,0x400a,0x400b,0x400c,0x400d,0x400e,0x400f, + 0x4010,0x4011,0x4012,0x4013,0x4014,0x4015,0x4016,0x4017, + 0x4018,0x4019,0x401a,0x401b,0x401c,0x401d,0x401e,0x401f, + 0x4020,0x4021,0x4022,0x4023,0x4024,0x4025,0x4026,0x4027, + 0x4028,0x4029,0x402a,0x402b,0x402c,0x402d,0x402e,0x402f, + 0x4030,0x4031,0x4032,0x4033,0x4034,0x4035,0x4036,0x4037, + 0x4038,0x4039,0x403a,0x403b,0x403c,0x403d,0x403e,0x403f, + 0x4040,0x4041,0x4042,0x4043,0x4044,0x4045,0x4046,0x4047, + 0x4048,0x4049,0x404a,0x404b,0x404c,0x404d,0x404e,0x404f, + 0x4050,0x4051,0x4052,0x4053,0x4054,0x4055,0x4056,0x4057, + 0x4058,0x4059,0x405a,0x405b,0x405c,0x405d,0x405e,0x405f, + 0x4060,0x4061,0x4062,0x4063,0x4064,0x4065,0x4066,0x4067, + 0x4068,0x4069,0x406a,0x406b,0x406c,0x406d,0x406e,0x406f, + 0x4070,0x4071,0x4072,0x4073,0x4074,0x4075,0x4076,0x4077, + 0x4078,0x4079,0x407a,0x407b,0x407c,0x407d,0x407e,0x407f, + 0x4080,0x4081,0x4082,0x4083,0x4084,0x4085,0x4086,0x4087, + 0x4088,0x4089,0x408a,0x408b,0x408c,0x408d,0x408e,0x408f, + 0x4090,0x4091,0x4092,0x4093,0x4094,0x4095,0x4096,0x4097, + 0x4098,0x4099,0x409a,0x409b,0x409c,0x409d,0x409e,0x409f, + 0x40a0,0x40a1,0x40a2,0x40a3,0x40a4,0x40a5,0x40a6,0x40a7, + 0x40a8,0x40a9,0x40aa,0x40ab,0x40ac,0x40ad,0x40ae,0x40af, + 0x40b0,0x40b1,0x40b2,0x40b3,0x40b4,0x40b5,0x40b6,0x40b7, + 0x40b8,0x40b9,0x40ba,0x40bb,0x40bc,0x40bd,0x40be,0x40bf, + 0x40c0,0x40c1,0x40c2,0x40c3,0x40c4,0x40c5,0x40c6,0x40c7, + 0x40c8,0x40c9,0x40ca,0x40cb,0x40cc,0x40cd,0x40ce,0x40cf, + 0x40d0,0x40d1,0x40d2,0x40d3,0x40d4,0x40d5,0x40d6,0x40d7, + 0x40d8,0x40d9,0x40da,0x40db,0x40dc,0x40dd,0x40de,0x40df, + 0x40e0,0x40e1,0x40e2,0x40e3,0x40e4,0x40e5,0x40e6,0x40e7, + 0x40e8,0x40e9,0x40ea,0x40eb,0x40ec,0x40ed,0x40ee,0x40ef, + 0x40f0,0x40f1,0x40f2,0x40f3,0x40f4,0x40f5,0x40f6,0x40f7, + 0x40f8,0x40f9,0x40fa,0x40fb,0x40fc,0x40fd,0x40fe,0x40ff, + 0x4100,0x4101,0x4102,0x4103,0x4104,0x4105,0x4106,0x4107, + 0x4108,0x4109,0x410a,0x410b,0x410c,0x410d,0x410e,0x410f, + 0x4110,0x4111,0x4112,0x4113,0x4114,0x4115,0x4116,0x4117, + 0x4118,0x4119,0x411a,0x411b,0x411c,0x411d,0x411e,0x411f, + 0x4120,0x4121,0x4122,0x4123,0x4124,0x4125,0x4126,0x4127, + 0x4128,0x4129,0x412a,0x412b,0x412c,0x412d,0x412e,0x412f, + 0x4130,0x4131,0x4132,0x4133,0x4134,0x4135,0x4136,0x4137, + 0x4138,0x4139,0x413a,0x413b,0x413c,0x413d,0x413e,0x413f, + 0x4140,0x4141,0x4142,0x4143,0x4144,0x4145,0x4146,0x4147, + 0x4148,0x4149,0x414a,0x414b,0x414c,0x414d,0x414e,0x414f, + 0x4150,0x4151,0x4152,0x4153,0x4154,0x4155,0x4156,0x4157, + 0x4158,0x4159,0x415a,0x415b,0x415c,0x415d,0x415e,0x415f, + 0x4160,0x4161,0x4162,0x4163,0x4164,0x4165,0x4166,0x4167, + 0x4168,0x4169,0x416a,0x416b,0x416c,0x416d,0x416e,0x416f, + 0x4170,0x4171,0x4172,0x4173,0x4174,0x4175,0x4176,0x4177, + 0x4178,0x4179,0x417a,0x417b,0x417c,0x417d,0x417e,0x417f, + 0x4180,0x4181,0x4182,0x4183,0x4184,0x4185,0x4186,0x4187, + 0x4188,0x4189,0x418a,0x418b,0x418c,0x418d,0x418e,0x418f, + 0x4190,0x4191,0x4192,0x4193,0x4194,0x4195,0x4196,0x4197, + 0x4198,0x4199,0x419a,0x419b,0x419c,0x419d,0x419e,0x419f, + 0x41a0,0x41a1,0x41a2,0x41a3,0x41a4,0x41a5,0x41a6,0x41a7, + 0x41a8,0x41a9,0x41aa,0x41ab,0x41ac,0x41ad,0x41ae,0x41af, + 0x41b0,0x41b1,0x41b2,0x41b3,0x41b4,0x41b5,0x41b6,0x41b7, + 0x41b8,0x41b9,0x41ba,0x41bb,0x41bc,0x41bd,0x41be,0x41bf, + 0x41c0,0x41c1,0x41c2,0x41c3,0x41c4,0x41c5,0x41c6,0x41c7, + 0x41c8,0x41c9,0x41ca,0x41cb,0x41cc,0x41cd,0x41ce,0x41cf, + 0x41d0,0x41d1,0x41d2,0x41d3,0x41d4,0x41d5,0x41d6,0x41d7, + 0x41d8,0x41d9,0x41da,0x41db,0x41dc,0x41dd,0x41de,0x41df, + 0x41e0,0x41e1,0x41e2,0x41e3,0x41e4,0x41e5,0x41e6,0x41e7, + 0x41e8,0x41e9,0x41ea,0x41eb,0x41ec,0x41ed,0x41ee,0x41ef, + 0x41f0,0x41f1,0x41f2,0x41f3,0x41f4,0x41f5,0x41f6,0x41f7, + 0x41f8,0x41f9,0x41fa,0x41fb,0x41fc,0x41fd,0x41fe,0x41ff, + 0x4200,0x4201,0x4202,0x4203,0x4204,0x4205,0x4206,0x4207, + 0x4208,0x4209,0x420a,0x420b,0x420c,0x420d,0x420e,0x420f, + 0x4210,0x4211,0x4212,0x4213,0x4214,0x4215,0x4216,0x4217, + 0x4218,0x4219,0x421a,0x421b,0x421c,0x421d,0x421e,0x421f, + 0x4220,0x4221,0x4222,0x4223,0x4224,0x4225,0x4226,0x4227, + 0x4228,0x4229,0x422a,0x422b,0x422c,0x422d,0x422e,0x422f, + 0x4230,0x4231,0x4232,0x4233,0x4234,0x4235,0x4236,0x4237, + 0x4238,0x4239,0x423a,0x423b,0x423c,0x423d,0x423e,0x423f, + 0x4240,0x4241,0x4242,0x4243,0x4244,0x4245,0x4246,0x4247, + 0x4248,0x4249,0x424a,0x424b,0x424c,0x424d,0x424e,0x424f, + 0x4250,0x4251,0x4252,0x4253,0x4254,0x4255,0x4256,0x4257, + 0x4258,0x4259,0x425a,0x425b,0x425c,0x425d,0x425e,0x425f, + 0x4260,0x4261,0x4262,0x4263,0x4264,0x4265,0x4266,0x4267, + 0x4268,0x4269,0x426a,0x426b,0x426c,0x426d,0x426e,0x426f, + 0x4270,0x4271,0x4272,0x4273,0x4274,0x4275,0x4276,0x4277, + 0x4278,0x4279,0x427a,0x427b,0x427c,0x427d,0x427e,0x427f, + 0x4280,0x4281,0x4282,0x4283,0x4284,0x4285,0x4286,0x4287, + 0x4288,0x4289,0x428a,0x428b,0x428c,0x428d,0x428e,0x428f, + 0x4290,0x4291,0x4292,0x4293,0x4294,0x4295,0x4296,0x4297, + 0x4298,0x4299,0x429a,0x429b,0x429c,0x429d,0x429e,0x429f, + 0x42a0,0x42a1,0x42a2,0x42a3,0x42a4,0x42a5,0x42a6,0x42a7, + 0x42a8,0x42a9,0x42aa,0x42ab,0x42ac,0x42ad,0x42ae,0x42af, + 0x42b0,0x42b1,0x42b2,0x42b3,0x42b4,0x42b5,0x42b6,0x42b7, + 0x42b8,0x42b9,0x42ba,0x42bb,0x42bc,0x42bd,0x42be,0x42bf, + 0x42c0,0x42c1,0x42c2,0x42c3,0x42c4,0x42c5,0x42c6,0x42c7, + 0x42c8,0x42c9,0x42ca,0x42cb,0x42cc,0x42cd,0x42ce,0x42cf, + 0x42d0,0x42d1,0x42d2,0x42d3,0x42d4,0x42d5,0x42d6,0x42d7, + 0x42d8,0x42d9,0x42da,0x42db,0x42dc,0x42dd,0x42de,0x42df, + 0x42e0,0x42e1,0x42e2,0x42e3,0x42e4,0x42e5,0x42e6,0x42e7, + 0x42e8,0x42e9,0x42ea,0x42eb,0x42ec,0x42ed,0x42ee,0x42ef, + 0x42f0,0x42f1,0x42f2,0x42f3,0x42f4,0x42f5,0x42f6,0x42f7, + 0x42f8,0x42f9,0x42fa,0x42fb,0x42fc,0x42fd,0x42fe,0x42ff, + 0x4300,0x4301,0x4302,0x4303,0x4304,0x4305,0x4306,0x4307, + 0x4308,0x4309,0x430a,0x430b,0x430c,0x430d,0x430e,0x430f, + 0x4310,0x4311,0x4312,0x4313,0x4314,0x4315,0x4316,0x4317, + 0x4318,0x4319,0x431a,0x431b,0x431c,0x431d,0x431e,0x431f, + 0x4320,0x4321,0x4322,0x4323,0x4324,0x4325,0x4326,0x4327, + 0x4328,0x4329,0x432a,0x432b,0x432c,0x432d,0x432e,0x432f, + 0x4330,0x4331,0x4332,0x4333,0x4334,0x4335,0x4336,0x4337, + 0x4338,0x4339,0x433a,0x433b,0x433c,0x433d,0x433e,0x433f, + 0x4340,0x4341,0x4342,0x4343,0x4344,0x4345,0x4346,0x4347, + 0x4348,0x4349,0x434a,0x434b,0x434c,0x434d,0x434e,0x434f, + 0x4350,0x4351,0x4352,0x4353,0x4354,0x4355,0x4356,0x4357, + 0x4358,0x4359,0x435a,0x435b,0x435c,0x435d,0x435e,0x435f, + 0x4360,0x4361,0x4362,0x4363,0x4364,0x4365,0x4366,0x4367, + 0x4368,0x4369,0x436a,0x436b,0x436c,0x436d,0x436e,0x436f, + 0x4370,0x4371,0x4372,0x4373,0x4374,0x4375,0x4376,0x4377, + 0x4378,0x4379,0x437a,0x437b,0x437c,0x437d,0x437e,0x437f, + 0x4380,0x4381,0x4382,0x4383,0x4384,0x4385,0x4386,0x4387, + 0x4388,0x4389,0x438a,0x438b,0x438c,0x438d,0x438e,0x438f, + 0x4390,0x4391,0x4392,0x4393,0x4394,0x4395,0x4396,0x4397, + 0x4398,0x4399,0x439a,0x439b,0x439c,0x439d,0x439e,0x439f, + 0x43a0,0x43a1,0x43a2,0x43a3,0x43a4,0x43a5,0x43a6,0x43a7, + 0x43a8,0x43a9,0x43aa,0x43ab,0x43ac,0x43ad,0x43ae,0x43af, + 0x43b0,0x43b1,0x43b2,0x43b3,0x43b4,0x43b5,0x43b6,0x43b7, + 0x43b8,0x43b9,0x43ba,0x43bb,0x43bc,0x43bd,0x43be,0x43bf, + 0x43c0,0x43c1,0x43c2,0x43c3,0x43c4,0x43c5,0x43c6,0x43c7, + 0x43c8,0x43c9,0x43ca,0x43cb,0x43cc,0x43cd,0x43ce,0x43cf, + 0x43d0,0x43d1,0x43d2,0x43d3,0x43d4,0x43d5,0x43d6,0x43d7, + 0x43d8,0x43d9,0x43da,0x43db,0x43dc,0x43dd,0x43de,0x43df, + 0x43e0,0x43e1,0x43e2,0x43e3,0x43e4,0x43e5,0x43e6,0x43e7, + 0x43e8,0x43e9,0x43ea,0x43eb,0x43ec,0x43ed,0x43ee,0x43ef, + 0x43f0,0x43f1,0x43f2,0x43f3,0x43f4,0x43f5,0x43f6,0x43f7, + 0x43f8,0x43f9,0x43fa,0x43fb,0x43fc,0x43fd,0x43fe,0x43ff, + 0x4400,0x4401,0x4402,0x4403,0x4404,0x4405,0x4406,0x4407, + 0x4408,0x4409,0x440a,0x440b,0x440c,0x440d,0x440e,0x440f, + 0x4410,0x4411,0x4412,0x4413,0x4414,0x4415,0x4416,0x4417, + 0x4418,0x4419,0x441a,0x441b,0x441c,0x441d,0x441e,0x441f, + 0x4420,0x4421,0x4422,0x4423,0x4424,0x4425,0x4426,0x4427, + 0x4428,0x4429,0x442a,0x442b,0x442c,0x442d,0x442e,0x442f, + 0x4430,0x4431,0x4432,0x4433,0x4434,0x4435,0x4436,0x4437, + 0x4438,0x4439,0x443a,0x443b,0x443c,0x443d,0x443e,0x443f, + 0x4440,0x4441,0x4442,0x4443,0x4444,0x4445,0x4446,0x4447, + 0x4448,0x4449,0x444a,0x444b,0x444c,0x444d,0x444e,0x444f, + 0x4450,0x4451,0x4452,0x4453,0x4454,0x4455,0x4456,0x4457, + 0x4458,0x4459,0x445a,0x445b,0x445c,0x445d,0x445e,0x445f, + 0x4460,0x4461,0x4462,0x4463,0x4464,0x4465,0x4466,0x4467, + 0x4468,0x4469,0x446a,0x446b,0x446c,0x446d,0x446e,0x446f, + 0x4470,0x4471,0x4472,0x4473,0x4474,0x4475,0x4476,0x4477, + 0x4478,0x4479,0x447a,0x447b,0x447c,0x447d,0x447e,0x447f, + 0x4480,0x4481,0x4482,0x4483,0x4484,0x4485,0x4486,0x4487, + 0x4488,0x4489,0x448a,0x448b,0x448c,0x448d,0x448e,0x448f, + 0x4490,0x4491,0x4492,0x4493,0x4494,0x4495,0x4496,0x4497, + 0x4498,0x4499,0x449a,0x449b,0x449c,0x449d,0x449e,0x449f, + 0x44a0,0x44a1,0x44a2,0x44a3,0x44a4,0x44a5,0x44a6,0x44a7, + 0x44a8,0x44a9,0x44aa,0x44ab,0x44ac,0x44ad,0x44ae,0x44af, + 0x44b0,0x44b1,0x44b2,0x44b3,0x44b4,0x44b5,0x44b6,0x44b7, + 0x44b8,0x44b9,0x44ba,0x44bb,0x44bc,0x44bd,0x44be,0x44bf, + 0x44c0,0x44c1,0x44c2,0x44c3,0x44c4,0x44c5,0x44c6,0x44c7, + 0x44c8,0x44c9,0x44ca,0x44cb,0x44cc,0x44cd,0x44ce,0x44cf, + 0x44d0,0x44d1,0x44d2,0x44d3,0x44d4,0x44d5,0x44d6,0x44d7, + 0x44d8,0x44d9,0x44da,0x44db,0x44dc,0x44dd,0x44de,0x44df, + 0x44e0,0x44e1,0x44e2,0x44e3,0x44e4,0x44e5,0x44e6,0x44e7, + 0x44e8,0x44e9,0x44ea,0x44eb,0x44ec,0x44ed,0x44ee,0x44ef, + 0x44f0,0x44f1,0x44f2,0x44f3,0x44f4,0x44f5,0x44f6,0x44f7, + 0x44f8,0x44f9,0x44fa,0x44fb,0x44fc,0x44fd,0x44fe,0x44ff, + 0x4500,0x4501,0x4502,0x4503,0x4504,0x4505,0x4506,0x4507, + 0x4508,0x4509,0x450a,0x450b,0x450c,0x450d,0x450e,0x450f, + 0x4510,0x4511,0x4512,0x4513,0x4514,0x4515,0x4516,0x4517, + 0x4518,0x4519,0x451a,0x451b,0x451c,0x451d,0x451e,0x451f, + 0x4520,0x4521,0x4522,0x4523,0x4524,0x4525,0x4526,0x4527, + 0x4528,0x4529,0x452a,0x452b,0x452c,0x452d,0x452e,0x452f, + 0x4530,0x4531,0x4532,0x4533,0x4534,0x4535,0x4536,0x4537, + 0x4538,0x4539,0x453a,0x453b,0x453c,0x453d,0x453e,0x453f, + 0x4540,0x4541,0x4542,0x4543,0x4544,0x4545,0x4546,0x4547, + 0x4548,0x4549,0x454a,0x454b,0x454c,0x454d,0x454e,0x454f, + 0x4550,0x4551,0x4552,0x4553,0x4554,0x4555,0x4556,0x4557, + 0x4558,0x4559,0x455a,0x455b,0x455c,0x455d,0x455e,0x455f, + 0x4560,0x4561,0x4562,0x4563,0x4564,0x4565,0x4566,0x4567, + 0x4568,0x4569,0x456a,0x456b,0x456c,0x456d,0x456e,0x456f, + 0x4570,0x4571,0x4572,0x4573,0x4574,0x4575,0x4576,0x4577, + 0x4578,0x4579,0x457a,0x457b,0x457c,0x457d,0x457e,0x457f, + 0x4580,0x4581,0x4582,0x4583,0x4584,0x4585,0x4586,0x4587, + 0x4588,0x4589,0x458a,0x458b,0x458c,0x458d,0x458e,0x458f, + 0x4590,0x4591,0x4592,0x4593,0x4594,0x4595,0x4596,0x4597, + 0x4598,0x4599,0x459a,0x459b,0x459c,0x459d,0x459e,0x459f, + 0x45a0,0x45a1,0x45a2,0x45a3,0x45a4,0x45a5,0x45a6,0x45a7, + 0x45a8,0x45a9,0x45aa,0x45ab,0x45ac,0x45ad,0x45ae,0x45af, + 0x45b0,0x45b1,0x45b2,0x45b3,0x45b4,0x45b5,0x45b6,0x45b7, + 0x45b8,0x45b9,0x45ba,0x45bb,0x45bc,0x45bd,0x45be,0x45bf, + 0x45c0,0x45c1,0x45c2,0x45c3,0x45c4,0x45c5,0x45c6,0x45c7, + 0x45c8,0x45c9,0x45ca,0x45cb,0x45cc,0x45cd,0x45ce,0x45cf, + 0x45d0,0x45d1,0x45d2,0x45d3,0x45d4,0x45d5,0x45d6,0x45d7, + 0x45d8,0x45d9,0x45da,0x45db,0x45dc,0x45dd,0x45de,0x45df, + 0x45e0,0x45e1,0x45e2,0x45e3,0x45e4,0x45e5,0x45e6,0x45e7, + 0x45e8,0x45e9,0x45ea,0x45eb,0x45ec,0x45ed,0x45ee,0x45ef, + 0x45f0,0x45f1,0x45f2,0x45f3,0x45f4,0x45f5,0x45f6,0x45f7, + 0x45f8,0x45f9,0x45fa,0x45fb,0x45fc,0x45fd,0x45fe,0x45ff, + 0x4600,0x4601,0x4602,0x4603,0x4604,0x4605,0x4606,0x4607, + 0x4608,0x4609,0x460a,0x460b,0x460c,0x460d,0x460e,0x460f, + 0x4610,0x4611,0x4612,0x4613,0x4614,0x4615,0x4616,0x4617, + 0x4618,0x4619,0x461a,0x461b,0x461c,0x461d,0x461e,0x461f, + 0x4620,0x4621,0x4622,0x4623,0x4624,0x4625,0x4626,0x4627, + 0x4628,0x4629,0x462a,0x462b,0x462c,0x462d,0x462e,0x462f, + 0x4630,0x4631,0x4632,0x4633,0x4634,0x4635,0x4636,0x4637, + 0x4638,0x4639,0x463a,0x463b,0x463c,0x463d,0x463e,0x463f, + 0x4640,0x4641,0x4642,0x4643,0x4644,0x4645,0x4646,0x4647, + 0x4648,0x4649,0x464a,0x464b,0x464c,0x464d,0x464e,0x464f, + 0x4650,0x4651,0x4652,0x4653,0x4654,0x4655,0x4656,0x4657, + 0x4658,0x4659,0x465a,0x465b,0x465c,0x465d,0x465e,0x465f, + 0x4660,0x4661,0x4662,0x4663,0x4664,0x4665,0x4666,0x4667, + 0x4668,0x4669,0x466a,0x466b,0x466c,0x466d,0x466e,0x466f, + 0x4670,0x4671,0x4672,0x4673,0x4674,0x4675,0x4676,0x4677, + 0x4678,0x4679,0x467a,0x467b,0x467c,0x467d,0x467e,0x467f, + 0x4680,0x4681,0x4682,0x4683,0x4684,0x4685,0x4686,0x4687, + 0x4688,0x4689,0x468a,0x468b,0x468c,0x468d,0x468e,0x468f, + 0x4690,0x4691,0x4692,0x4693,0x4694,0x4695,0x4696,0x4697, + 0x4698,0x4699,0x469a,0x469b,0x469c,0x469d,0x469e,0x469f, + 0x46a0,0x46a1,0x46a2,0x46a3,0x46a4,0x46a5,0x46a6,0x46a7, + 0x46a8,0x46a9,0x46aa,0x46ab,0x46ac,0x46ad,0x46ae,0x46af, + 0x46b0,0x46b1,0x46b2,0x46b3,0x46b4,0x46b5,0x46b6,0x46b7, + 0x46b8,0x46b9,0x46ba,0x46bb,0x46bc,0x46bd,0x46be,0x46bf, + 0x46c0,0x46c1,0x46c2,0x46c3,0x46c4,0x46c5,0x46c6,0x46c7, + 0x46c8,0x46c9,0x46ca,0x46cb,0x46cc,0x46cd,0x46ce,0x46cf, + 0x46d0,0x46d1,0x46d2,0x46d3,0x46d4,0x46d5,0x46d6,0x46d7, + 0x46d8,0x46d9,0x46da,0x46db,0x46dc,0x46dd,0x46de,0x46df, + 0x46e0,0x46e1,0x46e2,0x46e3,0x46e4,0x46e5,0x46e6,0x46e7, + 0x46e8,0x46e9,0x46ea,0x46eb,0x46ec,0x46ed,0x46ee,0x46ef, + 0x46f0,0x46f1,0x46f2,0x46f3,0x46f4,0x46f5,0x46f6,0x46f7, + 0x46f8,0x46f9,0x46fa,0x46fb,0x46fc,0x46fd,0x46fe,0x46ff, + 0x4700,0x4701,0x4702,0x4703,0x4704,0x4705,0x4706,0x4707, + 0x4708,0x4709,0x470a,0x470b,0x470c,0x470d,0x470e,0x470f, + 0x4710,0x4711,0x4712,0x4713,0x4714,0x4715,0x4716,0x4717, + 0x4718,0x4719,0x471a,0x471b,0x471c,0x471d,0x471e,0x471f, + 0x4720,0x4721,0x4722,0x4723,0x4724,0x4725,0x4726,0x4727, + 0x4728,0x4729,0x472a,0x472b,0x472c,0x472d,0x472e,0x472f, + 0x4730,0x4731,0x4732,0x4733,0x4734,0x4735,0x4736,0x4737, + 0x4738,0x4739,0x473a,0x473b,0x473c,0x473d,0x473e,0x473f, + 0x4740,0x4741,0x4742,0x4743,0x4744,0x4745,0x4746,0x4747, + 0x4748,0x4749,0x474a,0x474b,0x474c,0x474d,0x474e,0x474f, + 0x4750,0x4751,0x4752,0x4753,0x4754,0x4755,0x4756,0x4757, + 0x4758,0x4759,0x475a,0x475b,0x475c,0x475d,0x475e,0x475f, + 0x4760,0x4761,0x4762,0x4763,0x4764,0x4765,0x4766,0x4767, + 0x4768,0x4769,0x476a,0x476b,0x476c,0x476d,0x476e,0x476f, + 0x4770,0x4771,0x4772,0x4773,0x4774,0x4775,0x4776,0x4777, + 0x4778,0x4779,0x477a,0x477b,0x477c,0x477d,0x477e,0x477f, + 0x4780,0x4781,0x4782,0x4783,0x4784,0x4785,0x4786,0x4787, + 0x4788,0x4789,0x478a,0x478b,0x478c,0x478d,0x478e,0x478f, + 0x4790,0x4791,0x4792,0x4793,0x4794,0x4795,0x4796,0x4797, + 0x4798,0x4799,0x479a,0x479b,0x479c,0x479d,0x479e,0x479f, + 0x47a0,0x47a1,0x47a2,0x47a3,0x47a4,0x47a5,0x47a6,0x47a7, + 0x47a8,0x47a9,0x47aa,0x47ab,0x47ac,0x47ad,0x47ae,0x47af, + 0x47b0,0x47b1,0x47b2,0x47b3,0x47b4,0x47b5,0x47b6,0x47b7, + 0x47b8,0x47b9,0x47ba,0x47bb,0x47bc,0x47bd,0x47be,0x47bf, + 0x47c0,0x47c1,0x47c2,0x47c3,0x47c4,0x47c5,0x47c6,0x47c7, + 0x47c8,0x47c9,0x47ca,0x47cb,0x47cc,0x47cd,0x47ce,0x47cf, + 0x47d0,0x47d1,0x47d2,0x47d3,0x47d4,0x47d5,0x47d6,0x47d7, + 0x47d8,0x47d9,0x47da,0x47db,0x47dc,0x47dd,0x47de,0x47df, + 0x47e0,0x47e1,0x47e2,0x47e3,0x47e4,0x47e5,0x47e6,0x47e7, + 0x47e8,0x47e9,0x47ea,0x47eb,0x47ec,0x47ed,0x47ee,0x47ef, + 0x47f0,0x47f1,0x47f2,0x47f3,0x47f4,0x47f5,0x47f6,0x47f7, + 0x47f8,0x47f9,0x47fa,0x47fb,0x47fc,0x47fd,0x47fe,0x47ff, + 0x4800,0x4801,0x4802,0x4803,0x4804,0x4805,0x4806,0x4807, + 0x4808,0x4809,0x480a,0x480b,0x480c,0x480d,0x480e,0x480f, + 0x4810,0x4811,0x4812,0x4813,0x4814,0x4815,0x4816,0x4817, + 0x4818,0x4819,0x481a,0x481b,0x481c,0x481d,0x481e,0x481f, + 0x4820,0x4821,0x4822,0x4823,0x4824,0x4825,0x4826,0x4827, + 0x4828,0x4829,0x482a,0x482b,0x482c,0x482d,0x482e,0x482f, + 0x4830,0x4831,0x4832,0x4833,0x4834,0x4835,0x4836,0x4837, + 0x4838,0x4839,0x483a,0x483b,0x483c,0x483d,0x483e,0x483f, + 0x4840,0x4841,0x4842,0x4843,0x4844,0x4845,0x4846,0x4847, + 0x4848,0x4849,0x484a,0x484b,0x484c,0x484d,0x484e,0x484f, + 0x4850,0x4851,0x4852,0x4853,0x4854,0x4855,0x4856,0x4857, + 0x4858,0x4859,0x485a,0x485b,0x485c,0x485d,0x485e,0x485f, + 0x4860,0x4861,0x4862,0x4863,0x4864,0x4865,0x4866,0x4867, + 0x4868,0x4869,0x486a,0x486b,0x486c,0x486d,0x486e,0x486f, + 0x4870,0x4871,0x4872,0x4873,0x4874,0x4875,0x4876,0x4877, + 0x4878,0x4879,0x487a,0x487b,0x487c,0x487d,0x487e,0x487f, + 0x4880,0x4881,0x4882,0x4883,0x4884,0x4885,0x4886,0x4887, + 0x4888,0x4889,0x488a,0x488b,0x488c,0x488d,0x488e,0x488f, + 0x4890,0x4891,0x4892,0x4893,0x4894,0x4895,0x4896,0x4897, + 0x4898,0x4899,0x489a,0x489b,0x489c,0x489d,0x489e,0x489f, + 0x48a0,0x48a1,0x48a2,0x48a3,0x48a4,0x48a5,0x48a6,0x48a7, + 0x48a8,0x48a9,0x48aa,0x48ab,0x48ac,0x48ad,0x48ae,0x48af, + 0x48b0,0x48b1,0x48b2,0x48b3,0x48b4,0x48b5,0x48b6,0x48b7, + 0x48b8,0x48b9,0x48ba,0x48bb,0x48bc,0x48bd,0x48be,0x48bf, + 0x48c0,0x48c1,0x48c2,0x48c3,0x48c4,0x48c5,0x48c6,0x48c7, + 0x48c8,0x48c9,0x48ca,0x48cb,0x48cc,0x48cd,0x48ce,0x48cf, + 0x48d0,0x48d1,0x48d2,0x48d3,0x48d4,0x48d5,0x48d6,0x48d7, + 0x48d8,0x48d9,0x48da,0x48db,0x48dc,0x48dd,0x48de,0x48df, + 0x48e0,0x48e1,0x48e2,0x48e3,0x48e4,0x48e5,0x48e6,0x48e7, + 0x48e8,0x48e9,0x48ea,0x48eb,0x48ec,0x48ed,0x48ee,0x48ef, + 0x48f0,0x48f1,0x48f2,0x48f3,0x48f4,0x48f5,0x48f6,0x48f7, + 0x48f8,0x48f9,0x48fa,0x48fb,0x48fc,0x48fd,0x48fe,0x48ff, + 0x4900,0x4901,0x4902,0x4903,0x4904,0x4905,0x4906,0x4907, + 0x4908,0x4909,0x490a,0x490b,0x490c,0x490d,0x490e,0x490f, + 0x4910,0x4911,0x4912,0x4913,0x4914,0x4915,0x4916,0x4917, + 0x4918,0x4919,0x491a,0x491b,0x491c,0x491d,0x491e,0x491f, + 0x4920,0x4921,0x4922,0x4923,0x4924,0x4925,0x4926,0x4927, + 0x4928,0x4929,0x492a,0x492b,0x492c,0x492d,0x492e,0x492f, + 0x4930,0x4931,0x4932,0x4933,0x4934,0x4935,0x4936,0x4937, + 0x4938,0x4939,0x493a,0x493b,0x493c,0x493d,0x493e,0x493f, + 0x4940,0x4941,0x4942,0x4943,0x4944,0x4945,0x4946,0x4947, + 0x4948,0x4949,0x494a,0x494b,0x494c,0x494d,0x494e,0x494f, + 0x4950,0x4951,0x4952,0x4953,0x4954,0x4955,0x4956,0x4957, + 0x4958,0x4959,0x495a,0x495b,0x495c,0x495d,0x495e,0x495f, + 0x4960,0x4961,0x4962,0x4963,0x4964,0x4965,0x4966,0x4967, + 0x4968,0x4969,0x496a,0x496b,0x496c,0x496d,0x496e,0x496f, + 0x4970,0x4971,0x4972,0x4973,0x4974,0x4975,0x4976,0x4977, + 0x4978,0x4979,0x497a,0x497b,0x497c,0x497d,0x497e,0x497f, + 0x4980,0x4981,0x4982,0x4983,0x4984,0x4985,0x4986,0x4987, + 0x4988,0x4989,0x498a,0x498b,0x498c,0x498d,0x498e,0x498f, + 0x4990,0x4991,0x4992,0x4993,0x4994,0x4995,0x4996,0x4997, + 0x4998,0x4999,0x499a,0x499b,0x499c,0x499d,0x499e,0x499f, + 0x49a0,0x49a1,0x49a2,0x49a3,0x49a4,0x49a5,0x49a6,0x49a7, + 0x49a8,0x49a9,0x49aa,0x49ab,0x49ac,0x49ad,0x49ae,0x49af, + 0x49b0,0x49b1,0x49b2,0x49b3,0x49b4,0x49b5,0x49b6,0x49b7, + 0x49b8,0x49b9,0x49ba,0x49bb,0x49bc,0x49bd,0x49be,0x49bf, + 0x49c0,0x49c1,0x49c2,0x49c3,0x49c4,0x49c5,0x49c6,0x49c7, + 0x49c8,0x49c9,0x49ca,0x49cb,0x49cc,0x49cd,0x49ce,0x49cf, + 0x49d0,0x49d1,0x49d2,0x49d3,0x49d4,0x49d5,0x49d6,0x49d7, + 0x49d8,0x49d9,0x49da,0x49db,0x49dc,0x49dd,0x49de,0x49df, + 0x49e0,0x49e1,0x49e2,0x49e3,0x49e4,0x49e5,0x49e6,0x49e7, + 0x49e8,0x49e9,0x49ea,0x49eb,0x49ec,0x49ed,0x49ee,0x49ef, + 0x49f0,0x49f1,0x49f2,0x49f3,0x49f4,0x49f5,0x49f6,0x49f7, + 0x49f8,0x49f9,0x49fa,0x49fb,0x49fc,0x49fd,0x49fe,0x49ff, + 0x4a00,0x4a01,0x4a02,0x4a03,0x4a04,0x4a05,0x4a06,0x4a07, + 0x4a08,0x4a09,0x4a0a,0x4a0b,0x4a0c,0x4a0d,0x4a0e,0x4a0f, + 0x4a10,0x4a11,0x4a12,0x4a13,0x4a14,0x4a15,0x4a16,0x4a17, + 0x4a18,0x4a19,0x4a1a,0x4a1b,0x4a1c,0x4a1d,0x4a1e,0x4a1f, + 0x4a20,0x4a21,0x4a22,0x4a23,0x4a24,0x4a25,0x4a26,0x4a27, + 0x4a28,0x4a29,0x4a2a,0x4a2b,0x4a2c,0x4a2d,0x4a2e,0x4a2f, + 0x4a30,0x4a31,0x4a32,0x4a33,0x4a34,0x4a35,0x4a36,0x4a37, + 0x4a38,0x4a39,0x4a3a,0x4a3b,0x4a3c,0x4a3d,0x4a3e,0x4a3f, + 0x4a40,0x4a41,0x4a42,0x4a43,0x4a44,0x4a45,0x4a46,0x4a47, + 0x4a48,0x4a49,0x4a4a,0x4a4b,0x4a4c,0x4a4d,0x4a4e,0x4a4f, + 0x4a50,0x4a51,0x4a52,0x4a53,0x4a54,0x4a55,0x4a56,0x4a57, + 0x4a58,0x4a59,0x4a5a,0x4a5b,0x4a5c,0x4a5d,0x4a5e,0x4a5f, + 0x4a60,0x4a61,0x4a62,0x4a63,0x4a64,0x4a65,0x4a66,0x4a67, + 0x4a68,0x4a69,0x4a6a,0x4a6b,0x4a6c,0x4a6d,0x4a6e,0x4a6f, + 0x4a70,0x4a71,0x4a72,0x4a73,0x4a74,0x4a75,0x4a76,0x4a77, + 0x4a78,0x4a79,0x4a7a,0x4a7b,0x4a7c,0x4a7d,0x4a7e,0x4a7f, + 0x4a80,0x4a81,0x4a82,0x4a83,0x4a84,0x4a85,0x4a86,0x4a87, + 0x4a88,0x4a89,0x4a8a,0x4a8b,0x4a8c,0x4a8d,0x4a8e,0x4a8f, + 0x4a90,0x4a91,0x4a92,0x4a93,0x4a94,0x4a95,0x4a96,0x4a97, + 0x4a98,0x4a99,0x4a9a,0x4a9b,0x4a9c,0x4a9d,0x4a9e,0x4a9f, + 0x4aa0,0x4aa1,0x4aa2,0x4aa3,0x4aa4,0x4aa5,0x4aa6,0x4aa7, + 0x4aa8,0x4aa9,0x4aaa,0x4aab,0x4aac,0x4aad,0x4aae,0x4aaf, + 0x4ab0,0x4ab1,0x4ab2,0x4ab3,0x4ab4,0x4ab5,0x4ab6,0x4ab7, + 0x4ab8,0x4ab9,0x4aba,0x4abb,0x4abc,0x4abd,0x4abe,0x4abf, + 0x4ac0,0x4ac1,0x4ac2,0x4ac3,0x4ac4,0x4ac5,0x4ac6,0x4ac7, + 0x4ac8,0x4ac9,0x4aca,0x4acb,0x4acc,0x4acd,0x4ace,0x4acf, + 0x4ad0,0x4ad1,0x4ad2,0x4ad3,0x4ad4,0x4ad5,0x4ad6,0x4ad7, + 0x4ad8,0x4ad9,0x4ada,0x4adb,0x4adc,0x4add,0x4ade,0x4adf, + 0x4ae0,0x4ae1,0x4ae2,0x4ae3,0x4ae4,0x4ae5,0x4ae6,0x4ae7, + 0x4ae8,0x4ae9,0x4aea,0x4aeb,0x4aec,0x4aed,0x4aee,0x4aef, + 0x4af0,0x4af1,0x4af2,0x4af3,0x4af4,0x4af5,0x4af6,0x4af7, + 0x4af8,0x4af9,0x4afa,0x4afb,0x4afc,0x4afd,0x4afe,0x4aff, + 0x4b00,0x4b01,0x4b02,0x4b03,0x4b04,0x4b05,0x4b06,0x4b07, + 0x4b08,0x4b09,0x4b0a,0x4b0b,0x4b0c,0x4b0d,0x4b0e,0x4b0f, + 0x4b10,0x4b11,0x4b12,0x4b13,0x4b14,0x4b15,0x4b16,0x4b17, + 0x4b18,0x4b19,0x4b1a,0x4b1b,0x4b1c,0x4b1d,0x4b1e,0x4b1f, + 0x4b20,0x4b21,0x4b22,0x4b23,0x4b24,0x4b25,0x4b26,0x4b27, + 0x4b28,0x4b29,0x4b2a,0x4b2b,0x4b2c,0x4b2d,0x4b2e,0x4b2f, + 0x4b30,0x4b31,0x4b32,0x4b33,0x4b34,0x4b35,0x4b36,0x4b37, + 0x4b38,0x4b39,0x4b3a,0x4b3b,0x4b3c,0x4b3d,0x4b3e,0x4b3f, + 0x4b40,0x4b41,0x4b42,0x4b43,0x4b44,0x4b45,0x4b46,0x4b47, + 0x4b48,0x4b49,0x4b4a,0x4b4b,0x4b4c,0x4b4d,0x4b4e,0x4b4f, + 0x4b50,0x4b51,0x4b52,0x4b53,0x4b54,0x4b55,0x4b56,0x4b57, + 0x4b58,0x4b59,0x4b5a,0x4b5b,0x4b5c,0x4b5d,0x4b5e,0x4b5f, + 0x4b60,0x4b61,0x4b62,0x4b63,0x4b64,0x4b65,0x4b66,0x4b67, + 0x4b68,0x4b69,0x4b6a,0x4b6b,0x4b6c,0x4b6d,0x4b6e,0x4b6f, + 0x4b70,0x4b71,0x4b72,0x4b73,0x4b74,0x4b75,0x4b76,0x4b77, + 0x4b78,0x4b79,0x4b7a,0x4b7b,0x4b7c,0x4b7d,0x4b7e,0x4b7f, + 0x4b80,0x4b81,0x4b82,0x4b83,0x4b84,0x4b85,0x4b86,0x4b87, + 0x4b88,0x4b89,0x4b8a,0x4b8b,0x4b8c,0x4b8d,0x4b8e,0x4b8f, + 0x4b90,0x4b91,0x4b92,0x4b93,0x4b94,0x4b95,0x4b96,0x4b97, + 0x4b98,0x4b99,0x4b9a,0x4b9b,0x4b9c,0x4b9d,0x4b9e,0x4b9f, + 0x4ba0,0x4ba1,0x4ba2,0x4ba3,0x4ba4,0x4ba5,0x4ba6,0x4ba7, + 0x4ba8,0x4ba9,0x4baa,0x4bab,0x4bac,0x4bad,0x4bae,0x4baf, + 0x4bb0,0x4bb1,0x4bb2,0x4bb3,0x4bb4,0x4bb5,0x4bb6,0x4bb7, + 0x4bb8,0x4bb9,0x4bba,0x4bbb,0x4bbc,0x4bbd,0x4bbe,0x4bbf, + 0x4bc0,0x4bc1,0x4bc2,0x4bc3,0x4bc4,0x4bc5,0x4bc6,0x4bc7, + 0x4bc8,0x4bc9,0x4bca,0x4bcb,0x4bcc,0x4bcd,0x4bce,0x4bcf, + 0x4bd0,0x4bd1,0x4bd2,0x4bd3,0x4bd4,0x4bd5,0x4bd6,0x4bd7, + 0x4bd8,0x4bd9,0x4bda,0x4bdb,0x4bdc,0x4bdd,0x4bde,0x4bdf, + 0x4be0,0x4be1,0x4be2,0x4be3,0x4be4,0x4be5,0x4be6,0x4be7, + 0x4be8,0x4be9,0x4bea,0x4beb,0x4bec,0x4bed,0x4bee,0x4bef, + 0x4bf0,0x4bf1,0x4bf2,0x4bf3,0x4bf4,0x4bf5,0x4bf6,0x4bf7, + 0x4bf8,0x4bf9,0x4bfa,0x4bfb,0x4bfc,0x4bfd,0x4bfe,0x4bff, + 0x4c00,0x4c01,0x4c02,0x4c03,0x4c04,0x4c05,0x4c06,0x4c07, + 0x4c08,0x4c09,0x4c0a,0x4c0b,0x4c0c,0x4c0d,0x4c0e,0x4c0f, + 0x4c10,0x4c11,0x4c12,0x4c13,0x4c14,0x4c15,0x4c16,0x4c17, + 0x4c18,0x4c19,0x4c1a,0x4c1b,0x4c1c,0x4c1d,0x4c1e,0x4c1f, + 0x4c20,0x4c21,0x4c22,0x4c23,0x4c24,0x4c25,0x4c26,0x4c27, + 0x4c28,0x4c29,0x4c2a,0x4c2b,0x4c2c,0x4c2d,0x4c2e,0x4c2f, + 0x4c30,0x4c31,0x4c32,0x4c33,0x4c34,0x4c35,0x4c36,0x4c37, + 0x4c38,0x4c39,0x4c3a,0x4c3b,0x4c3c,0x4c3d,0x4c3e,0x4c3f, + 0x4c40,0x4c41,0x4c42,0x4c43,0x4c44,0x4c45,0x4c46,0x4c47, + 0x4c48,0x4c49,0x4c4a,0x4c4b,0x4c4c,0x4c4d,0x4c4e,0x4c4f, + 0x4c50,0x4c51,0x4c52,0x4c53,0x4c54,0x4c55,0x4c56,0x4c57, + 0x4c58,0x4c59,0x4c5a,0x4c5b,0x4c5c,0x4c5d,0x4c5e,0x4c5f, + 0x4c60,0x4c61,0x4c62,0x4c63,0x4c64,0x4c65,0x4c66,0x4c67, + 0x4c68,0x4c69,0x4c6a,0x4c6b,0x4c6c,0x4c6d,0x4c6e,0x4c6f, + 0x4c70,0x4c71,0x4c72,0x4c73,0x4c74,0x4c75,0x4c76,0x4c77, + 0x4c78,0x4c79,0x4c7a,0x4c7b,0x4c7c,0x4c7d,0x4c7e,0x4c7f, + 0x4c80,0x4c81,0x4c82,0x4c83,0x4c84,0x4c85,0x4c86,0x4c87, + 0x4c88,0x4c89,0x4c8a,0x4c8b,0x4c8c,0x4c8d,0x4c8e,0x4c8f, + 0x4c90,0x4c91,0x4c92,0x4c93,0x4c94,0x4c95,0x4c96,0x4c97, + 0x4c98,0x4c99,0x4c9a,0x4c9b,0x4c9c,0x4c9d,0x4c9e,0x4c9f, + 0x4ca0,0x4ca1,0x4ca2,0x4ca3,0x4ca4,0x4ca5,0x4ca6,0x4ca7, + 0x4ca8,0x4ca9,0x4caa,0x4cab,0x4cac,0x4cad,0x4cae,0x4caf, + 0x4cb0,0x4cb1,0x4cb2,0x4cb3,0x4cb4,0x4cb5,0x4cb6,0x4cb7, + 0x4cb8,0x4cb9,0x4cba,0x4cbb,0x4cbc,0x4cbd,0x4cbe,0x4cbf, + 0x4cc0,0x4cc1,0x4cc2,0x4cc3,0x4cc4,0x4cc5,0x4cc6,0x4cc7, + 0x4cc8,0x4cc9,0x4cca,0x4ccb,0x4ccc,0x4ccd,0x4cce,0x4ccf, + 0x4cd0,0x4cd1,0x4cd2,0x4cd3,0x4cd4,0x4cd5,0x4cd6,0x4cd7, + 0x4cd8,0x4cd9,0x4cda,0x4cdb,0x4cdc,0x4cdd,0x4cde,0x4cdf, + 0x4ce0,0x4ce1,0x4ce2,0x4ce3,0x4ce4,0x4ce5,0x4ce6,0x4ce7, + 0x4ce8,0x4ce9,0x4cea,0x4ceb,0x4cec,0x4ced,0x4cee,0x4cef, + 0x4cf0,0x4cf1,0x4cf2,0x4cf3,0x4cf4,0x4cf5,0x4cf6,0x4cf7, + 0x4cf8,0x4cf9,0x4cfa,0x4cfb,0x4cfc,0x4cfd,0x4cfe,0x4cff, + 0x4d00,0x4d01,0x4d02,0x4d03,0x4d04,0x4d05,0x4d06,0x4d07, + 0x4d08,0x4d09,0x4d0a,0x4d0b,0x4d0c,0x4d0d,0x4d0e,0x4d0f, + 0x4d10,0x4d11,0x4d12,0x4d13,0x4d14,0x4d15,0x4d16,0x4d17, + 0x4d18,0x4d19,0x4d1a,0x4d1b,0x4d1c,0x4d1d,0x4d1e,0x4d1f, + 0x4d20,0x4d21,0x4d22,0x4d23,0x4d24,0x4d25,0x4d26,0x4d27, + 0x4d28,0x4d29,0x4d2a,0x4d2b,0x4d2c,0x4d2d,0x4d2e,0x4d2f, + 0x4d30,0x4d31,0x4d32,0x4d33,0x4d34,0x4d35,0x4d36,0x4d37, + 0x4d38,0x4d39,0x4d3a,0x4d3b,0x4d3c,0x4d3d,0x4d3e,0x4d3f, + 0x4d40,0x4d41,0x4d42,0x4d43,0x4d44,0x4d45,0x4d46,0x4d47, + 0x4d48,0x4d49,0x4d4a,0x4d4b,0x4d4c,0x4d4d,0x4d4e,0x4d4f, + 0x4d50,0x4d51,0x4d52,0x4d53,0x4d54,0x4d55,0x4d56,0x4d57, + 0x4d58,0x4d59,0x4d5a,0x4d5b,0x4d5c,0x4d5d,0x4d5e,0x4d5f, + 0x4d60,0x4d61,0x4d62,0x4d63,0x4d64,0x4d65,0x4d66,0x4d67, + 0x4d68,0x4d69,0x4d6a,0x4d6b,0x4d6c,0x4d6d,0x4d6e,0x4d6f, + 0x4d70,0x4d71,0x4d72,0x4d73,0x4d74,0x4d75,0x4d76,0x4d77, + 0x4d78,0x4d79,0x4d7a,0x4d7b,0x4d7c,0x4d7d,0x4d7e,0x4d7f, + 0x4d80,0x4d81,0x4d82,0x4d83,0x4d84,0x4d85,0x4d86,0x4d87, + 0x4d88,0x4d89,0x4d8a,0x4d8b,0x4d8c,0x4d8d,0x4d8e,0x4d8f, + 0x4d90,0x4d91,0x4d92,0x4d93,0x4d94,0x4d95,0x4d96,0x4d97, + 0x4d98,0x4d99,0x4d9a,0x4d9b,0x4d9c,0x4d9d,0x4d9e,0x4d9f, + 0x4da0,0x4da1,0x4da2,0x4da3,0x4da4,0x4da5,0x4da6,0x4da7, + 0x4da8,0x4da9,0x4daa,0x4dab,0x4dac,0x4dad,0x4dae,0x4daf, + 0x4db0,0x4db1,0x4db2,0x4db3,0x4db4,0x4db5,0x4db6,0x4db7, + 0x4db8,0x4db9,0x4dba,0x4dbb,0x4dbc,0x4dbd,0x4dbe,0x4dbf, + 0x4dc0,0x4dc1,0x4dc2,0x4dc3,0x4dc4,0x4dc5,0x4dc6,0x4dc7, + 0x4dc8,0x4dc9,0x4dca,0x4dcb,0x4dcc,0x4dcd,0x4dce,0x4dcf, + 0x4dd0,0x4dd1,0x4dd2,0x4dd3,0x4dd4,0x4dd5,0x4dd6,0x4dd7, + 0x4dd8,0x4dd9,0x4dda,0x4ddb,0x4ddc,0x4ddd,0x4dde,0x4ddf, + 0x4de0,0x4de1,0x4de2,0x4de3,0x4de4,0x4de5,0x4de6,0x4de7, + 0x4de8,0x4de9,0x4dea,0x4deb,0x4dec,0x4ded,0x4dee,0x4def, + 0x4df0,0x4df1,0x4df2,0x4df3,0x4df4,0x4df5,0x4df6,0x4df7, + 0x4df8,0x4df9,0x4dfa,0x4dfb,0x4dfc,0x4dfd,0x4dfe,0x4dff, + 0x4e00,0x4e01,0x4e02,0x4e03,0x4e04,0x4e05,0x4e06,0x4e07, + 0x4e08,0x4e09,0x4e0a,0x4e0b,0x4e0c,0x4e0d,0x4e0e,0x4e0f, + 0x4e10,0x4e11,0x4e12,0x4e13,0x4e14,0x4e15,0x4e16,0x4e17, + 0x4e18,0x4e19,0x4e1a,0x4e1b,0x4e1c,0x4e1d,0x4e1e,0x4e1f, + 0x4e20,0x4e21,0x4e22,0x4e23,0x4e24,0x4e25,0x4e26,0x4e27, + 0x4e28,0x4e29,0x4e2a,0x4e2b,0x4e2c,0x4e2d,0x4e2e,0x4e2f, + 0x4e30,0x4e31,0x4e32,0x4e33,0x4e34,0x4e35,0x4e36,0x4e37, + 0x4e38,0x4e39,0x4e3a,0x4e3b,0x4e3c,0x4e3d,0x4e3e,0x4e3f, + 0x4e40,0x4e41,0x4e42,0x4e43,0x4e44,0x4e45,0x4e46,0x4e47, + 0x4e48,0x4e49,0x4e4a,0x4e4b,0x4e4c,0x4e4d,0x4e4e,0x4e4f, + 0x4e50,0x4e51,0x4e52,0x4e53,0x4e54,0x4e55,0x4e56,0x4e57, + 0x4e58,0x4e59,0x4e5a,0x4e5b,0x4e5c,0x4e5d,0x4e5e,0x4e5f, + 0x4e60,0x4e61,0x4e62,0x4e63,0x4e64,0x4e65,0x4e66,0x4e67, + 0x4e68,0x4e69,0x4e6a,0x4e6b,0x4e6c,0x4e6d,0x4e6e,0x4e6f, + 0x4e70,0x4e71,0x4e72,0x4e73,0x4e74,0x4e75,0x4e76,0x4e77, + 0x4e78,0x4e79,0x4e7a,0x4e7b,0x4e7c,0x4e7d,0x4e7e,0x4e7f, + 0x4e80,0x4e81,0x4e82,0x4e83,0x4e84,0x4e85,0x4e86,0x4e87, + 0x4e88,0x4e89,0x4e8a,0x4e8b,0x4e8c,0x4e8d,0x4e8e,0x4e8f, + 0x4e90,0x4e91,0x4e92,0x4e93,0x4e94,0x4e95,0x4e96,0x4e97, + 0x4e98,0x4e99,0x4e9a,0x4e9b,0x4e9c,0x4e9d,0x4e9e,0x4e9f, + 0x4ea0,0x4ea1,0x4ea2,0x4ea3,0x4ea4,0x4ea5,0x4ea6,0x4ea7, + 0x4ea8,0x4ea9,0x4eaa,0x4eab,0x4eac,0x4ead,0x4eae,0x4eaf, + 0x4eb0,0x4eb1,0x4eb2,0x4eb3,0x4eb4,0x4eb5,0x4eb6,0x4eb7, + 0x4eb8,0x4eb9,0x4eba,0x4ebb,0x4ebc,0x4ebd,0x4ebe,0x4ebf, + 0x4ec0,0x4ec1,0x4ec2,0x4ec3,0x4ec4,0x4ec5,0x4ec6,0x4ec7, + 0x4ec8,0x4ec9,0x4eca,0x4ecb,0x4ecc,0x4ecd,0x4ece,0x4ecf, + 0x4ed0,0x4ed1,0x4ed2,0x4ed3,0x4ed4,0x4ed5,0x4ed6,0x4ed7, + 0x4ed8,0x4ed9,0x4eda,0x4edb,0x4edc,0x4edd,0x4ede,0x4edf, + 0x4ee0,0x4ee1,0x4ee2,0x4ee3,0x4ee4,0x4ee5,0x4ee6,0x4ee7, + 0x4ee8,0x4ee9,0x4eea,0x4eeb,0x4eec,0x4eed,0x4eee,0x4eef, + 0x4ef0,0x4ef1,0x4ef2,0x4ef3,0x4ef4,0x4ef5,0x4ef6,0x4ef7, + 0x4ef8,0x4ef9,0x4efa,0x4efb,0x4efc,0x4efd,0x4efe,0x4eff, + 0x4f00,0x4f01,0x4f02,0x4f03,0x4f04,0x4f05,0x4f06,0x4f07, + 0x4f08,0x4f09,0x4f0a,0x4f0b,0x4f0c,0x4f0d,0x4f0e,0x4f0f, + 0x4f10,0x4f11,0x4f12,0x4f13,0x4f14,0x4f15,0x4f16,0x4f17, + 0x4f18,0x4f19,0x4f1a,0x4f1b,0x4f1c,0x4f1d,0x4f1e,0x4f1f, + 0x4f20,0x4f21,0x4f22,0x4f23,0x4f24,0x4f25,0x4f26,0x4f27, + 0x4f28,0x4f29,0x4f2a,0x4f2b,0x4f2c,0x4f2d,0x4f2e,0x4f2f, + 0x4f30,0x4f31,0x4f32,0x4f33,0x4f34,0x4f35,0x4f36,0x4f37, + 0x4f38,0x4f39,0x4f3a,0x4f3b,0x4f3c,0x4f3d,0x4f3e,0x4f3f, + 0x4f40,0x4f41,0x4f42,0x4f43,0x4f44,0x4f45,0x4f46,0x4f47, + 0x4f48,0x4f49,0x4f4a,0x4f4b,0x4f4c,0x4f4d,0x4f4e,0x4f4f, + 0x4f50,0x4f51,0x4f52,0x4f53,0x4f54,0x4f55,0x4f56,0x4f57, + 0x4f58,0x4f59,0x4f5a,0x4f5b,0x4f5c,0x4f5d,0x4f5e,0x4f5f, + 0x4f60,0x4f61,0x4f62,0x4f63,0x4f64,0x4f65,0x4f66,0x4f67, + 0x4f68,0x4f69,0x4f6a,0x4f6b,0x4f6c,0x4f6d,0x4f6e,0x4f6f, + 0x4f70,0x4f71,0x4f72,0x4f73,0x4f74,0x4f75,0x4f76,0x4f77, + 0x4f78,0x4f79,0x4f7a,0x4f7b,0x4f7c,0x4f7d,0x4f7e,0x4f7f, + 0x4f80,0x4f81,0x4f82,0x4f83,0x4f84,0x4f85,0x4f86,0x4f87, + 0x4f88,0x4f89,0x4f8a,0x4f8b,0x4f8c,0x4f8d,0x4f8e,0x4f8f, + 0x4f90,0x4f91,0x4f92,0x4f93,0x4f94,0x4f95,0x4f96,0x4f97, + 0x4f98,0x4f99,0x4f9a,0x4f9b,0x4f9c,0x4f9d,0x4f9e,0x4f9f, + 0x4fa0,0x4fa1,0x4fa2,0x4fa3,0x4fa4,0x4fa5,0x4fa6,0x4fa7, + 0x4fa8,0x4fa9,0x4faa,0x4fab,0x4fac,0x4fad,0x4fae,0x4faf, + 0x4fb0,0x4fb1,0x4fb2,0x4fb3,0x4fb4,0x4fb5,0x4fb6,0x4fb7, + 0x4fb8,0x4fb9,0x4fba,0x4fbb,0x4fbc,0x4fbd,0x4fbe,0x4fbf, + 0x4fc0,0x4fc1,0x4fc2,0x4fc3,0x4fc4,0x4fc5,0x4fc6,0x4fc7, + 0x4fc8,0x4fc9,0x4fca,0x4fcb,0x4fcc,0x4fcd,0x4fce,0x4fcf, + 0x4fd0,0x4fd1,0x4fd2,0x4fd3,0x4fd4,0x4fd5,0x4fd6,0x4fd7, + 0x4fd8,0x4fd9,0x4fda,0x4fdb,0x4fdc,0x4fdd,0x4fde,0x4fdf, + 0x4fe0,0x4fe1,0x4fe2,0x4fe3,0x4fe4,0x4fe5,0x4fe6,0x4fe7, + 0x4fe8,0x4fe9,0x4fea,0x4feb,0x4fec,0x4fed,0x4fee,0x4fef, + 0x4ff0,0x4ff1,0x4ff2,0x4ff3,0x4ff4,0x4ff5,0x4ff6,0x4ff7, + 0x4ff8,0x4ff9,0x4ffa,0x4ffb,0x4ffc,0x4ffd,0x4ffe,0x4fff, + 0x5000,0x5001,0x5002,0x5003,0x5004,0x5005,0x5006,0x5007, + 0x5008,0x5009,0x500a,0x500b,0x500c,0x500d,0x500e,0x500f, + 0x5010,0x5011,0x5012,0x5013,0x5014,0x5015,0x5016,0x5017, + 0x5018,0x5019,0x501a,0x501b,0x501c,0x501d,0x501e,0x501f, + 0x5020,0x5021,0x5022,0x5023,0x5024,0x5025,0x5026,0x5027, + 0x5028,0x5029,0x502a,0x502b,0x502c,0x502d,0x502e,0x502f, + 0x5030,0x5031,0x5032,0x5033,0x5034,0x5035,0x5036,0x5037, + 0x5038,0x5039,0x503a,0x503b,0x503c,0x503d,0x503e,0x503f, + 0x5040,0x5041,0x5042,0x5043,0x5044,0x5045,0x5046,0x5047, + 0x5048,0x5049,0x504a,0x504b,0x504c,0x504d,0x504e,0x504f, + 0x5050,0x5051,0x5052,0x5053,0x5054,0x5055,0x5056,0x5057, + 0x5058,0x5059,0x505a,0x505b,0x505c,0x505d,0x505e,0x505f, + 0x5060,0x5061,0x5062,0x5063,0x5064,0x5065,0x5066,0x5067, + 0x5068,0x5069,0x506a,0x506b,0x506c,0x506d,0x506e,0x506f, + 0x5070,0x5071,0x5072,0x5073,0x5074,0x5075,0x5076,0x5077, + 0x5078,0x5079,0x507a,0x507b,0x507c,0x507d,0x507e,0x507f, + 0x5080,0x5081,0x5082,0x5083,0x5084,0x5085,0x5086,0x5087, + 0x5088,0x5089,0x508a,0x508b,0x508c,0x508d,0x508e,0x508f, + 0x5090,0x5091,0x5092,0x5093,0x5094,0x5095,0x5096,0x5097, + 0x5098,0x5099,0x509a,0x509b,0x509c,0x509d,0x509e,0x509f, + 0x50a0,0x50a1,0x50a2,0x50a3,0x50a4,0x50a5,0x50a6,0x50a7, + 0x50a8,0x50a9,0x50aa,0x50ab,0x50ac,0x50ad,0x50ae,0x50af, + 0x50b0,0x50b1,0x50b2,0x50b3,0x50b4,0x50b5,0x50b6,0x50b7, + 0x50b8,0x50b9,0x50ba,0x50bb,0x50bc,0x50bd,0x50be,0x50bf, + 0x50c0,0x50c1,0x50c2,0x50c3,0x50c4,0x50c5,0x50c6,0x50c7, + 0x50c8,0x50c9,0x50ca,0x50cb,0x50cc,0x50cd,0x50ce,0x50cf, + 0x50d0,0x50d1,0x50d2,0x50d3,0x50d4,0x50d5,0x50d6,0x50d7, + 0x50d8,0x50d9,0x50da,0x50db,0x50dc,0x50dd,0x50de,0x50df, + 0x50e0,0x50e1,0x50e2,0x50e3,0x50e4,0x50e5,0x50e6,0x50e7, + 0x50e8,0x50e9,0x50ea,0x50eb,0x50ec,0x50ed,0x50ee,0x50ef, + 0x50f0,0x50f1,0x50f2,0x50f3,0x50f4,0x50f5,0x50f6,0x50f7, + 0x50f8,0x50f9,0x50fa,0x50fb,0x50fc,0x50fd,0x50fe,0x50ff, + 0x5100,0x5101,0x5102,0x5103,0x5104,0x5105,0x5106,0x5107, + 0x5108,0x5109,0x510a,0x510b,0x510c,0x510d,0x510e,0x510f, + 0x5110,0x5111,0x5112,0x5113,0x5114,0x5115,0x5116,0x5117, + 0x5118,0x5119,0x511a,0x511b,0x511c,0x511d,0x511e,0x511f, + 0x5120,0x5121,0x5122,0x5123,0x5124,0x5125,0x5126,0x5127, + 0x5128,0x5129,0x512a,0x512b,0x512c,0x512d,0x512e,0x512f, + 0x5130,0x5131,0x5132,0x5133,0x5134,0x5135,0x5136,0x5137, + 0x5138,0x5139,0x513a,0x513b,0x513c,0x513d,0x513e,0x513f, + 0x5140,0x5141,0x5142,0x5143,0x5144,0x5145,0x5146,0x5147, + 0x5148,0x5149,0x514a,0x514b,0x514c,0x514d,0x514e,0x514f, + 0x5150,0x5151,0x5152,0x5153,0x5154,0x5155,0x5156,0x5157, + 0x5158,0x5159,0x515a,0x515b,0x515c,0x515d,0x515e,0x515f, + 0x5160,0x5161,0x5162,0x5163,0x5164,0x5165,0x5166,0x5167, + 0x5168,0x5169,0x516a,0x516b,0x516c,0x516d,0x516e,0x516f, + 0x5170,0x5171,0x5172,0x5173,0x5174,0x5175,0x5176,0x5177, + 0x5178,0x5179,0x517a,0x517b,0x517c,0x517d,0x517e,0x517f, + 0x5180,0x5181,0x5182,0x5183,0x5184,0x5185,0x5186,0x5187, + 0x5188,0x5189,0x518a,0x518b,0x518c,0x518d,0x518e,0x518f, + 0x5190,0x5191,0x5192,0x5193,0x5194,0x5195,0x5196,0x5197, + 0x5198,0x5199,0x519a,0x519b,0x519c,0x519d,0x519e,0x519f, + 0x51a0,0x51a1,0x51a2,0x51a3,0x51a4,0x51a5,0x51a6,0x51a7, + 0x51a8,0x51a9,0x51aa,0x51ab,0x51ac,0x51ad,0x51ae,0x51af, + 0x51b0,0x51b1,0x51b2,0x51b3,0x51b4,0x51b5,0x51b6,0x51b7, + 0x51b8,0x51b9,0x51ba,0x51bb,0x51bc,0x51bd,0x51be,0x51bf, + 0x51c0,0x51c1,0x51c2,0x51c3,0x51c4,0x51c5,0x51c6,0x51c7, + 0x51c8,0x51c9,0x51ca,0x51cb,0x51cc,0x51cd,0x51ce,0x51cf, + 0x51d0,0x51d1,0x51d2,0x51d3,0x51d4,0x51d5,0x51d6,0x51d7, + 0x51d8,0x51d9,0x51da,0x51db,0x51dc,0x51dd,0x51de,0x51df, + 0x51e0,0x51e1,0x51e2,0x51e3,0x51e4,0x51e5,0x51e6,0x51e7, + 0x51e8,0x51e9,0x51ea,0x51eb,0x51ec,0x51ed,0x51ee,0x51ef, + 0x51f0,0x51f1,0x51f2,0x51f3,0x51f4,0x51f5,0x51f6,0x51f7, + 0x51f8,0x51f9,0x51fa,0x51fb,0x51fc,0x51fd,0x51fe,0x51ff, + 0x5200,0x5201,0x5202,0x5203,0x5204,0x5205,0x5206,0x5207, + 0x5208,0x5209,0x520a,0x520b,0x520c,0x520d,0x520e,0x520f, + 0x5210,0x5211,0x5212,0x5213,0x5214,0x5215,0x5216,0x5217, + 0x5218,0x5219,0x521a,0x521b,0x521c,0x521d,0x521e,0x521f, + 0x5220,0x5221,0x5222,0x5223,0x5224,0x5225,0x5226,0x5227, + 0x5228,0x5229,0x522a,0x522b,0x522c,0x522d,0x522e,0x522f, + 0x5230,0x5231,0x5232,0x5233,0x5234,0x5235,0x5236,0x5237, + 0x5238,0x5239,0x523a,0x523b,0x523c,0x523d,0x523e,0x523f, + 0x5240,0x5241,0x5242,0x5243,0x5244,0x5245,0x5246,0x5247, + 0x5248,0x5249,0x524a,0x524b,0x524c,0x524d,0x524e,0x524f, + 0x5250,0x5251,0x5252,0x5253,0x5254,0x5255,0x5256,0x5257, + 0x5258,0x5259,0x525a,0x525b,0x525c,0x525d,0x525e,0x525f, + 0x5260,0x5261,0x5262,0x5263,0x5264,0x5265,0x5266,0x5267, + 0x5268,0x5269,0x526a,0x526b,0x526c,0x526d,0x526e,0x526f, + 0x5270,0x5271,0x5272,0x5273,0x5274,0x5275,0x5276,0x5277, + 0x5278,0x5279,0x527a,0x527b,0x527c,0x527d,0x527e,0x527f, + 0x5280,0x5281,0x5282,0x5283,0x5284,0x5285,0x5286,0x5287, + 0x5288,0x5289,0x528a,0x528b,0x528c,0x528d,0x528e,0x528f, + 0x5290,0x5291,0x5292,0x5293,0x5294,0x5295,0x5296,0x5297, + 0x5298,0x5299,0x529a,0x529b,0x529c,0x529d,0x529e,0x529f, + 0x52a0,0x52a1,0x52a2,0x52a3,0x52a4,0x52a5,0x52a6,0x52a7, + 0x52a8,0x52a9,0x52aa,0x52ab,0x52ac,0x52ad,0x52ae,0x52af, + 0x52b0,0x52b1,0x52b2,0x52b3,0x52b4,0x52b5,0x52b6,0x52b7, + 0x52b8,0x52b9,0x52ba,0x52bb,0x52bc,0x52bd,0x52be,0x52bf, + 0x52c0,0x52c1,0x52c2,0x52c3,0x52c4,0x52c5,0x52c6,0x52c7, + 0x52c8,0x52c9,0x52ca,0x52cb,0x52cc,0x52cd,0x52ce,0x52cf, + 0x52d0,0x52d1,0x52d2,0x52d3,0x52d4,0x52d5,0x52d6,0x52d7, + 0x52d8,0x52d9,0x52da,0x52db,0x52dc,0x52dd,0x52de,0x52df, + 0x52e0,0x52e1,0x52e2,0x52e3,0x52e4,0x52e5,0x52e6,0x52e7, + 0x52e8,0x52e9,0x52ea,0x52eb,0x52ec,0x52ed,0x52ee,0x52ef, + 0x52f0,0x52f1,0x52f2,0x52f3,0x52f4,0x52f5,0x52f6,0x52f7, + 0x52f8,0x52f9,0x52fa,0x52fb,0x52fc,0x52fd,0x52fe,0x52ff, + 0x5300,0x5301,0x5302,0x5303,0x5304,0x5305,0x5306,0x5307, + 0x5308,0x5309,0x530a,0x530b,0x530c,0x530d,0x530e,0x530f, + 0x5310,0x5311,0x5312,0x5313,0x5314,0x5315,0x5316,0x5317, + 0x5318,0x5319,0x531a,0x531b,0x531c,0x531d,0x531e,0x531f, + 0x5320,0x5321,0x5322,0x5323,0x5324,0x5325,0x5326,0x5327, + 0x5328,0x5329,0x532a,0x532b,0x532c,0x532d,0x532e,0x532f, + 0x5330,0x5331,0x5332,0x5333,0x5334,0x5335,0x5336,0x5337, + 0x5338,0x5339,0x533a,0x533b,0x533c,0x533d,0x533e,0x533f, + 0x5340,0x5341,0x5342,0x5343,0x5344,0x5345,0x5346,0x5347, + 0x5348,0x5349,0x534a,0x534b,0x534c,0x534d,0x534e,0x534f, + 0x5350,0x5351,0x5352,0x5353,0x5354,0x5355,0x5356,0x5357, + 0x5358,0x5359,0x535a,0x535b,0x535c,0x535d,0x535e,0x535f, + 0x5360,0x5361,0x5362,0x5363,0x5364,0x5365,0x5366,0x5367, + 0x5368,0x5369,0x536a,0x536b,0x536c,0x536d,0x536e,0x536f, + 0x5370,0x5371,0x5372,0x5373,0x5374,0x5375,0x5376,0x5377, + 0x5378,0x5379,0x537a,0x537b,0x537c,0x537d,0x537e,0x537f, + 0x5380,0x5381,0x5382,0x5383,0x5384,0x5385,0x5386,0x5387, + 0x5388,0x5389,0x538a,0x538b,0x538c,0x538d,0x538e,0x538f, + 0x5390,0x5391,0x5392,0x5393,0x5394,0x5395,0x5396,0x5397, + 0x5398,0x5399,0x539a,0x539b,0x539c,0x539d,0x539e,0x539f, + 0x53a0,0x53a1,0x53a2,0x53a3,0x53a4,0x53a5,0x53a6,0x53a7, + 0x53a8,0x53a9,0x53aa,0x53ab,0x53ac,0x53ad,0x53ae,0x53af, + 0x53b0,0x53b1,0x53b2,0x53b3,0x53b4,0x53b5,0x53b6,0x53b7, + 0x53b8,0x53b9,0x53ba,0x53bb,0x53bc,0x53bd,0x53be,0x53bf, + 0x53c0,0x53c1,0x53c2,0x53c3,0x53c4,0x53c5,0x53c6,0x53c7, + 0x53c8,0x53c9,0x53ca,0x53cb,0x53cc,0x53cd,0x53ce,0x53cf, + 0x53d0,0x53d1,0x53d2,0x53d3,0x53d4,0x53d5,0x53d6,0x53d7, + 0x53d8,0x53d9,0x53da,0x53db,0x53dc,0x53dd,0x53de,0x53df, + 0x53e0,0x53e1,0x53e2,0x53e3,0x53e4,0x53e5,0x53e6,0x53e7, + 0x53e8,0x53e9,0x53ea,0x53eb,0x53ec,0x53ed,0x53ee,0x53ef, + 0x53f0,0x53f1,0x53f2,0x53f3,0x53f4,0x53f5,0x53f6,0x53f7, + 0x53f8,0x53f9,0x53fa,0x53fb,0x53fc,0x53fd,0x53fe,0x53ff, + 0x5400,0x5401,0x5402,0x5403,0x5404,0x5405,0x5406,0x5407, + 0x5408,0x5409,0x540a,0x540b,0x540c,0x540d,0x540e,0x540f, + 0x5410,0x5411,0x5412,0x5413,0x5414,0x5415,0x5416,0x5417, + 0x5418,0x5419,0x541a,0x541b,0x541c,0x541d,0x541e,0x541f, + 0x5420,0x5421,0x5422,0x5423,0x5424,0x5425,0x5426,0x5427, + 0x5428,0x5429,0x542a,0x542b,0x542c,0x542d,0x542e,0x542f, + 0x5430,0x5431,0x5432,0x5433,0x5434,0x5435,0x5436,0x5437, + 0x5438,0x5439,0x543a,0x543b,0x543c,0x543d,0x543e,0x543f, + 0x5440,0x5441,0x5442,0x5443,0x5444,0x5445,0x5446,0x5447, + 0x5448,0x5449,0x544a,0x544b,0x544c,0x544d,0x544e,0x544f, + 0x5450,0x5451,0x5452,0x5453,0x5454,0x5455,0x5456,0x5457, + 0x5458,0x5459,0x545a,0x545b,0x545c,0x545d,0x545e,0x545f, + 0x5460,0x5461,0x5462,0x5463,0x5464,0x5465,0x5466,0x5467, + 0x5468,0x5469,0x546a,0x546b,0x546c,0x546d,0x546e,0x546f, + 0x5470,0x5471,0x5472,0x5473,0x5474,0x5475,0x5476,0x5477, + 0x5478,0x5479,0x547a,0x547b,0x547c,0x547d,0x547e,0x547f, + 0x5480,0x5481,0x5482,0x5483,0x5484,0x5485,0x5486,0x5487, + 0x5488,0x5489,0x548a,0x548b,0x548c,0x548d,0x548e,0x548f, + 0x5490,0x5491,0x5492,0x5493,0x5494,0x5495,0x5496,0x5497, + 0x5498,0x5499,0x549a,0x549b,0x549c,0x549d,0x549e,0x549f, + 0x54a0,0x54a1,0x54a2,0x54a3,0x54a4,0x54a5,0x54a6,0x54a7, + 0x54a8,0x54a9,0x54aa,0x54ab,0x54ac,0x54ad,0x54ae,0x54af, + 0x54b0,0x54b1,0x54b2,0x54b3,0x54b4,0x54b5,0x54b6,0x54b7, + 0x54b8,0x54b9,0x54ba,0x54bb,0x54bc,0x54bd,0x54be,0x54bf, + 0x54c0,0x54c1,0x54c2,0x54c3,0x54c4,0x54c5,0x54c6,0x54c7, + 0x54c8,0x54c9,0x54ca,0x54cb,0x54cc,0x54cd,0x54ce,0x54cf, + 0x54d0,0x54d1,0x54d2,0x54d3,0x54d4,0x54d5,0x54d6,0x54d7, + 0x54d8,0x54d9,0x54da,0x54db,0x54dc,0x54dd,0x54de,0x54df, + 0x54e0,0x54e1,0x54e2,0x54e3,0x54e4,0x54e5,0x54e6,0x54e7, + 0x54e8,0x54e9,0x54ea,0x54eb,0x54ec,0x54ed,0x54ee,0x54ef, + 0x54f0,0x54f1,0x54f2,0x54f3,0x54f4,0x54f5,0x54f6,0x54f7, + 0x54f8,0x54f9,0x54fa,0x54fb,0x54fc,0x54fd,0x54fe,0x54ff, + 0x5500,0x5501,0x5502,0x5503,0x5504,0x5505,0x5506,0x5507, + 0x5508,0x5509,0x550a,0x550b,0x550c,0x550d,0x550e,0x550f, + 0x5510,0x5511,0x5512,0x5513,0x5514,0x5515,0x5516,0x5517, + 0x5518,0x5519,0x551a,0x551b,0x551c,0x551d,0x551e,0x551f, + 0x5520,0x5521,0x5522,0x5523,0x5524,0x5525,0x5526,0x5527, + 0x5528,0x5529,0x552a,0x552b,0x552c,0x552d,0x552e,0x552f, + 0x5530,0x5531,0x5532,0x5533,0x5534,0x5535,0x5536,0x5537, + 0x5538,0x5539,0x553a,0x553b,0x553c,0x553d,0x553e,0x553f, + 0x5540,0x5541,0x5542,0x5543,0x5544,0x5545,0x5546,0x5547, + 0x5548,0x5549,0x554a,0x554b,0x554c,0x554d,0x554e,0x554f, + 0x5550,0x5551,0x5552,0x5553,0x5554,0x5555,0x5556,0x5557, + 0x5558,0x5559,0x555a,0x555b,0x555c,0x555d,0x555e,0x555f, + 0x5560,0x5561,0x5562,0x5563,0x5564,0x5565,0x5566,0x5567, + 0x5568,0x5569,0x556a,0x556b,0x556c,0x556d,0x556e,0x556f, + 0x5570,0x5571,0x5572,0x5573,0x5574,0x5575,0x5576,0x5577, + 0x5578,0x5579,0x557a,0x557b,0x557c,0x557d,0x557e,0x557f, + 0x5580,0x5581,0x5582,0x5583,0x5584,0x5585,0x5586,0x5587, + 0x5588,0x5589,0x558a,0x558b,0x558c,0x558d,0x558e,0x558f, + 0x5590,0x5591,0x5592,0x5593,0x5594,0x5595,0x5596,0x5597, + 0x5598,0x5599,0x559a,0x559b,0x559c,0x559d,0x559e,0x559f, + 0x55a0,0x55a1,0x55a2,0x55a3,0x55a4,0x55a5,0x55a6,0x55a7, + 0x55a8,0x55a9,0x55aa,0x55ab,0x55ac,0x55ad,0x55ae,0x55af, + 0x55b0,0x55b1,0x55b2,0x55b3,0x55b4,0x55b5,0x55b6,0x55b7, + 0x55b8,0x55b9,0x55ba,0x55bb,0x55bc,0x55bd,0x55be,0x55bf, + 0x55c0,0x55c1,0x55c2,0x55c3,0x55c4,0x55c5,0x55c6,0x55c7, + 0x55c8,0x55c9,0x55ca,0x55cb,0x55cc,0x55cd,0x55ce,0x55cf, + 0x55d0,0x55d1,0x55d2,0x55d3,0x55d4,0x55d5,0x55d6,0x55d7, + 0x55d8,0x55d9,0x55da,0x55db,0x55dc,0x55dd,0x55de,0x55df, + 0x55e0,0x55e1,0x55e2,0x55e3,0x55e4,0x55e5,0x55e6,0x55e7, + 0x55e8,0x55e9,0x55ea,0x55eb,0x55ec,0x55ed,0x55ee,0x55ef, + 0x55f0,0x55f1,0x55f2,0x55f3,0x55f4,0x55f5,0x55f6,0x55f7, + 0x55f8,0x55f9,0x55fa,0x55fb,0x55fc,0x55fd,0x55fe,0x55ff, + 0x5600,0x5601,0x5602,0x5603,0x5604,0x5605,0x5606,0x5607, + 0x5608,0x5609,0x560a,0x560b,0x560c,0x560d,0x560e,0x560f, + 0x5610,0x5611,0x5612,0x5613,0x5614,0x5615,0x5616,0x5617, + 0x5618,0x5619,0x561a,0x561b,0x561c,0x561d,0x561e,0x561f, + 0x5620,0x5621,0x5622,0x5623,0x5624,0x5625,0x5626,0x5627, + 0x5628,0x5629,0x562a,0x562b,0x562c,0x562d,0x562e,0x562f, + 0x5630,0x5631,0x5632,0x5633,0x5634,0x5635,0x5636,0x5637, + 0x5638,0x5639,0x563a,0x563b,0x563c,0x563d,0x563e,0x563f, + 0x5640,0x5641,0x5642,0x5643,0x5644,0x5645,0x5646,0x5647, + 0x5648,0x5649,0x564a,0x564b,0x564c,0x564d,0x564e,0x564f, + 0x5650,0x5651,0x5652,0x5653,0x5654,0x5655,0x5656,0x5657, + 0x5658,0x5659,0x565a,0x565b,0x565c,0x565d,0x565e,0x565f, + 0x5660,0x5661,0x5662,0x5663,0x5664,0x5665,0x5666,0x5667, + 0x5668,0x5669,0x566a,0x566b,0x566c,0x566d,0x566e,0x566f, + 0x5670,0x5671,0x5672,0x5673,0x5674,0x5675,0x5676,0x5677, + 0x5678,0x5679,0x567a,0x567b,0x567c,0x567d,0x567e,0x567f, + 0x5680,0x5681,0x5682,0x5683,0x5684,0x5685,0x5686,0x5687, + 0x5688,0x5689,0x568a,0x568b,0x568c,0x568d,0x568e,0x568f, + 0x5690,0x5691,0x5692,0x5693,0x5694,0x5695,0x5696,0x5697, + 0x5698,0x5699,0x569a,0x569b,0x569c,0x569d,0x569e,0x569f, + 0x56a0,0x56a1,0x56a2,0x56a3,0x56a4,0x56a5,0x56a6,0x56a7, + 0x56a8,0x56a9,0x56aa,0x56ab,0x56ac,0x56ad,0x56ae,0x56af, + 0x56b0,0x56b1,0x56b2,0x56b3,0x56b4,0x56b5,0x56b6,0x56b7, + 0x56b8,0x56b9,0x56ba,0x56bb,0x56bc,0x56bd,0x56be,0x56bf, + 0x56c0,0x56c1,0x56c2,0x56c3,0x56c4,0x56c5,0x56c6,0x56c7, + 0x56c8,0x56c9,0x56ca,0x56cb,0x56cc,0x56cd,0x56ce,0x56cf, + 0x56d0,0x56d1,0x56d2,0x56d3,0x56d4,0x56d5,0x56d6,0x56d7, + 0x56d8,0x56d9,0x56da,0x56db,0x56dc,0x56dd,0x56de,0x56df, + 0x56e0,0x56e1,0x56e2,0x56e3,0x56e4,0x56e5,0x56e6,0x56e7, + 0x56e8,0x56e9,0x56ea,0x56eb,0x56ec,0x56ed,0x56ee,0x56ef, + 0x56f0,0x56f1,0x56f2,0x56f3,0x56f4,0x56f5,0x56f6,0x56f7, + 0x56f8,0x56f9,0x56fa,0x56fb,0x56fc,0x56fd,0x56fe,0x56ff, + 0x5700,0x5701,0x5702,0x5703,0x5704,0x5705,0x5706,0x5707, + 0x5708,0x5709,0x570a,0x570b,0x570c,0x570d,0x570e,0x570f, + 0x5710,0x5711,0x5712,0x5713,0x5714,0x5715,0x5716,0x5717, + 0x5718,0x5719,0x571a,0x571b,0x571c,0x571d,0x571e,0x571f, + 0x5720,0x5721,0x5722,0x5723,0x5724,0x5725,0x5726,0x5727, + 0x5728,0x5729,0x572a,0x572b,0x572c,0x572d,0x572e,0x572f, + 0x5730,0x5731,0x5732,0x5733,0x5734,0x5735,0x5736,0x5737, + 0x5738,0x5739,0x573a,0x573b,0x573c,0x573d,0x573e,0x573f, + 0x5740,0x5741,0x5742,0x5743,0x5744,0x5745,0x5746,0x5747, + 0x5748,0x5749,0x574a,0x574b,0x574c,0x574d,0x574e,0x574f, + 0x5750,0x5751,0x5752,0x5753,0x5754,0x5755,0x5756,0x5757, + 0x5758,0x5759,0x575a,0x575b,0x575c,0x575d,0x575e,0x575f, + 0x5760,0x5761,0x5762,0x5763,0x5764,0x5765,0x5766,0x5767, + 0x5768,0x5769,0x576a,0x576b,0x576c,0x576d,0x576e,0x576f, + 0x5770,0x5771,0x5772,0x5773,0x5774,0x5775,0x5776,0x5777, + 0x5778,0x5779,0x577a,0x577b,0x577c,0x577d,0x577e,0x577f, + 0x5780,0x5781,0x5782,0x5783,0x5784,0x5785,0x5786,0x5787, + 0x5788,0x5789,0x578a,0x578b,0x578c,0x578d,0x578e,0x578f, + 0x5790,0x5791,0x5792,0x5793,0x5794,0x5795,0x5796,0x5797, + 0x5798,0x5799,0x579a,0x579b,0x579c,0x579d,0x579e,0x579f, + 0x57a0,0x57a1,0x57a2,0x57a3,0x57a4,0x57a5,0x57a6,0x57a7, + 0x57a8,0x57a9,0x57aa,0x57ab,0x57ac,0x57ad,0x57ae,0x57af, + 0x57b0,0x57b1,0x57b2,0x57b3,0x57b4,0x57b5,0x57b6,0x57b7, + 0x57b8,0x57b9,0x57ba,0x57bb,0x57bc,0x57bd,0x57be,0x57bf, + 0x57c0,0x57c1,0x57c2,0x57c3,0x57c4,0x57c5,0x57c6,0x57c7, + 0x57c8,0x57c9,0x57ca,0x57cb,0x57cc,0x57cd,0x57ce,0x57cf, + 0x57d0,0x57d1,0x57d2,0x57d3,0x57d4,0x57d5,0x57d6,0x57d7, + 0x57d8,0x57d9,0x57da,0x57db,0x57dc,0x57dd,0x57de,0x57df, + 0x57e0,0x57e1,0x57e2,0x57e3,0x57e4,0x57e5,0x57e6,0x57e7, + 0x57e8,0x57e9,0x57ea,0x57eb,0x57ec,0x57ed,0x57ee,0x57ef, + 0x57f0,0x57f1,0x57f2,0x57f3,0x57f4,0x57f5,0x57f6,0x57f7, + 0x57f8,0x57f9,0x57fa,0x57fb,0x57fc,0x57fd,0x57fe,0x57ff, + 0x5800,0x5801,0x5802,0x5803,0x5804,0x5805,0x5806,0x5807, + 0x5808,0x5809,0x580a,0x580b,0x580c,0x580d,0x580e,0x580f, + 0x5810,0x5811,0x5812,0x5813,0x5814,0x5815,0x5816,0x5817, + 0x5818,0x5819,0x581a,0x581b,0x581c,0x581d,0x581e,0x581f, + 0x5820,0x5821,0x5822,0x5823,0x5824,0x5825,0x5826,0x5827, + 0x5828,0x5829,0x582a,0x582b,0x582c,0x582d,0x582e,0x582f, + 0x5830,0x5831,0x5832,0x5833,0x5834,0x5835,0x5836,0x5837, + 0x5838,0x5839,0x583a,0x583b,0x583c,0x583d,0x583e,0x583f, + 0x5840,0x5841,0x5842,0x5843,0x5844,0x5845,0x5846,0x5847, + 0x5848,0x5849,0x584a,0x584b,0x584c,0x584d,0x584e,0x584f, + 0x5850,0x5851,0x5852,0x5853,0x5854,0x5855,0x5856,0x5857, + 0x5858,0x5859,0x585a,0x585b,0x585c,0x585d,0x585e,0x585f, + 0x5860,0x5861,0x5862,0x5863,0x5864,0x5865,0x5866,0x5867, + 0x5868,0x5869,0x586a,0x586b,0x586c,0x586d,0x586e,0x586f, + 0x5870,0x5871,0x5872,0x5873,0x5874,0x5875,0x5876,0x5877, + 0x5878,0x5879,0x587a,0x587b,0x587c,0x587d,0x587e,0x587f, + 0x5880,0x5881,0x5882,0x5883,0x5884,0x5885,0x5886,0x5887, + 0x5888,0x5889,0x588a,0x588b,0x588c,0x588d,0x588e,0x588f, + 0x5890,0x5891,0x5892,0x5893,0x5894,0x5895,0x5896,0x5897, + 0x5898,0x5899,0x589a,0x589b,0x589c,0x589d,0x589e,0x589f, + 0x58a0,0x58a1,0x58a2,0x58a3,0x58a4,0x58a5,0x58a6,0x58a7, + 0x58a8,0x58a9,0x58aa,0x58ab,0x58ac,0x58ad,0x58ae,0x58af, + 0x58b0,0x58b1,0x58b2,0x58b3,0x58b4,0x58b5,0x58b6,0x58b7, + 0x58b8,0x58b9,0x58ba,0x58bb,0x58bc,0x58bd,0x58be,0x58bf, + 0x58c0,0x58c1,0x58c2,0x58c3,0x58c4,0x58c5,0x58c6,0x58c7, + 0x58c8,0x58c9,0x58ca,0x58cb,0x58cc,0x58cd,0x58ce,0x58cf, + 0x58d0,0x58d1,0x58d2,0x58d3,0x58d4,0x58d5,0x58d6,0x58d7, + 0x58d8,0x58d9,0x58da,0x58db,0x58dc,0x58dd,0x58de,0x58df, + 0x58e0,0x58e1,0x58e2,0x58e3,0x58e4,0x58e5,0x58e6,0x58e7, + 0x58e8,0x58e9,0x58ea,0x58eb,0x58ec,0x58ed,0x58ee,0x58ef, + 0x58f0,0x58f1,0x58f2,0x58f3,0x58f4,0x58f5,0x58f6,0x58f7, + 0x58f8,0x58f9,0x58fa,0x58fb,0x58fc,0x58fd,0x58fe,0x58ff, + 0x5900,0x5901,0x5902,0x5903,0x5904,0x5905,0x5906,0x5907, + 0x5908,0x5909,0x590a,0x590b,0x590c,0x590d,0x590e,0x590f, + 0x5910,0x5911,0x5912,0x5913,0x5914,0x5915,0x5916,0x5917, + 0x5918,0x5919,0x591a,0x591b,0x591c,0x591d,0x591e,0x591f, + 0x5920,0x5921,0x5922,0x5923,0x5924,0x5925,0x5926,0x5927, + 0x5928,0x5929,0x592a,0x592b,0x592c,0x592d,0x592e,0x592f, + 0x5930,0x5931,0x5932,0x5933,0x5934,0x5935,0x5936,0x5937, + 0x5938,0x5939,0x593a,0x593b,0x593c,0x593d,0x593e,0x593f, + 0x5940,0x5941,0x5942,0x5943,0x5944,0x5945,0x5946,0x5947, + 0x5948,0x5949,0x594a,0x594b,0x594c,0x594d,0x594e,0x594f, + 0x5950,0x5951,0x5952,0x5953,0x5954,0x5955,0x5956,0x5957, + 0x5958,0x5959,0x595a,0x595b,0x595c,0x595d,0x595e,0x595f, + 0x5960,0x5961,0x5962,0x5963,0x5964,0x5965,0x5966,0x5967, + 0x5968,0x5969,0x596a,0x596b,0x596c,0x596d,0x596e,0x596f, + 0x5970,0x5971,0x5972,0x5973,0x5974,0x5975,0x5976,0x5977, + 0x5978,0x5979,0x597a,0x597b,0x597c,0x597d,0x597e,0x597f, + 0x5980,0x5981,0x5982,0x5983,0x5984,0x5985,0x5986,0x5987, + 0x5988,0x5989,0x598a,0x598b,0x598c,0x598d,0x598e,0x598f, + 0x5990,0x5991,0x5992,0x5993,0x5994,0x5995,0x5996,0x5997, + 0x5998,0x5999,0x599a,0x599b,0x599c,0x599d,0x599e,0x599f, + 0x59a0,0x59a1,0x59a2,0x59a3,0x59a4,0x59a5,0x59a6,0x59a7, + 0x59a8,0x59a9,0x59aa,0x59ab,0x59ac,0x59ad,0x59ae,0x59af, + 0x59b0,0x59b1,0x59b2,0x59b3,0x59b4,0x59b5,0x59b6,0x59b7, + 0x59b8,0x59b9,0x59ba,0x59bb,0x59bc,0x59bd,0x59be,0x59bf, + 0x59c0,0x59c1,0x59c2,0x59c3,0x59c4,0x59c5,0x59c6,0x59c7, + 0x59c8,0x59c9,0x59ca,0x59cb,0x59cc,0x59cd,0x59ce,0x59cf, + 0x59d0,0x59d1,0x59d2,0x59d3,0x59d4,0x59d5,0x59d6,0x59d7, + 0x59d8,0x59d9,0x59da,0x59db,0x59dc,0x59dd,0x59de,0x59df, + 0x59e0,0x59e1,0x59e2,0x59e3,0x59e4,0x59e5,0x59e6,0x59e7, + 0x59e8,0x59e9,0x59ea,0x59eb,0x59ec,0x59ed,0x59ee,0x59ef, + 0x59f0,0x59f1,0x59f2,0x59f3,0x59f4,0x59f5,0x59f6,0x59f7, + 0x59f8,0x59f9,0x59fa,0x59fb,0x59fc,0x59fd,0x59fe,0x59ff, + 0x5a00,0x5a01,0x5a02,0x5a03,0x5a04,0x5a05,0x5a06,0x5a07, + 0x5a08,0x5a09,0x5a0a,0x5a0b,0x5a0c,0x5a0d,0x5a0e,0x5a0f, + 0x5a10,0x5a11,0x5a12,0x5a13,0x5a14,0x5a15,0x5a16,0x5a17, + 0x5a18,0x5a19,0x5a1a,0x5a1b,0x5a1c,0x5a1d,0x5a1e,0x5a1f, + 0x5a20,0x5a21,0x5a22,0x5a23,0x5a24,0x5a25,0x5a26,0x5a27, + 0x5a28,0x5a29,0x5a2a,0x5a2b,0x5a2c,0x5a2d,0x5a2e,0x5a2f, + 0x5a30,0x5a31,0x5a32,0x5a33,0x5a34,0x5a35,0x5a36,0x5a37, + 0x5a38,0x5a39,0x5a3a,0x5a3b,0x5a3c,0x5a3d,0x5a3e,0x5a3f, + 0x5a40,0x5a41,0x5a42,0x5a43,0x5a44,0x5a45,0x5a46,0x5a47, + 0x5a48,0x5a49,0x5a4a,0x5a4b,0x5a4c,0x5a4d,0x5a4e,0x5a4f, + 0x5a50,0x5a51,0x5a52,0x5a53,0x5a54,0x5a55,0x5a56,0x5a57, + 0x5a58,0x5a59,0x5a5a,0x5a5b,0x5a5c,0x5a5d,0x5a5e,0x5a5f, + 0x5a60,0x5a61,0x5a62,0x5a63,0x5a64,0x5a65,0x5a66,0x5a67, + 0x5a68,0x5a69,0x5a6a,0x5a6b,0x5a6c,0x5a6d,0x5a6e,0x5a6f, + 0x5a70,0x5a71,0x5a72,0x5a73,0x5a74,0x5a75,0x5a76,0x5a77, + 0x5a78,0x5a79,0x5a7a,0x5a7b,0x5a7c,0x5a7d,0x5a7e,0x5a7f, + 0x5a80,0x5a81,0x5a82,0x5a83,0x5a84,0x5a85,0x5a86,0x5a87, + 0x5a88,0x5a89,0x5a8a,0x5a8b,0x5a8c,0x5a8d,0x5a8e,0x5a8f, + 0x5a90,0x5a91,0x5a92,0x5a93,0x5a94,0x5a95,0x5a96,0x5a97, + 0x5a98,0x5a99,0x5a9a,0x5a9b,0x5a9c,0x5a9d,0x5a9e,0x5a9f, + 0x5aa0,0x5aa1,0x5aa2,0x5aa3,0x5aa4,0x5aa5,0x5aa6,0x5aa7, + 0x5aa8,0x5aa9,0x5aaa,0x5aab,0x5aac,0x5aad,0x5aae,0x5aaf, + 0x5ab0,0x5ab1,0x5ab2,0x5ab3,0x5ab4,0x5ab5,0x5ab6,0x5ab7, + 0x5ab8,0x5ab9,0x5aba,0x5abb,0x5abc,0x5abd,0x5abe,0x5abf, + 0x5ac0,0x5ac1,0x5ac2,0x5ac3,0x5ac4,0x5ac5,0x5ac6,0x5ac7, + 0x5ac8,0x5ac9,0x5aca,0x5acb,0x5acc,0x5acd,0x5ace,0x5acf, + 0x5ad0,0x5ad1,0x5ad2,0x5ad3,0x5ad4,0x5ad5,0x5ad6,0x5ad7, + 0x5ad8,0x5ad9,0x5ada,0x5adb,0x5adc,0x5add,0x5ade,0x5adf, + 0x5ae0,0x5ae1,0x5ae2,0x5ae3,0x5ae4,0x5ae5,0x5ae6,0x5ae7, + 0x5ae8,0x5ae9,0x5aea,0x5aeb,0x5aec,0x5aed,0x5aee,0x5aef, + 0x5af0,0x5af1,0x5af2,0x5af3,0x5af4,0x5af5,0x5af6,0x5af7, + 0x5af8,0x5af9,0x5afa,0x5afb,0x5afc,0x5afd,0x5afe,0x5aff, + 0x5b00,0x5b01,0x5b02,0x5b03,0x5b04,0x5b05,0x5b06,0x5b07, + 0x5b08,0x5b09,0x5b0a,0x5b0b,0x5b0c,0x5b0d,0x5b0e,0x5b0f, + 0x5b10,0x5b11,0x5b12,0x5b13,0x5b14,0x5b15,0x5b16,0x5b17, + 0x5b18,0x5b19,0x5b1a,0x5b1b,0x5b1c,0x5b1d,0x5b1e,0x5b1f, + 0x5b20,0x5b21,0x5b22,0x5b23,0x5b24,0x5b25,0x5b26,0x5b27, + 0x5b28,0x5b29,0x5b2a,0x5b2b,0x5b2c,0x5b2d,0x5b2e,0x5b2f, + 0x5b30,0x5b31,0x5b32,0x5b33,0x5b34,0x5b35,0x5b36,0x5b37, + 0x5b38,0x5b39,0x5b3a,0x5b3b,0x5b3c,0x5b3d,0x5b3e,0x5b3f, + 0x5b40,0x5b41,0x5b42,0x5b43,0x5b44,0x5b45,0x5b46,0x5b47, + 0x5b48,0x5b49,0x5b4a,0x5b4b,0x5b4c,0x5b4d,0x5b4e,0x5b4f, + 0x5b50,0x5b51,0x5b52,0x5b53,0x5b54,0x5b55,0x5b56,0x5b57, + 0x5b58,0x5b59,0x5b5a,0x5b5b,0x5b5c,0x5b5d,0x5b5e,0x5b5f, + 0x5b60,0x5b61,0x5b62,0x5b63,0x5b64,0x5b65,0x5b66,0x5b67, + 0x5b68,0x5b69,0x5b6a,0x5b6b,0x5b6c,0x5b6d,0x5b6e,0x5b6f, + 0x5b70,0x5b71,0x5b72,0x5b73,0x5b74,0x5b75,0x5b76,0x5b77, + 0x5b78,0x5b79,0x5b7a,0x5b7b,0x5b7c,0x5b7d,0x5b7e,0x5b7f, + 0x5b80,0x5b81,0x5b82,0x5b83,0x5b84,0x5b85,0x5b86,0x5b87, + 0x5b88,0x5b89,0x5b8a,0x5b8b,0x5b8c,0x5b8d,0x5b8e,0x5b8f, + 0x5b90,0x5b91,0x5b92,0x5b93,0x5b94,0x5b95,0x5b96,0x5b97, + 0x5b98,0x5b99,0x5b9a,0x5b9b,0x5b9c,0x5b9d,0x5b9e,0x5b9f, + 0x5ba0,0x5ba1,0x5ba2,0x5ba3,0x5ba4,0x5ba5,0x5ba6,0x5ba7, + 0x5ba8,0x5ba9,0x5baa,0x5bab,0x5bac,0x5bad,0x5bae,0x5baf, + 0x5bb0,0x5bb1,0x5bb2,0x5bb3,0x5bb4,0x5bb5,0x5bb6,0x5bb7, + 0x5bb8,0x5bb9,0x5bba,0x5bbb,0x5bbc,0x5bbd,0x5bbe,0x5bbf, + 0x5bc0,0x5bc1,0x5bc2,0x5bc3,0x5bc4,0x5bc5,0x5bc6,0x5bc7, + 0x5bc8,0x5bc9,0x5bca,0x5bcb,0x5bcc,0x5bcd,0x5bce,0x5bcf, + 0x5bd0,0x5bd1,0x5bd2,0x5bd3,0x5bd4,0x5bd5,0x5bd6,0x5bd7, + 0x5bd8,0x5bd9,0x5bda,0x5bdb,0x5bdc,0x5bdd,0x5bde,0x5bdf, + 0x5be0,0x5be1,0x5be2,0x5be3,0x5be4,0x5be5,0x5be6,0x5be7, + 0x5be8,0x5be9,0x5bea,0x5beb,0x5bec,0x5bed,0x5bee,0x5bef, + 0x5bf0,0x5bf1,0x5bf2,0x5bf3,0x5bf4,0x5bf5,0x5bf6,0x5bf7, + 0x5bf8,0x5bf9,0x5bfa,0x5bfb,0x5bfc,0x5bfd,0x5bfe,0x5bff, + 0x5c00,0x5c01,0x5c02,0x5c03,0x5c04,0x5c05,0x5c06,0x5c07, + 0x5c08,0x5c09,0x5c0a,0x5c0b,0x5c0c,0x5c0d,0x5c0e,0x5c0f, + 0x5c10,0x5c11,0x5c12,0x5c13,0x5c14,0x5c15,0x5c16,0x5c17, + 0x5c18,0x5c19,0x5c1a,0x5c1b,0x5c1c,0x5c1d,0x5c1e,0x5c1f, + 0x5c20,0x5c21,0x5c22,0x5c23,0x5c24,0x5c25,0x5c26,0x5c27, + 0x5c28,0x5c29,0x5c2a,0x5c2b,0x5c2c,0x5c2d,0x5c2e,0x5c2f, + 0x5c30,0x5c31,0x5c32,0x5c33,0x5c34,0x5c35,0x5c36,0x5c37, + 0x5c38,0x5c39,0x5c3a,0x5c3b,0x5c3c,0x5c3d,0x5c3e,0x5c3f, + 0x5c40,0x5c41,0x5c42,0x5c43,0x5c44,0x5c45,0x5c46,0x5c47, + 0x5c48,0x5c49,0x5c4a,0x5c4b,0x5c4c,0x5c4d,0x5c4e,0x5c4f, + 0x5c50,0x5c51,0x5c52,0x5c53,0x5c54,0x5c55,0x5c56,0x5c57, + 0x5c58,0x5c59,0x5c5a,0x5c5b,0x5c5c,0x5c5d,0x5c5e,0x5c5f, + 0x5c60,0x5c61,0x5c62,0x5c63,0x5c64,0x5c65,0x5c66,0x5c67, + 0x5c68,0x5c69,0x5c6a,0x5c6b,0x5c6c,0x5c6d,0x5c6e,0x5c6f, + 0x5c70,0x5c71,0x5c72,0x5c73,0x5c74,0x5c75,0x5c76,0x5c77, + 0x5c78,0x5c79,0x5c7a,0x5c7b,0x5c7c,0x5c7d,0x5c7e,0x5c7f, + 0x5c80,0x5c81,0x5c82,0x5c83,0x5c84,0x5c85,0x5c86,0x5c87, + 0x5c88,0x5c89,0x5c8a,0x5c8b,0x5c8c,0x5c8d,0x5c8e,0x5c8f, + 0x5c90,0x5c91,0x5c92,0x5c93,0x5c94,0x5c95,0x5c96,0x5c97, + 0x5c98,0x5c99,0x5c9a,0x5c9b,0x5c9c,0x5c9d,0x5c9e,0x5c9f, + 0x5ca0,0x5ca1,0x5ca2,0x5ca3,0x5ca4,0x5ca5,0x5ca6,0x5ca7, + 0x5ca8,0x5ca9,0x5caa,0x5cab,0x5cac,0x5cad,0x5cae,0x5caf, + 0x5cb0,0x5cb1,0x5cb2,0x5cb3,0x5cb4,0x5cb5,0x5cb6,0x5cb7, + 0x5cb8,0x5cb9,0x5cba,0x5cbb,0x5cbc,0x5cbd,0x5cbe,0x5cbf, + 0x5cc0,0x5cc1,0x5cc2,0x5cc3,0x5cc4,0x5cc5,0x5cc6,0x5cc7, + 0x5cc8,0x5cc9,0x5cca,0x5ccb,0x5ccc,0x5ccd,0x5cce,0x5ccf, + 0x5cd0,0x5cd1,0x5cd2,0x5cd3,0x5cd4,0x5cd5,0x5cd6,0x5cd7, + 0x5cd8,0x5cd9,0x5cda,0x5cdb,0x5cdc,0x5cdd,0x5cde,0x5cdf, + 0x5ce0,0x5ce1,0x5ce2,0x5ce3,0x5ce4,0x5ce5,0x5ce6,0x5ce7, + 0x5ce8,0x5ce9,0x5cea,0x5ceb,0x5cec,0x5ced,0x5cee,0x5cef, + 0x5cf0,0x5cf1,0x5cf2,0x5cf3,0x5cf4,0x5cf5,0x5cf6,0x5cf7, + 0x5cf8,0x5cf9,0x5cfa,0x5cfb,0x5cfc,0x5cfd,0x5cfe,0x5cff, + 0x5d00,0x5d01,0x5d02,0x5d03,0x5d04,0x5d05,0x5d06,0x5d07, + 0x5d08,0x5d09,0x5d0a,0x5d0b,0x5d0c,0x5d0d,0x5d0e,0x5d0f, + 0x5d10,0x5d11,0x5d12,0x5d13,0x5d14,0x5d15,0x5d16,0x5d17, + 0x5d18,0x5d19,0x5d1a,0x5d1b,0x5d1c,0x5d1d,0x5d1e,0x5d1f, + 0x5d20,0x5d21,0x5d22,0x5d23,0x5d24,0x5d25,0x5d26,0x5d27, + 0x5d28,0x5d29,0x5d2a,0x5d2b,0x5d2c,0x5d2d,0x5d2e,0x5d2f, + 0x5d30,0x5d31,0x5d32,0x5d33,0x5d34,0x5d35,0x5d36,0x5d37, + 0x5d38,0x5d39,0x5d3a,0x5d3b,0x5d3c,0x5d3d,0x5d3e,0x5d3f, + 0x5d40,0x5d41,0x5d42,0x5d43,0x5d44,0x5d45,0x5d46,0x5d47, + 0x5d48,0x5d49,0x5d4a,0x5d4b,0x5d4c,0x5d4d,0x5d4e,0x5d4f, + 0x5d50,0x5d51,0x5d52,0x5d53,0x5d54,0x5d55,0x5d56,0x5d57, + 0x5d58,0x5d59,0x5d5a,0x5d5b,0x5d5c,0x5d5d,0x5d5e,0x5d5f, + 0x5d60,0x5d61,0x5d62,0x5d63,0x5d64,0x5d65,0x5d66,0x5d67, + 0x5d68,0x5d69,0x5d6a,0x5d6b,0x5d6c,0x5d6d,0x5d6e,0x5d6f, + 0x5d70,0x5d71,0x5d72,0x5d73,0x5d74,0x5d75,0x5d76,0x5d77, + 0x5d78,0x5d79,0x5d7a,0x5d7b,0x5d7c,0x5d7d,0x5d7e,0x5d7f, + 0x5d80,0x5d81,0x5d82,0x5d83,0x5d84,0x5d85,0x5d86,0x5d87, + 0x5d88,0x5d89,0x5d8a,0x5d8b,0x5d8c,0x5d8d,0x5d8e,0x5d8f, + 0x5d90,0x5d91,0x5d92,0x5d93,0x5d94,0x5d95,0x5d96,0x5d97, + 0x5d98,0x5d99,0x5d9a,0x5d9b,0x5d9c,0x5d9d,0x5d9e,0x5d9f, + 0x5da0,0x5da1,0x5da2,0x5da3,0x5da4,0x5da5,0x5da6,0x5da7, + 0x5da8,0x5da9,0x5daa,0x5dab,0x5dac,0x5dad,0x5dae,0x5daf, + 0x5db0,0x5db1,0x5db2,0x5db3,0x5db4,0x5db5,0x5db6,0x5db7, + 0x5db8,0x5db9,0x5dba,0x5dbb,0x5dbc,0x5dbd,0x5dbe,0x5dbf, + 0x5dc0,0x5dc1,0x5dc2,0x5dc3,0x5dc4,0x5dc5,0x5dc6,0x5dc7, + 0x5dc8,0x5dc9,0x5dca,0x5dcb,0x5dcc,0x5dcd,0x5dce,0x5dcf, + 0x5dd0,0x5dd1,0x5dd2,0x5dd3,0x5dd4,0x5dd5,0x5dd6,0x5dd7, + 0x5dd8,0x5dd9,0x5dda,0x5ddb,0x5ddc,0x5ddd,0x5dde,0x5ddf, + 0x5de0,0x5de1,0x5de2,0x5de3,0x5de4,0x5de5,0x5de6,0x5de7, + 0x5de8,0x5de9,0x5dea,0x5deb,0x5dec,0x5ded,0x5dee,0x5def, + 0x5df0,0x5df1,0x5df2,0x5df3,0x5df4,0x5df5,0x5df6,0x5df7, + 0x5df8,0x5df9,0x5dfa,0x5dfb,0x5dfc,0x5dfd,0x5dfe,0x5dff, + 0x5e00,0x5e01,0x5e02,0x5e03,0x5e04,0x5e05,0x5e06,0x5e07, + 0x5e08,0x5e09,0x5e0a,0x5e0b,0x5e0c,0x5e0d,0x5e0e,0x5e0f, + 0x5e10,0x5e11,0x5e12,0x5e13,0x5e14,0x5e15,0x5e16,0x5e17, + 0x5e18,0x5e19,0x5e1a,0x5e1b,0x5e1c,0x5e1d,0x5e1e,0x5e1f, + 0x5e20,0x5e21,0x5e22,0x5e23,0x5e24,0x5e25,0x5e26,0x5e27, + 0x5e28,0x5e29,0x5e2a,0x5e2b,0x5e2c,0x5e2d,0x5e2e,0x5e2f, + 0x5e30,0x5e31,0x5e32,0x5e33,0x5e34,0x5e35,0x5e36,0x5e37, + 0x5e38,0x5e39,0x5e3a,0x5e3b,0x5e3c,0x5e3d,0x5e3e,0x5e3f, + 0x5e40,0x5e41,0x5e42,0x5e43,0x5e44,0x5e45,0x5e46,0x5e47, + 0x5e48,0x5e49,0x5e4a,0x5e4b,0x5e4c,0x5e4d,0x5e4e,0x5e4f, + 0x5e50,0x5e51,0x5e52,0x5e53,0x5e54,0x5e55,0x5e56,0x5e57, + 0x5e58,0x5e59,0x5e5a,0x5e5b,0x5e5c,0x5e5d,0x5e5e,0x5e5f, + 0x5e60,0x5e61,0x5e62,0x5e63,0x5e64,0x5e65,0x5e66,0x5e67, + 0x5e68,0x5e69,0x5e6a,0x5e6b,0x5e6c,0x5e6d,0x5e6e,0x5e6f, + 0x5e70,0x5e71,0x5e72,0x5e73,0x5e74,0x5e75,0x5e76,0x5e77, + 0x5e78,0x5e79,0x5e7a,0x5e7b,0x5e7c,0x5e7d,0x5e7e,0x5e7f, + 0x5e80,0x5e81,0x5e82,0x5e83,0x5e84,0x5e85,0x5e86,0x5e87, + 0x5e88,0x5e89,0x5e8a,0x5e8b,0x5e8c,0x5e8d,0x5e8e,0x5e8f, + 0x5e90,0x5e91,0x5e92,0x5e93,0x5e94,0x5e95,0x5e96,0x5e97, + 0x5e98,0x5e99,0x5e9a,0x5e9b,0x5e9c,0x5e9d,0x5e9e,0x5e9f, + 0x5ea0,0x5ea1,0x5ea2,0x5ea3,0x5ea4,0x5ea5,0x5ea6,0x5ea7, + 0x5ea8,0x5ea9,0x5eaa,0x5eab,0x5eac,0x5ead,0x5eae,0x5eaf, + 0x5eb0,0x5eb1,0x5eb2,0x5eb3,0x5eb4,0x5eb5,0x5eb6,0x5eb7, + 0x5eb8,0x5eb9,0x5eba,0x5ebb,0x5ebc,0x5ebd,0x5ebe,0x5ebf, + 0x5ec0,0x5ec1,0x5ec2,0x5ec3,0x5ec4,0x5ec5,0x5ec6,0x5ec7, + 0x5ec8,0x5ec9,0x5eca,0x5ecb,0x5ecc,0x5ecd,0x5ece,0x5ecf, + 0x5ed0,0x5ed1,0x5ed2,0x5ed3,0x5ed4,0x5ed5,0x5ed6,0x5ed7, + 0x5ed8,0x5ed9,0x5eda,0x5edb,0x5edc,0x5edd,0x5ede,0x5edf, + 0x5ee0,0x5ee1,0x5ee2,0x5ee3,0x5ee4,0x5ee5,0x5ee6,0x5ee7, + 0x5ee8,0x5ee9,0x5eea,0x5eeb,0x5eec,0x5eed,0x5eee,0x5eef, + 0x5ef0,0x5ef1,0x5ef2,0x5ef3,0x5ef4,0x5ef5,0x5ef6,0x5ef7, + 0x5ef8,0x5ef9,0x5efa,0x5efb,0x5efc,0x5efd,0x5efe,0x5eff, + 0x5f00,0x5f01,0x5f02,0x5f03,0x5f04,0x5f05,0x5f06,0x5f07, + 0x5f08,0x5f09,0x5f0a,0x5f0b,0x5f0c,0x5f0d,0x5f0e,0x5f0f, + 0x5f10,0x5f11,0x5f12,0x5f13,0x5f14,0x5f15,0x5f16,0x5f17, + 0x5f18,0x5f19,0x5f1a,0x5f1b,0x5f1c,0x5f1d,0x5f1e,0x5f1f, + 0x5f20,0x5f21,0x5f22,0x5f23,0x5f24,0x5f25,0x5f26,0x5f27, + 0x5f28,0x5f29,0x5f2a,0x5f2b,0x5f2c,0x5f2d,0x5f2e,0x5f2f, + 0x5f30,0x5f31,0x5f32,0x5f33,0x5f34,0x5f35,0x5f36,0x5f37, + 0x5f38,0x5f39,0x5f3a,0x5f3b,0x5f3c,0x5f3d,0x5f3e,0x5f3f, + 0x5f40,0x5f41,0x5f42,0x5f43,0x5f44,0x5f45,0x5f46,0x5f47, + 0x5f48,0x5f49,0x5f4a,0x5f4b,0x5f4c,0x5f4d,0x5f4e,0x5f4f, + 0x5f50,0x5f51,0x5f52,0x5f53,0x5f54,0x5f55,0x5f56,0x5f57, + 0x5f58,0x5f59,0x5f5a,0x5f5b,0x5f5c,0x5f5d,0x5f5e,0x5f5f, + 0x5f60,0x5f61,0x5f62,0x5f63,0x5f64,0x5f65,0x5f66,0x5f67, + 0x5f68,0x5f69,0x5f6a,0x5f6b,0x5f6c,0x5f6d,0x5f6e,0x5f6f, + 0x5f70,0x5f71,0x5f72,0x5f73,0x5f74,0x5f75,0x5f76,0x5f77, + 0x5f78,0x5f79,0x5f7a,0x5f7b,0x5f7c,0x5f7d,0x5f7e,0x5f7f, + 0x5f80,0x5f81,0x5f82,0x5f83,0x5f84,0x5f85,0x5f86,0x5f87, + 0x5f88,0x5f89,0x5f8a,0x5f8b,0x5f8c,0x5f8d,0x5f8e,0x5f8f, + 0x5f90,0x5f91,0x5f92,0x5f93,0x5f94,0x5f95,0x5f96,0x5f97, + 0x5f98,0x5f99,0x5f9a,0x5f9b,0x5f9c,0x5f9d,0x5f9e,0x5f9f, + 0x5fa0,0x5fa1,0x5fa2,0x5fa3,0x5fa4,0x5fa5,0x5fa6,0x5fa7, + 0x5fa8,0x5fa9,0x5faa,0x5fab,0x5fac,0x5fad,0x5fae,0x5faf, + 0x5fb0,0x5fb1,0x5fb2,0x5fb3,0x5fb4,0x5fb5,0x5fb6,0x5fb7, + 0x5fb8,0x5fb9,0x5fba,0x5fbb,0x5fbc,0x5fbd,0x5fbe,0x5fbf, + 0x5fc0,0x5fc1,0x5fc2,0x5fc3,0x5fc4,0x5fc5,0x5fc6,0x5fc7, + 0x5fc8,0x5fc9,0x5fca,0x5fcb,0x5fcc,0x5fcd,0x5fce,0x5fcf, + 0x5fd0,0x5fd1,0x5fd2,0x5fd3,0x5fd4,0x5fd5,0x5fd6,0x5fd7, + 0x5fd8,0x5fd9,0x5fda,0x5fdb,0x5fdc,0x5fdd,0x5fde,0x5fdf, + 0x5fe0,0x5fe1,0x5fe2,0x5fe3,0x5fe4,0x5fe5,0x5fe6,0x5fe7, + 0x5fe8,0x5fe9,0x5fea,0x5feb,0x5fec,0x5fed,0x5fee,0x5fef, + 0x5ff0,0x5ff1,0x5ff2,0x5ff3,0x5ff4,0x5ff5,0x5ff6,0x5ff7, + 0x5ff8,0x5ff9,0x5ffa,0x5ffb,0x5ffc,0x5ffd,0x5ffe,0x5fff, + 0x6000,0x6001,0x6002,0x6003,0x6004,0x6005,0x6006,0x6007, + 0x6008,0x6009,0x600a,0x600b,0x600c,0x600d,0x600e,0x600f, + 0x6010,0x6011,0x6012,0x6013,0x6014,0x6015,0x6016,0x6017, + 0x6018,0x6019,0x601a,0x601b,0x601c,0x601d,0x601e,0x601f, + 0x6020,0x6021,0x6022,0x6023,0x6024,0x6025,0x6026,0x6027, + 0x6028,0x6029,0x602a,0x602b,0x602c,0x602d,0x602e,0x602f, + 0x6030,0x6031,0x6032,0x6033,0x6034,0x6035,0x6036,0x6037, + 0x6038,0x6039,0x603a,0x603b,0x603c,0x603d,0x603e,0x603f, + 0x6040,0x6041,0x6042,0x6043,0x6044,0x6045,0x6046,0x6047, + 0x6048,0x6049,0x604a,0x604b,0x604c,0x604d,0x604e,0x604f, + 0x6050,0x6051,0x6052,0x6053,0x6054,0x6055,0x6056,0x6057, + 0x6058,0x6059,0x605a,0x605b,0x605c,0x605d,0x605e,0x605f, + 0x6060,0x6061,0x6062,0x6063,0x6064,0x6065,0x6066,0x6067, + 0x6068,0x6069,0x606a,0x606b,0x606c,0x606d,0x606e,0x606f, + 0x6070,0x6071,0x6072,0x6073,0x6074,0x6075,0x6076,0x6077, + 0x6078,0x6079,0x607a,0x607b,0x607c,0x607d,0x607e,0x607f, + 0x6080,0x6081,0x6082,0x6083,0x6084,0x6085,0x6086,0x6087, + 0x6088,0x6089,0x608a,0x608b,0x608c,0x608d,0x608e,0x608f, + 0x6090,0x6091,0x6092,0x6093,0x6094,0x6095,0x6096,0x6097, + 0x6098,0x6099,0x609a,0x609b,0x609c,0x609d,0x609e,0x609f, + 0x60a0,0x60a1,0x60a2,0x60a3,0x60a4,0x60a5,0x60a6,0x60a7, + 0x60a8,0x60a9,0x60aa,0x60ab,0x60ac,0x60ad,0x60ae,0x60af, + 0x60b0,0x60b1,0x60b2,0x60b3,0x60b4,0x60b5,0x60b6,0x60b7, + 0x60b8,0x60b9,0x60ba,0x60bb,0x60bc,0x60bd,0x60be,0x60bf, + 0x60c0,0x60c1,0x60c2,0x60c3,0x60c4,0x60c5,0x60c6,0x60c7, + 0x60c8,0x60c9,0x60ca,0x60cb,0x60cc,0x60cd,0x60ce,0x60cf, + 0x60d0,0x60d1,0x60d2,0x60d3,0x60d4,0x60d5,0x60d6,0x60d7, + 0x60d8,0x60d9,0x60da,0x60db,0x60dc,0x60dd,0x60de,0x60df, + 0x60e0,0x60e1,0x60e2,0x60e3,0x60e4,0x60e5,0x60e6,0x60e7, + 0x60e8,0x60e9,0x60ea,0x60eb,0x60ec,0x60ed,0x60ee,0x60ef, + 0x60f0,0x60f1,0x60f2,0x60f3,0x60f4,0x60f5,0x60f6,0x60f7, + 0x60f8,0x60f9,0x60fa,0x60fb,0x60fc,0x60fd,0x60fe,0x60ff, + 0x6100,0x6101,0x6102,0x6103,0x6104,0x6105,0x6106,0x6107, + 0x6108,0x6109,0x610a,0x610b,0x610c,0x610d,0x610e,0x610f, + 0x6110,0x6111,0x6112,0x6113,0x6114,0x6115,0x6116,0x6117, + 0x6118,0x6119,0x611a,0x611b,0x611c,0x611d,0x611e,0x611f, + 0x6120,0x6121,0x6122,0x6123,0x6124,0x6125,0x6126,0x6127, + 0x6128,0x6129,0x612a,0x612b,0x612c,0x612d,0x612e,0x612f, + 0x6130,0x6131,0x6132,0x6133,0x6134,0x6135,0x6136,0x6137, + 0x6138,0x6139,0x613a,0x613b,0x613c,0x613d,0x613e,0x613f, + 0x6140,0x6141,0x6142,0x6143,0x6144,0x6145,0x6146,0x6147, + 0x6148,0x6149,0x614a,0x614b,0x614c,0x614d,0x614e,0x614f, + 0x6150,0x6151,0x6152,0x6153,0x6154,0x6155,0x6156,0x6157, + 0x6158,0x6159,0x615a,0x615b,0x615c,0x615d,0x615e,0x615f, + 0x6160,0x6161,0x6162,0x6163,0x6164,0x6165,0x6166,0x6167, + 0x6168,0x6169,0x616a,0x616b,0x616c,0x616d,0x616e,0x616f, + 0x6170,0x6171,0x6172,0x6173,0x6174,0x6175,0x6176,0x6177, + 0x6178,0x6179,0x617a,0x617b,0x617c,0x617d,0x617e,0x617f, + 0x6180,0x6181,0x6182,0x6183,0x6184,0x6185,0x6186,0x6187, + 0x6188,0x6189,0x618a,0x618b,0x618c,0x618d,0x618e,0x618f, + 0x6190,0x6191,0x6192,0x6193,0x6194,0x6195,0x6196,0x6197, + 0x6198,0x6199,0x619a,0x619b,0x619c,0x619d,0x619e,0x619f, + 0x61a0,0x61a1,0x61a2,0x61a3,0x61a4,0x61a5,0x61a6,0x61a7, + 0x61a8,0x61a9,0x61aa,0x61ab,0x61ac,0x61ad,0x61ae,0x61af, + 0x61b0,0x61b1,0x61b2,0x61b3,0x61b4,0x61b5,0x61b6,0x61b7, + 0x61b8,0x61b9,0x61ba,0x61bb,0x61bc,0x61bd,0x61be,0x61bf, + 0x61c0,0x61c1,0x61c2,0x61c3,0x61c4,0x61c5,0x61c6,0x61c7, + 0x61c8,0x61c9,0x61ca,0x61cb,0x61cc,0x61cd,0x61ce,0x61cf, + 0x61d0,0x61d1,0x61d2,0x61d3,0x61d4,0x61d5,0x61d6,0x61d7, + 0x61d8,0x61d9,0x61da,0x61db,0x61dc,0x61dd,0x61de,0x61df, + 0x61e0,0x61e1,0x61e2,0x61e3,0x61e4,0x61e5,0x61e6,0x61e7, + 0x61e8,0x61e9,0x61ea,0x61eb,0x61ec,0x61ed,0x61ee,0x61ef, + 0x61f0,0x61f1,0x61f2,0x61f3,0x61f4,0x61f5,0x61f6,0x61f7, + 0x61f8,0x61f9,0x61fa,0x61fb,0x61fc,0x61fd,0x61fe,0x61ff, + 0x6200,0x6201,0x6202,0x6203,0x6204,0x6205,0x6206,0x6207, + 0x6208,0x6209,0x620a,0x620b,0x620c,0x620d,0x620e,0x620f, + 0x6210,0x6211,0x6212,0x6213,0x6214,0x6215,0x6216,0x6217, + 0x6218,0x6219,0x621a,0x621b,0x621c,0x621d,0x621e,0x621f, + 0x6220,0x6221,0x6222,0x6223,0x6224,0x6225,0x6226,0x6227, + 0x6228,0x6229,0x622a,0x622b,0x622c,0x622d,0x622e,0x622f, + 0x6230,0x6231,0x6232,0x6233,0x6234,0x6235,0x6236,0x6237, + 0x6238,0x6239,0x623a,0x623b,0x623c,0x623d,0x623e,0x623f, + 0x6240,0x6241,0x6242,0x6243,0x6244,0x6245,0x6246,0x6247, + 0x6248,0x6249,0x624a,0x624b,0x624c,0x624d,0x624e,0x624f, + 0x6250,0x6251,0x6252,0x6253,0x6254,0x6255,0x6256,0x6257, + 0x6258,0x6259,0x625a,0x625b,0x625c,0x625d,0x625e,0x625f, + 0x6260,0x6261,0x6262,0x6263,0x6264,0x6265,0x6266,0x6267, + 0x6268,0x6269,0x626a,0x626b,0x626c,0x626d,0x626e,0x626f, + 0x6270,0x6271,0x6272,0x6273,0x6274,0x6275,0x6276,0x6277, + 0x6278,0x6279,0x627a,0x627b,0x627c,0x627d,0x627e,0x627f, + 0x6280,0x6281,0x6282,0x6283,0x6284,0x6285,0x6286,0x6287, + 0x6288,0x6289,0x628a,0x628b,0x628c,0x628d,0x628e,0x628f, + 0x6290,0x6291,0x6292,0x6293,0x6294,0x6295,0x6296,0x6297, + 0x6298,0x6299,0x629a,0x629b,0x629c,0x629d,0x629e,0x629f, + 0x62a0,0x62a1,0x62a2,0x62a3,0x62a4,0x62a5,0x62a6,0x62a7, + 0x62a8,0x62a9,0x62aa,0x62ab,0x62ac,0x62ad,0x62ae,0x62af, + 0x62b0,0x62b1,0x62b2,0x62b3,0x62b4,0x62b5,0x62b6,0x62b7, + 0x62b8,0x62b9,0x62ba,0x62bb,0x62bc,0x62bd,0x62be,0x62bf, + 0x62c0,0x62c1,0x62c2,0x62c3,0x62c4,0x62c5,0x62c6,0x62c7, + 0x62c8,0x62c9,0x62ca,0x62cb,0x62cc,0x62cd,0x62ce,0x62cf, + 0x62d0,0x62d1,0x62d2,0x62d3,0x62d4,0x62d5,0x62d6,0x62d7, + 0x62d8,0x62d9,0x62da,0x62db,0x62dc,0x62dd,0x62de,0x62df, + 0x62e0,0x62e1,0x62e2,0x62e3,0x62e4,0x62e5,0x62e6,0x62e7, + 0x62e8,0x62e9,0x62ea,0x62eb,0x62ec,0x62ed,0x62ee,0x62ef, + 0x62f0,0x62f1,0x62f2,0x62f3,0x62f4,0x62f5,0x62f6,0x62f7, + 0x62f8,0x62f9,0x62fa,0x62fb,0x62fc,0x62fd,0x62fe,0x62ff, + 0x6300,0x6301,0x6302,0x6303,0x6304,0x6305,0x6306,0x6307, + 0x6308,0x6309,0x630a,0x630b,0x630c,0x630d,0x630e,0x630f, + 0x6310,0x6311,0x6312,0x6313,0x6314,0x6315,0x6316,0x6317, + 0x6318,0x6319,0x631a,0x631b,0x631c,0x631d,0x631e,0x631f, + 0x6320,0x6321,0x6322,0x6323,0x6324,0x6325,0x6326,0x6327, + 0x6328,0x6329,0x632a,0x632b,0x632c,0x632d,0x632e,0x632f, + 0x6330,0x6331,0x6332,0x6333,0x6334,0x6335,0x6336,0x6337, + 0x6338,0x6339,0x633a,0x633b,0x633c,0x633d,0x633e,0x633f, + 0x6340,0x6341,0x6342,0x6343,0x6344,0x6345,0x6346,0x6347, + 0x6348,0x6349,0x634a,0x634b,0x634c,0x634d,0x634e,0x634f, + 0x6350,0x6351,0x6352,0x6353,0x6354,0x6355,0x6356,0x6357, + 0x6358,0x6359,0x635a,0x635b,0x635c,0x635d,0x635e,0x635f, + 0x6360,0x6361,0x6362,0x6363,0x6364,0x6365,0x6366,0x6367, + 0x6368,0x6369,0x636a,0x636b,0x636c,0x636d,0x636e,0x636f, + 0x6370,0x6371,0x6372,0x6373,0x6374,0x6375,0x6376,0x6377, + 0x6378,0x6379,0x637a,0x637b,0x637c,0x637d,0x637e,0x637f, + 0x6380,0x6381,0x6382,0x6383,0x6384,0x6385,0x6386,0x6387, + 0x6388,0x6389,0x638a,0x638b,0x638c,0x638d,0x638e,0x638f, + 0x6390,0x6391,0x6392,0x6393,0x6394,0x6395,0x6396,0x6397, + 0x6398,0x6399,0x639a,0x639b,0x639c,0x639d,0x639e,0x639f, + 0x63a0,0x63a1,0x63a2,0x63a3,0x63a4,0x63a5,0x63a6,0x63a7, + 0x63a8,0x63a9,0x63aa,0x63ab,0x63ac,0x63ad,0x63ae,0x63af, + 0x63b0,0x63b1,0x63b2,0x63b3,0x63b4,0x63b5,0x63b6,0x63b7, + 0x63b8,0x63b9,0x63ba,0x63bb,0x63bc,0x63bd,0x63be,0x63bf, + 0x63c0,0x63c1,0x63c2,0x63c3,0x63c4,0x63c5,0x63c6,0x63c7, + 0x63c8,0x63c9,0x63ca,0x63cb,0x63cc,0x63cd,0x63ce,0x63cf, + 0x63d0,0x63d1,0x63d2,0x63d3,0x63d4,0x63d5,0x63d6,0x63d7, + 0x63d8,0x63d9,0x63da,0x63db,0x63dc,0x63dd,0x63de,0x63df, + 0x63e0,0x63e1,0x63e2,0x63e3,0x63e4,0x63e5,0x63e6,0x63e7, + 0x63e8,0x63e9,0x63ea,0x63eb,0x63ec,0x63ed,0x63ee,0x63ef, + 0x63f0,0x63f1,0x63f2,0x63f3,0x63f4,0x63f5,0x63f6,0x63f7, + 0x63f8,0x63f9,0x63fa,0x63fb,0x63fc,0x63fd,0x63fe,0x63ff, + 0x6400,0x6401,0x6402,0x6403,0x6404,0x6405,0x6406,0x6407, + 0x6408,0x6409,0x640a,0x640b,0x640c,0x640d,0x640e,0x640f, + 0x6410,0x6411,0x6412,0x6413,0x6414,0x6415,0x6416,0x6417, + 0x6418,0x6419,0x641a,0x641b,0x641c,0x641d,0x641e,0x641f, + 0x6420,0x6421,0x6422,0x6423,0x6424,0x6425,0x6426,0x6427, + 0x6428,0x6429,0x642a,0x642b,0x642c,0x642d,0x642e,0x642f, + 0x6430,0x6431,0x6432,0x6433,0x6434,0x6435,0x6436,0x6437, + 0x6438,0x6439,0x643a,0x643b,0x643c,0x643d,0x643e,0x643f, + 0x6440,0x6441,0x6442,0x6443,0x6444,0x6445,0x6446,0x6447, + 0x6448,0x6449,0x644a,0x644b,0x644c,0x644d,0x644e,0x644f, + 0x6450,0x6451,0x6452,0x6453,0x6454,0x6455,0x6456,0x6457, + 0x6458,0x6459,0x645a,0x645b,0x645c,0x645d,0x645e,0x645f, + 0x6460,0x6461,0x6462,0x6463,0x6464,0x6465,0x6466,0x6467, + 0x6468,0x6469,0x646a,0x646b,0x646c,0x646d,0x646e,0x646f, + 0x6470,0x6471,0x6472,0x6473,0x6474,0x6475,0x6476,0x6477, + 0x6478,0x6479,0x647a,0x647b,0x647c,0x647d,0x647e,0x647f, + 0x6480,0x6481,0x6482,0x6483,0x6484,0x6485,0x6486,0x6487, + 0x6488,0x6489,0x648a,0x648b,0x648c,0x648d,0x648e,0x648f, + 0x6490,0x6491,0x6492,0x6493,0x6494,0x6495,0x6496,0x6497, + 0x6498,0x6499,0x649a,0x649b,0x649c,0x649d,0x649e,0x649f, + 0x64a0,0x64a1,0x64a2,0x64a3,0x64a4,0x64a5,0x64a6,0x64a7, + 0x64a8,0x64a9,0x64aa,0x64ab,0x64ac,0x64ad,0x64ae,0x64af, + 0x64b0,0x64b1,0x64b2,0x64b3,0x64b4,0x64b5,0x64b6,0x64b7, + 0x64b8,0x64b9,0x64ba,0x64bb,0x64bc,0x64bd,0x64be,0x64bf, + 0x64c0,0x64c1,0x64c2,0x64c3,0x64c4,0x64c5,0x64c6,0x64c7, + 0x64c8,0x64c9,0x64ca,0x64cb,0x64cc,0x64cd,0x64ce,0x64cf, + 0x64d0,0x64d1,0x64d2,0x64d3,0x64d4,0x64d5,0x64d6,0x64d7, + 0x64d8,0x64d9,0x64da,0x64db,0x64dc,0x64dd,0x64de,0x64df, + 0x64e0,0x64e1,0x64e2,0x64e3,0x64e4,0x64e5,0x64e6,0x64e7, + 0x64e8,0x64e9,0x64ea,0x64eb,0x64ec,0x64ed,0x64ee,0x64ef, + 0x64f0,0x64f1,0x64f2,0x64f3,0x64f4,0x64f5,0x64f6,0x64f7, + 0x64f8,0x64f9,0x64fa,0x64fb,0x64fc,0x64fd,0x64fe,0x64ff, + 0x6500,0x6501,0x6502,0x6503,0x6504,0x6505,0x6506,0x6507, + 0x6508,0x6509,0x650a,0x650b,0x650c,0x650d,0x650e,0x650f, + 0x6510,0x6511,0x6512,0x6513,0x6514,0x6515,0x6516,0x6517, + 0x6518,0x6519,0x651a,0x651b,0x651c,0x651d,0x651e,0x651f, + 0x6520,0x6521,0x6522,0x6523,0x6524,0x6525,0x6526,0x6527, + 0x6528,0x6529,0x652a,0x652b,0x652c,0x652d,0x652e,0x652f, + 0x6530,0x6531,0x6532,0x6533,0x6534,0x6535,0x6536,0x6537, + 0x6538,0x6539,0x653a,0x653b,0x653c,0x653d,0x653e,0x653f, + 0x6540,0x6541,0x6542,0x6543,0x6544,0x6545,0x6546,0x6547, + 0x6548,0x6549,0x654a,0x654b,0x654c,0x654d,0x654e,0x654f, + 0x6550,0x6551,0x6552,0x6553,0x6554,0x6555,0x6556,0x6557, + 0x6558,0x6559,0x655a,0x655b,0x655c,0x655d,0x655e,0x655f, + 0x6560,0x6561,0x6562,0x6563,0x6564,0x6565,0x6566,0x6567, + 0x6568,0x6569,0x656a,0x656b,0x656c,0x656d,0x656e,0x656f, + 0x6570,0x6571,0x6572,0x6573,0x6574,0x6575,0x6576,0x6577, + 0x6578,0x6579,0x657a,0x657b,0x657c,0x657d,0x657e,0x657f, + 0x6580,0x6581,0x6582,0x6583,0x6584,0x6585,0x6586,0x6587, + 0x6588,0x6589,0x658a,0x658b,0x658c,0x658d,0x658e,0x658f, + 0x6590,0x6591,0x6592,0x6593,0x6594,0x6595,0x6596,0x6597, + 0x6598,0x6599,0x659a,0x659b,0x659c,0x659d,0x659e,0x659f, + 0x65a0,0x65a1,0x65a2,0x65a3,0x65a4,0x65a5,0x65a6,0x65a7, + 0x65a8,0x65a9,0x65aa,0x65ab,0x65ac,0x65ad,0x65ae,0x65af, + 0x65b0,0x65b1,0x65b2,0x65b3,0x65b4,0x65b5,0x65b6,0x65b7, + 0x65b8,0x65b9,0x65ba,0x65bb,0x65bc,0x65bd,0x65be,0x65bf, + 0x65c0,0x65c1,0x65c2,0x65c3,0x65c4,0x65c5,0x65c6,0x65c7, + 0x65c8,0x65c9,0x65ca,0x65cb,0x65cc,0x65cd,0x65ce,0x65cf, + 0x65d0,0x65d1,0x65d2,0x65d3,0x65d4,0x65d5,0x65d6,0x65d7, + 0x65d8,0x65d9,0x65da,0x65db,0x65dc,0x65dd,0x65de,0x65df, + 0x65e0,0x65e1,0x65e2,0x65e3,0x65e4,0x65e5,0x65e6,0x65e7, + 0x65e8,0x65e9,0x65ea,0x65eb,0x65ec,0x65ed,0x65ee,0x65ef, + 0x65f0,0x65f1,0x65f2,0x65f3,0x65f4,0x65f5,0x65f6,0x65f7, + 0x65f8,0x65f9,0x65fa,0x65fb,0x65fc,0x65fd,0x65fe,0x65ff, + 0x6600,0x6601,0x6602,0x6603,0x6604,0x6605,0x6606,0x6607, + 0x6608,0x6609,0x660a,0x660b,0x660c,0x660d,0x660e,0x660f, + 0x6610,0x6611,0x6612,0x6613,0x6614,0x6615,0x6616,0x6617, + 0x6618,0x6619,0x661a,0x661b,0x661c,0x661d,0x661e,0x661f, + 0x6620,0x6621,0x6622,0x6623,0x6624,0x6625,0x6626,0x6627, + 0x6628,0x6629,0x662a,0x662b,0x662c,0x662d,0x662e,0x662f, + 0x6630,0x6631,0x6632,0x6633,0x6634,0x6635,0x6636,0x6637, + 0x6638,0x6639,0x663a,0x663b,0x663c,0x663d,0x663e,0x663f, + 0x6640,0x6641,0x6642,0x6643,0x6644,0x6645,0x6646,0x6647, + 0x6648,0x6649,0x664a,0x664b,0x664c,0x664d,0x664e,0x664f, + 0x6650,0x6651,0x6652,0x6653,0x6654,0x6655,0x6656,0x6657, + 0x6658,0x6659,0x665a,0x665b,0x665c,0x665d,0x665e,0x665f, + 0x6660,0x6661,0x6662,0x6663,0x6664,0x6665,0x6666,0x6667, + 0x6668,0x6669,0x666a,0x666b,0x666c,0x666d,0x666e,0x666f, + 0x6670,0x6671,0x6672,0x6673,0x6674,0x6675,0x6676,0x6677, + 0x6678,0x6679,0x667a,0x667b,0x667c,0x667d,0x667e,0x667f, + 0x6680,0x6681,0x6682,0x6683,0x6684,0x6685,0x6686,0x6687, + 0x6688,0x6689,0x668a,0x668b,0x668c,0x668d,0x668e,0x668f, + 0x6690,0x6691,0x6692,0x6693,0x6694,0x6695,0x6696,0x6697, + 0x6698,0x6699,0x669a,0x669b,0x669c,0x669d,0x669e,0x669f, + 0x66a0,0x66a1,0x66a2,0x66a3,0x66a4,0x66a5,0x66a6,0x66a7, + 0x66a8,0x66a9,0x66aa,0x66ab,0x66ac,0x66ad,0x66ae,0x66af, + 0x66b0,0x66b1,0x66b2,0x66b3,0x66b4,0x66b5,0x66b6,0x66b7, + 0x66b8,0x66b9,0x66ba,0x66bb,0x66bc,0x66bd,0x66be,0x66bf, + 0x66c0,0x66c1,0x66c2,0x66c3,0x66c4,0x66c5,0x66c6,0x66c7, + 0x66c8,0x66c9,0x66ca,0x66cb,0x66cc,0x66cd,0x66ce,0x66cf, + 0x66d0,0x66d1,0x66d2,0x66d3,0x66d4,0x66d5,0x66d6,0x66d7, + 0x66d8,0x66d9,0x66da,0x66db,0x66dc,0x66dd,0x66de,0x66df, + 0x66e0,0x66e1,0x66e2,0x66e3,0x66e4,0x66e5,0x66e6,0x66e7, + 0x66e8,0x66e9,0x66ea,0x66eb,0x66ec,0x66ed,0x66ee,0x66ef, + 0x66f0,0x66f1,0x66f2,0x66f3,0x66f4,0x66f5,0x66f6,0x66f7, + 0x66f8,0x66f9,0x66fa,0x66fb,0x66fc,0x66fd,0x66fe,0x66ff, + 0x6700,0x6701,0x6702,0x6703,0x6704,0x6705,0x6706,0x6707, + 0x6708,0x6709,0x670a,0x670b,0x670c,0x670d,0x670e,0x670f, + 0x6710,0x6711,0x6712,0x6713,0x6714,0x6715,0x6716,0x6717, + 0x6718,0x6719,0x671a,0x671b,0x671c,0x671d,0x671e,0x671f, + 0x6720,0x6721,0x6722,0x6723,0x6724,0x6725,0x6726,0x6727, + 0x6728,0x6729,0x672a,0x672b,0x672c,0x672d,0x672e,0x672f, + 0x6730,0x6731,0x6732,0x6733,0x6734,0x6735,0x6736,0x6737, + 0x6738,0x6739,0x673a,0x673b,0x673c,0x673d,0x673e,0x673f, + 0x6740,0x6741,0x6742,0x6743,0x6744,0x6745,0x6746,0x6747, + 0x6748,0x6749,0x674a,0x674b,0x674c,0x674d,0x674e,0x674f, + 0x6750,0x6751,0x6752,0x6753,0x6754,0x6755,0x6756,0x6757, + 0x6758,0x6759,0x675a,0x675b,0x675c,0x675d,0x675e,0x675f, + 0x6760,0x6761,0x6762,0x6763,0x6764,0x6765,0x6766,0x6767, + 0x6768,0x6769,0x676a,0x676b,0x676c,0x676d,0x676e,0x676f, + 0x6770,0x6771,0x6772,0x6773,0x6774,0x6775,0x6776,0x6777, + 0x6778,0x6779,0x677a,0x677b,0x677c,0x677d,0x677e,0x677f, + 0x6780,0x6781,0x6782,0x6783,0x6784,0x6785,0x6786,0x6787, + 0x6788,0x6789,0x678a,0x678b,0x678c,0x678d,0x678e,0x678f, + 0x6790,0x6791,0x6792,0x6793,0x6794,0x6795,0x6796,0x6797, + 0x6798,0x6799,0x679a,0x679b,0x679c,0x679d,0x679e,0x679f, + 0x67a0,0x67a1,0x67a2,0x67a3,0x67a4,0x67a5,0x67a6,0x67a7, + 0x67a8,0x67a9,0x67aa,0x67ab,0x67ac,0x67ad,0x67ae,0x67af, + 0x67b0,0x67b1,0x67b2,0x67b3,0x67b4,0x67b5,0x67b6,0x67b7, + 0x67b8,0x67b9,0x67ba,0x67bb,0x67bc,0x67bd,0x67be,0x67bf, + 0x67c0,0x67c1,0x67c2,0x67c3,0x67c4,0x67c5,0x67c6,0x67c7, + 0x67c8,0x67c9,0x67ca,0x67cb,0x67cc,0x67cd,0x67ce,0x67cf, + 0x67d0,0x67d1,0x67d2,0x67d3,0x67d4,0x67d5,0x67d6,0x67d7, + 0x67d8,0x67d9,0x67da,0x67db,0x67dc,0x67dd,0x67de,0x67df, + 0x67e0,0x67e1,0x67e2,0x67e3,0x67e4,0x67e5,0x67e6,0x67e7, + 0x67e8,0x67e9,0x67ea,0x67eb,0x67ec,0x67ed,0x67ee,0x67ef, + 0x67f0,0x67f1,0x67f2,0x67f3,0x67f4,0x67f5,0x67f6,0x67f7, + 0x67f8,0x67f9,0x67fa,0x67fb,0x67fc,0x67fd,0x67fe,0x67ff, + 0x6800,0x6801,0x6802,0x6803,0x6804,0x6805,0x6806,0x6807, + 0x6808,0x6809,0x680a,0x680b,0x680c,0x680d,0x680e,0x680f, + 0x6810,0x6811,0x6812,0x6813,0x6814,0x6815,0x6816,0x6817, + 0x6818,0x6819,0x681a,0x681b,0x681c,0x681d,0x681e,0x681f, + 0x6820,0x6821,0x6822,0x6823,0x6824,0x6825,0x6826,0x6827, + 0x6828,0x6829,0x682a,0x682b,0x682c,0x682d,0x682e,0x682f, + 0x6830,0x6831,0x6832,0x6833,0x6834,0x6835,0x6836,0x6837, + 0x6838,0x6839,0x683a,0x683b,0x683c,0x683d,0x683e,0x683f, + 0x6840,0x6841,0x6842,0x6843,0x6844,0x6845,0x6846,0x6847, + 0x6848,0x6849,0x684a,0x684b,0x684c,0x684d,0x684e,0x684f, + 0x6850,0x6851,0x6852,0x6853,0x6854,0x6855,0x6856,0x6857, + 0x6858,0x6859,0x685a,0x685b,0x685c,0x685d,0x685e,0x685f, + 0x6860,0x6861,0x6862,0x6863,0x6864,0x6865,0x6866,0x6867, + 0x6868,0x6869,0x686a,0x686b,0x686c,0x686d,0x686e,0x686f, + 0x6870,0x6871,0x6872,0x6873,0x6874,0x6875,0x6876,0x6877, + 0x6878,0x6879,0x687a,0x687b,0x687c,0x687d,0x687e,0x687f, + 0x6880,0x6881,0x6882,0x6883,0x6884,0x6885,0x6886,0x6887, + 0x6888,0x6889,0x688a,0x688b,0x688c,0x688d,0x688e,0x688f, + 0x6890,0x6891,0x6892,0x6893,0x6894,0x6895,0x6896,0x6897, + 0x6898,0x6899,0x689a,0x689b,0x689c,0x689d,0x689e,0x689f, + 0x68a0,0x68a1,0x68a2,0x68a3,0x68a4,0x68a5,0x68a6,0x68a7, + 0x68a8,0x68a9,0x68aa,0x68ab,0x68ac,0x68ad,0x68ae,0x68af, + 0x68b0,0x68b1,0x68b2,0x68b3,0x68b4,0x68b5,0x68b6,0x68b7, + 0x68b8,0x68b9,0x68ba,0x68bb,0x68bc,0x68bd,0x68be,0x68bf, + 0x68c0,0x68c1,0x68c2,0x68c3,0x68c4,0x68c5,0x68c6,0x68c7, + 0x68c8,0x68c9,0x68ca,0x68cb,0x68cc,0x68cd,0x68ce,0x68cf, + 0x68d0,0x68d1,0x68d2,0x68d3,0x68d4,0x68d5,0x68d6,0x68d7, + 0x68d8,0x68d9,0x68da,0x68db,0x68dc,0x68dd,0x68de,0x68df, + 0x68e0,0x68e1,0x68e2,0x68e3,0x68e4,0x68e5,0x68e6,0x68e7, + 0x68e8,0x68e9,0x68ea,0x68eb,0x68ec,0x68ed,0x68ee,0x68ef, + 0x68f0,0x68f1,0x68f2,0x68f3,0x68f4,0x68f5,0x68f6,0x68f7, + 0x68f8,0x68f9,0x68fa,0x68fb,0x68fc,0x68fd,0x68fe,0x68ff, + 0x6900,0x6901,0x6902,0x6903,0x6904,0x6905,0x6906,0x6907, + 0x6908,0x6909,0x690a,0x690b,0x690c,0x690d,0x690e,0x690f, + 0x6910,0x6911,0x6912,0x6913,0x6914,0x6915,0x6916,0x6917, + 0x6918,0x6919,0x691a,0x691b,0x691c,0x691d,0x691e,0x691f, + 0x6920,0x6921,0x6922,0x6923,0x6924,0x6925,0x6926,0x6927, + 0x6928,0x6929,0x692a,0x692b,0x692c,0x692d,0x692e,0x692f, + 0x6930,0x6931,0x6932,0x6933,0x6934,0x6935,0x6936,0x6937, + 0x6938,0x6939,0x693a,0x693b,0x693c,0x693d,0x693e,0x693f, + 0x6940,0x6941,0x6942,0x6943,0x6944,0x6945,0x6946,0x6947, + 0x6948,0x6949,0x694a,0x694b,0x694c,0x694d,0x694e,0x694f, + 0x6950,0x6951,0x6952,0x6953,0x6954,0x6955,0x6956,0x6957, + 0x6958,0x6959,0x695a,0x695b,0x695c,0x695d,0x695e,0x695f, + 0x6960,0x6961,0x6962,0x6963,0x6964,0x6965,0x6966,0x6967, + 0x6968,0x6969,0x696a,0x696b,0x696c,0x696d,0x696e,0x696f, + 0x6970,0x6971,0x6972,0x6973,0x6974,0x6975,0x6976,0x6977, + 0x6978,0x6979,0x697a,0x697b,0x697c,0x697d,0x697e,0x697f, + 0x6980,0x6981,0x6982,0x6983,0x6984,0x6985,0x6986,0x6987, + 0x6988,0x6989,0x698a,0x698b,0x698c,0x698d,0x698e,0x698f, + 0x6990,0x6991,0x6992,0x6993,0x6994,0x6995,0x6996,0x6997, + 0x6998,0x6999,0x699a,0x699b,0x699c,0x699d,0x699e,0x699f, + 0x69a0,0x69a1,0x69a2,0x69a3,0x69a4,0x69a5,0x69a6,0x69a7, + 0x69a8,0x69a9,0x69aa,0x69ab,0x69ac,0x69ad,0x69ae,0x69af, + 0x69b0,0x69b1,0x69b2,0x69b3,0x69b4,0x69b5,0x69b6,0x69b7, + 0x69b8,0x69b9,0x69ba,0x69bb,0x69bc,0x69bd,0x69be,0x69bf, + 0x69c0,0x69c1,0x69c2,0x69c3,0x69c4,0x69c5,0x69c6,0x69c7, + 0x69c8,0x69c9,0x69ca,0x69cb,0x69cc,0x69cd,0x69ce,0x69cf, + 0x69d0,0x69d1,0x69d2,0x69d3,0x69d4,0x69d5,0x69d6,0x69d7, + 0x69d8,0x69d9,0x69da,0x69db,0x69dc,0x69dd,0x69de,0x69df, + 0x69e0,0x69e1,0x69e2,0x69e3,0x69e4,0x69e5,0x69e6,0x69e7, + 0x69e8,0x69e9,0x69ea,0x69eb,0x69ec,0x69ed,0x69ee,0x69ef, + 0x69f0,0x69f1,0x69f2,0x69f3,0x69f4,0x69f5,0x69f6,0x69f7, + 0x69f8,0x69f9,0x69fa,0x69fb,0x69fc,0x69fd,0x69fe,0x69ff, + 0x6a00,0x6a01,0x6a02,0x6a03,0x6a04,0x6a05,0x6a06,0x6a07, + 0x6a08,0x6a09,0x6a0a,0x6a0b,0x6a0c,0x6a0d,0x6a0e,0x6a0f, + 0x6a10,0x6a11,0x6a12,0x6a13,0x6a14,0x6a15,0x6a16,0x6a17, + 0x6a18,0x6a19,0x6a1a,0x6a1b,0x6a1c,0x6a1d,0x6a1e,0x6a1f, + 0x6a20,0x6a21,0x6a22,0x6a23,0x6a24,0x6a25,0x6a26,0x6a27, + 0x6a28,0x6a29,0x6a2a,0x6a2b,0x6a2c,0x6a2d,0x6a2e,0x6a2f, + 0x6a30,0x6a31,0x6a32,0x6a33,0x6a34,0x6a35,0x6a36,0x6a37, + 0x6a38,0x6a39,0x6a3a,0x6a3b,0x6a3c,0x6a3d,0x6a3e,0x6a3f, + 0x6a40,0x6a41,0x6a42,0x6a43,0x6a44,0x6a45,0x6a46,0x6a47, + 0x6a48,0x6a49,0x6a4a,0x6a4b,0x6a4c,0x6a4d,0x6a4e,0x6a4f, + 0x6a50,0x6a51,0x6a52,0x6a53,0x6a54,0x6a55,0x6a56,0x6a57, + 0x6a58,0x6a59,0x6a5a,0x6a5b,0x6a5c,0x6a5d,0x6a5e,0x6a5f, + 0x6a60,0x6a61,0x6a62,0x6a63,0x6a64,0x6a65,0x6a66,0x6a67, + 0x6a68,0x6a69,0x6a6a,0x6a6b,0x6a6c,0x6a6d,0x6a6e,0x6a6f, + 0x6a70,0x6a71,0x6a72,0x6a73,0x6a74,0x6a75,0x6a76,0x6a77, + 0x6a78,0x6a79,0x6a7a,0x6a7b,0x6a7c,0x6a7d,0x6a7e,0x6a7f, + 0x6a80,0x6a81,0x6a82,0x6a83,0x6a84,0x6a85,0x6a86,0x6a87, + 0x6a88,0x6a89,0x6a8a,0x6a8b,0x6a8c,0x6a8d,0x6a8e,0x6a8f, + 0x6a90,0x6a91,0x6a92,0x6a93,0x6a94,0x6a95,0x6a96,0x6a97, + 0x6a98,0x6a99,0x6a9a,0x6a9b,0x6a9c,0x6a9d,0x6a9e,0x6a9f, + 0x6aa0,0x6aa1,0x6aa2,0x6aa3,0x6aa4,0x6aa5,0x6aa6,0x6aa7, + 0x6aa8,0x6aa9,0x6aaa,0x6aab,0x6aac,0x6aad,0x6aae,0x6aaf, + 0x6ab0,0x6ab1,0x6ab2,0x6ab3,0x6ab4,0x6ab5,0x6ab6,0x6ab7, + 0x6ab8,0x6ab9,0x6aba,0x6abb,0x6abc,0x6abd,0x6abe,0x6abf, + 0x6ac0,0x6ac1,0x6ac2,0x6ac3,0x6ac4,0x6ac5,0x6ac6,0x6ac7, + 0x6ac8,0x6ac9,0x6aca,0x6acb,0x6acc,0x6acd,0x6ace,0x6acf, + 0x6ad0,0x6ad1,0x6ad2,0x6ad3,0x6ad4,0x6ad5,0x6ad6,0x6ad7, + 0x6ad8,0x6ad9,0x6ada,0x6adb,0x6adc,0x6add,0x6ade,0x6adf, + 0x6ae0,0x6ae1,0x6ae2,0x6ae3,0x6ae4,0x6ae5,0x6ae6,0x6ae7, + 0x6ae8,0x6ae9,0x6aea,0x6aeb,0x6aec,0x6aed,0x6aee,0x6aef, + 0x6af0,0x6af1,0x6af2,0x6af3,0x6af4,0x6af5,0x6af6,0x6af7, + 0x6af8,0x6af9,0x6afa,0x6afb,0x6afc,0x6afd,0x6afe,0x6aff, + 0x6b00,0x6b01,0x6b02,0x6b03,0x6b04,0x6b05,0x6b06,0x6b07, + 0x6b08,0x6b09,0x6b0a,0x6b0b,0x6b0c,0x6b0d,0x6b0e,0x6b0f, + 0x6b10,0x6b11,0x6b12,0x6b13,0x6b14,0x6b15,0x6b16,0x6b17, + 0x6b18,0x6b19,0x6b1a,0x6b1b,0x6b1c,0x6b1d,0x6b1e,0x6b1f, + 0x6b20,0x6b21,0x6b22,0x6b23,0x6b24,0x6b25,0x6b26,0x6b27, + 0x6b28,0x6b29,0x6b2a,0x6b2b,0x6b2c,0x6b2d,0x6b2e,0x6b2f, + 0x6b30,0x6b31,0x6b32,0x6b33,0x6b34,0x6b35,0x6b36,0x6b37, + 0x6b38,0x6b39,0x6b3a,0x6b3b,0x6b3c,0x6b3d,0x6b3e,0x6b3f, + 0x6b40,0x6b41,0x6b42,0x6b43,0x6b44,0x6b45,0x6b46,0x6b47, + 0x6b48,0x6b49,0x6b4a,0x6b4b,0x6b4c,0x6b4d,0x6b4e,0x6b4f, + 0x6b50,0x6b51,0x6b52,0x6b53,0x6b54,0x6b55,0x6b56,0x6b57, + 0x6b58,0x6b59,0x6b5a,0x6b5b,0x6b5c,0x6b5d,0x6b5e,0x6b5f, + 0x6b60,0x6b61,0x6b62,0x6b63,0x6b64,0x6b65,0x6b66,0x6b67, + 0x6b68,0x6b69,0x6b6a,0x6b6b,0x6b6c,0x6b6d,0x6b6e,0x6b6f, + 0x6b70,0x6b71,0x6b72,0x6b73,0x6b74,0x6b75,0x6b76,0x6b77, + 0x6b78,0x6b79,0x6b7a,0x6b7b,0x6b7c,0x6b7d,0x6b7e,0x6b7f, + 0x6b80,0x6b81,0x6b82,0x6b83,0x6b84,0x6b85,0x6b86,0x6b87, + 0x6b88,0x6b89,0x6b8a,0x6b8b,0x6b8c,0x6b8d,0x6b8e,0x6b8f, + 0x6b90,0x6b91,0x6b92,0x6b93,0x6b94,0x6b95,0x6b96,0x6b97, + 0x6b98,0x6b99,0x6b9a,0x6b9b,0x6b9c,0x6b9d,0x6b9e,0x6b9f, + 0x6ba0,0x6ba1,0x6ba2,0x6ba3,0x6ba4,0x6ba5,0x6ba6,0x6ba7, + 0x6ba8,0x6ba9,0x6baa,0x6bab,0x6bac,0x6bad,0x6bae,0x6baf, + 0x6bb0,0x6bb1,0x6bb2,0x6bb3,0x6bb4,0x6bb5,0x6bb6,0x6bb7, + 0x6bb8,0x6bb9,0x6bba,0x6bbb,0x6bbc,0x6bbd,0x6bbe,0x6bbf, + 0x6bc0,0x6bc1,0x6bc2,0x6bc3,0x6bc4,0x6bc5,0x6bc6,0x6bc7, + 0x6bc8,0x6bc9,0x6bca,0x6bcb,0x6bcc,0x6bcd,0x6bce,0x6bcf, + 0x6bd0,0x6bd1,0x6bd2,0x6bd3,0x6bd4,0x6bd5,0x6bd6,0x6bd7, + 0x6bd8,0x6bd9,0x6bda,0x6bdb,0x6bdc,0x6bdd,0x6bde,0x6bdf, + 0x6be0,0x6be1,0x6be2,0x6be3,0x6be4,0x6be5,0x6be6,0x6be7, + 0x6be8,0x6be9,0x6bea,0x6beb,0x6bec,0x6bed,0x6bee,0x6bef, + 0x6bf0,0x6bf1,0x6bf2,0x6bf3,0x6bf4,0x6bf5,0x6bf6,0x6bf7, + 0x6bf8,0x6bf9,0x6bfa,0x6bfb,0x6bfc,0x6bfd,0x6bfe,0x6bff, + 0x6c00,0x6c01,0x6c02,0x6c03,0x6c04,0x6c05,0x6c06,0x6c07, + 0x6c08,0x6c09,0x6c0a,0x6c0b,0x6c0c,0x6c0d,0x6c0e,0x6c0f, + 0x6c10,0x6c11,0x6c12,0x6c13,0x6c14,0x6c15,0x6c16,0x6c17, + 0x6c18,0x6c19,0x6c1a,0x6c1b,0x6c1c,0x6c1d,0x6c1e,0x6c1f, + 0x6c20,0x6c21,0x6c22,0x6c23,0x6c24,0x6c25,0x6c26,0x6c27, + 0x6c28,0x6c29,0x6c2a,0x6c2b,0x6c2c,0x6c2d,0x6c2e,0x6c2f, + 0x6c30,0x6c31,0x6c32,0x6c33,0x6c34,0x6c35,0x6c36,0x6c37, + 0x6c38,0x6c39,0x6c3a,0x6c3b,0x6c3c,0x6c3d,0x6c3e,0x6c3f, + 0x6c40,0x6c41,0x6c42,0x6c43,0x6c44,0x6c45,0x6c46,0x6c47, + 0x6c48,0x6c49,0x6c4a,0x6c4b,0x6c4c,0x6c4d,0x6c4e,0x6c4f, + 0x6c50,0x6c51,0x6c52,0x6c53,0x6c54,0x6c55,0x6c56,0x6c57, + 0x6c58,0x6c59,0x6c5a,0x6c5b,0x6c5c,0x6c5d,0x6c5e,0x6c5f, + 0x6c60,0x6c61,0x6c62,0x6c63,0x6c64,0x6c65,0x6c66,0x6c67, + 0x6c68,0x6c69,0x6c6a,0x6c6b,0x6c6c,0x6c6d,0x6c6e,0x6c6f, + 0x6c70,0x6c71,0x6c72,0x6c73,0x6c74,0x6c75,0x6c76,0x6c77, + 0x6c78,0x6c79,0x6c7a,0x6c7b,0x6c7c,0x6c7d,0x6c7e,0x6c7f, + 0x6c80,0x6c81,0x6c82,0x6c83,0x6c84,0x6c85,0x6c86,0x6c87, + 0x6c88,0x6c89,0x6c8a,0x6c8b,0x6c8c,0x6c8d,0x6c8e,0x6c8f, + 0x6c90,0x6c91,0x6c92,0x6c93,0x6c94,0x6c95,0x6c96,0x6c97, + 0x6c98,0x6c99,0x6c9a,0x6c9b,0x6c9c,0x6c9d,0x6c9e,0x6c9f, + 0x6ca0,0x6ca1,0x6ca2,0x6ca3,0x6ca4,0x6ca5,0x6ca6,0x6ca7, + 0x6ca8,0x6ca9,0x6caa,0x6cab,0x6cac,0x6cad,0x6cae,0x6caf, + 0x6cb0,0x6cb1,0x6cb2,0x6cb3,0x6cb4,0x6cb5,0x6cb6,0x6cb7, + 0x6cb8,0x6cb9,0x6cba,0x6cbb,0x6cbc,0x6cbd,0x6cbe,0x6cbf, + 0x6cc0,0x6cc1,0x6cc2,0x6cc3,0x6cc4,0x6cc5,0x6cc6,0x6cc7, + 0x6cc8,0x6cc9,0x6cca,0x6ccb,0x6ccc,0x6ccd,0x6cce,0x6ccf, + 0x6cd0,0x6cd1,0x6cd2,0x6cd3,0x6cd4,0x6cd5,0x6cd6,0x6cd7, + 0x6cd8,0x6cd9,0x6cda,0x6cdb,0x6cdc,0x6cdd,0x6cde,0x6cdf, + 0x6ce0,0x6ce1,0x6ce2,0x6ce3,0x6ce4,0x6ce5,0x6ce6,0x6ce7, + 0x6ce8,0x6ce9,0x6cea,0x6ceb,0x6cec,0x6ced,0x6cee,0x6cef, + 0x6cf0,0x6cf1,0x6cf2,0x6cf3,0x6cf4,0x6cf5,0x6cf6,0x6cf7, + 0x6cf8,0x6cf9,0x6cfa,0x6cfb,0x6cfc,0x6cfd,0x6cfe,0x6cff, + 0x6d00,0x6d01,0x6d02,0x6d03,0x6d04,0x6d05,0x6d06,0x6d07, + 0x6d08,0x6d09,0x6d0a,0x6d0b,0x6d0c,0x6d0d,0x6d0e,0x6d0f, + 0x6d10,0x6d11,0x6d12,0x6d13,0x6d14,0x6d15,0x6d16,0x6d17, + 0x6d18,0x6d19,0x6d1a,0x6d1b,0x6d1c,0x6d1d,0x6d1e,0x6d1f, + 0x6d20,0x6d21,0x6d22,0x6d23,0x6d24,0x6d25,0x6d26,0x6d27, + 0x6d28,0x6d29,0x6d2a,0x6d2b,0x6d2c,0x6d2d,0x6d2e,0x6d2f, + 0x6d30,0x6d31,0x6d32,0x6d33,0x6d34,0x6d35,0x6d36,0x6d37, + 0x6d38,0x6d39,0x6d3a,0x6d3b,0x6d3c,0x6d3d,0x6d3e,0x6d3f, + 0x6d40,0x6d41,0x6d42,0x6d43,0x6d44,0x6d45,0x6d46,0x6d47, + 0x6d48,0x6d49,0x6d4a,0x6d4b,0x6d4c,0x6d4d,0x6d4e,0x6d4f, + 0x6d50,0x6d51,0x6d52,0x6d53,0x6d54,0x6d55,0x6d56,0x6d57, + 0x6d58,0x6d59,0x6d5a,0x6d5b,0x6d5c,0x6d5d,0x6d5e,0x6d5f, + 0x6d60,0x6d61,0x6d62,0x6d63,0x6d64,0x6d65,0x6d66,0x6d67, + 0x6d68,0x6d69,0x6d6a,0x6d6b,0x6d6c,0x6d6d,0x6d6e,0x6d6f, + 0x6d70,0x6d71,0x6d72,0x6d73,0x6d74,0x6d75,0x6d76,0x6d77, + 0x6d78,0x6d79,0x6d7a,0x6d7b,0x6d7c,0x6d7d,0x6d7e,0x6d7f, + 0x6d80,0x6d81,0x6d82,0x6d83,0x6d84,0x6d85,0x6d86,0x6d87, + 0x6d88,0x6d89,0x6d8a,0x6d8b,0x6d8c,0x6d8d,0x6d8e,0x6d8f, + 0x6d90,0x6d91,0x6d92,0x6d93,0x6d94,0x6d95,0x6d96,0x6d97, + 0x6d98,0x6d99,0x6d9a,0x6d9b,0x6d9c,0x6d9d,0x6d9e,0x6d9f, + 0x6da0,0x6da1,0x6da2,0x6da3,0x6da4,0x6da5,0x6da6,0x6da7, + 0x6da8,0x6da9,0x6daa,0x6dab,0x6dac,0x6dad,0x6dae,0x6daf, + 0x6db0,0x6db1,0x6db2,0x6db3,0x6db4,0x6db5,0x6db6,0x6db7, + 0x6db8,0x6db9,0x6dba,0x6dbb,0x6dbc,0x6dbd,0x6dbe,0x6dbf, + 0x6dc0,0x6dc1,0x6dc2,0x6dc3,0x6dc4,0x6dc5,0x6dc6,0x6dc7, + 0x6dc8,0x6dc9,0x6dca,0x6dcb,0x6dcc,0x6dcd,0x6dce,0x6dcf, + 0x6dd0,0x6dd1,0x6dd2,0x6dd3,0x6dd4,0x6dd5,0x6dd6,0x6dd7, + 0x6dd8,0x6dd9,0x6dda,0x6ddb,0x6ddc,0x6ddd,0x6dde,0x6ddf, + 0x6de0,0x6de1,0x6de2,0x6de3,0x6de4,0x6de5,0x6de6,0x6de7, + 0x6de8,0x6de9,0x6dea,0x6deb,0x6dec,0x6ded,0x6dee,0x6def, + 0x6df0,0x6df1,0x6df2,0x6df3,0x6df4,0x6df5,0x6df6,0x6df7, + 0x6df8,0x6df9,0x6dfa,0x6dfb,0x6dfc,0x6dfd,0x6dfe,0x6dff, + 0x6e00,0x6e01,0x6e02,0x6e03,0x6e04,0x6e05,0x6e06,0x6e07, + 0x6e08,0x6e09,0x6e0a,0x6e0b,0x6e0c,0x6e0d,0x6e0e,0x6e0f, + 0x6e10,0x6e11,0x6e12,0x6e13,0x6e14,0x6e15,0x6e16,0x6e17, + 0x6e18,0x6e19,0x6e1a,0x6e1b,0x6e1c,0x6e1d,0x6e1e,0x6e1f, + 0x6e20,0x6e21,0x6e22,0x6e23,0x6e24,0x6e25,0x6e26,0x6e27, + 0x6e28,0x6e29,0x6e2a,0x6e2b,0x6e2c,0x6e2d,0x6e2e,0x6e2f, + 0x6e30,0x6e31,0x6e32,0x6e33,0x6e34,0x6e35,0x6e36,0x6e37, + 0x6e38,0x6e39,0x6e3a,0x6e3b,0x6e3c,0x6e3d,0x6e3e,0x6e3f, + 0x6e40,0x6e41,0x6e42,0x6e43,0x6e44,0x6e45,0x6e46,0x6e47, + 0x6e48,0x6e49,0x6e4a,0x6e4b,0x6e4c,0x6e4d,0x6e4e,0x6e4f, + 0x6e50,0x6e51,0x6e52,0x6e53,0x6e54,0x6e55,0x6e56,0x6e57, + 0x6e58,0x6e59,0x6e5a,0x6e5b,0x6e5c,0x6e5d,0x6e5e,0x6e5f, + 0x6e60,0x6e61,0x6e62,0x6e63,0x6e64,0x6e65,0x6e66,0x6e67, + 0x6e68,0x6e69,0x6e6a,0x6e6b,0x6e6c,0x6e6d,0x6e6e,0x6e6f, + 0x6e70,0x6e71,0x6e72,0x6e73,0x6e74,0x6e75,0x6e76,0x6e77, + 0x6e78,0x6e79,0x6e7a,0x6e7b,0x6e7c,0x6e7d,0x6e7e,0x6e7f, + 0x6e80,0x6e81,0x6e82,0x6e83,0x6e84,0x6e85,0x6e86,0x6e87, + 0x6e88,0x6e89,0x6e8a,0x6e8b,0x6e8c,0x6e8d,0x6e8e,0x6e8f, + 0x6e90,0x6e91,0x6e92,0x6e93,0x6e94,0x6e95,0x6e96,0x6e97, + 0x6e98,0x6e99,0x6e9a,0x6e9b,0x6e9c,0x6e9d,0x6e9e,0x6e9f, + 0x6ea0,0x6ea1,0x6ea2,0x6ea3,0x6ea4,0x6ea5,0x6ea6,0x6ea7, + 0x6ea8,0x6ea9,0x6eaa,0x6eab,0x6eac,0x6ead,0x6eae,0x6eaf, + 0x6eb0,0x6eb1,0x6eb2,0x6eb3,0x6eb4,0x6eb5,0x6eb6,0x6eb7, + 0x6eb8,0x6eb9,0x6eba,0x6ebb,0x6ebc,0x6ebd,0x6ebe,0x6ebf, + 0x6ec0,0x6ec1,0x6ec2,0x6ec3,0x6ec4,0x6ec5,0x6ec6,0x6ec7, + 0x6ec8,0x6ec9,0x6eca,0x6ecb,0x6ecc,0x6ecd,0x6ece,0x6ecf, + 0x6ed0,0x6ed1,0x6ed2,0x6ed3,0x6ed4,0x6ed5,0x6ed6,0x6ed7, + 0x6ed8,0x6ed9,0x6eda,0x6edb,0x6edc,0x6edd,0x6ede,0x6edf, + 0x6ee0,0x6ee1,0x6ee2,0x6ee3,0x6ee4,0x6ee5,0x6ee6,0x6ee7, + 0x6ee8,0x6ee9,0x6eea,0x6eeb,0x6eec,0x6eed,0x6eee,0x6eef, + 0x6ef0,0x6ef1,0x6ef2,0x6ef3,0x6ef4,0x6ef5,0x6ef6,0x6ef7, + 0x6ef8,0x6ef9,0x6efa,0x6efb,0x6efc,0x6efd,0x6efe,0x6eff, + 0x6f00,0x6f01,0x6f02,0x6f03,0x6f04,0x6f05,0x6f06,0x6f07, + 0x6f08,0x6f09,0x6f0a,0x6f0b,0x6f0c,0x6f0d,0x6f0e,0x6f0f, + 0x6f10,0x6f11,0x6f12,0x6f13,0x6f14,0x6f15,0x6f16,0x6f17, + 0x6f18,0x6f19,0x6f1a,0x6f1b,0x6f1c,0x6f1d,0x6f1e,0x6f1f, + 0x6f20,0x6f21,0x6f22,0x6f23,0x6f24,0x6f25,0x6f26,0x6f27, + 0x6f28,0x6f29,0x6f2a,0x6f2b,0x6f2c,0x6f2d,0x6f2e,0x6f2f, + 0x6f30,0x6f31,0x6f32,0x6f33,0x6f34,0x6f35,0x6f36,0x6f37, + 0x6f38,0x6f39,0x6f3a,0x6f3b,0x6f3c,0x6f3d,0x6f3e,0x6f3f, + 0x6f40,0x6f41,0x6f42,0x6f43,0x6f44,0x6f45,0x6f46,0x6f47, + 0x6f48,0x6f49,0x6f4a,0x6f4b,0x6f4c,0x6f4d,0x6f4e,0x6f4f, + 0x6f50,0x6f51,0x6f52,0x6f53,0x6f54,0x6f55,0x6f56,0x6f57, + 0x6f58,0x6f59,0x6f5a,0x6f5b,0x6f5c,0x6f5d,0x6f5e,0x6f5f, + 0x6f60,0x6f61,0x6f62,0x6f63,0x6f64,0x6f65,0x6f66,0x6f67, + 0x6f68,0x6f69,0x6f6a,0x6f6b,0x6f6c,0x6f6d,0x6f6e,0x6f6f, + 0x6f70,0x6f71,0x6f72,0x6f73,0x6f74,0x6f75,0x6f76,0x6f77, + 0x6f78,0x6f79,0x6f7a,0x6f7b,0x6f7c,0x6f7d,0x6f7e,0x6f7f, + 0x6f80,0x6f81,0x6f82,0x6f83,0x6f84,0x6f85,0x6f86,0x6f87, + 0x6f88,0x6f89,0x6f8a,0x6f8b,0x6f8c,0x6f8d,0x6f8e,0x6f8f, + 0x6f90,0x6f91,0x6f92,0x6f93,0x6f94,0x6f95,0x6f96,0x6f97, + 0x6f98,0x6f99,0x6f9a,0x6f9b,0x6f9c,0x6f9d,0x6f9e,0x6f9f, + 0x6fa0,0x6fa1,0x6fa2,0x6fa3,0x6fa4,0x6fa5,0x6fa6,0x6fa7, + 0x6fa8,0x6fa9,0x6faa,0x6fab,0x6fac,0x6fad,0x6fae,0x6faf, + 0x6fb0,0x6fb1,0x6fb2,0x6fb3,0x6fb4,0x6fb5,0x6fb6,0x6fb7, + 0x6fb8,0x6fb9,0x6fba,0x6fbb,0x6fbc,0x6fbd,0x6fbe,0x6fbf, + 0x6fc0,0x6fc1,0x6fc2,0x6fc3,0x6fc4,0x6fc5,0x6fc6,0x6fc7, + 0x6fc8,0x6fc9,0x6fca,0x6fcb,0x6fcc,0x6fcd,0x6fce,0x6fcf, + 0x6fd0,0x6fd1,0x6fd2,0x6fd3,0x6fd4,0x6fd5,0x6fd6,0x6fd7, + 0x6fd8,0x6fd9,0x6fda,0x6fdb,0x6fdc,0x6fdd,0x6fde,0x6fdf, + 0x6fe0,0x6fe1,0x6fe2,0x6fe3,0x6fe4,0x6fe5,0x6fe6,0x6fe7, + 0x6fe8,0x6fe9,0x6fea,0x6feb,0x6fec,0x6fed,0x6fee,0x6fef, + 0x6ff0,0x6ff1,0x6ff2,0x6ff3,0x6ff4,0x6ff5,0x6ff6,0x6ff7, + 0x6ff8,0x6ff9,0x6ffa,0x6ffb,0x6ffc,0x6ffd,0x6ffe,0x6fff, + 0x7000,0x7001,0x7002,0x7003,0x7004,0x7005,0x7006,0x7007, + 0x7008,0x7009,0x700a,0x700b,0x700c,0x700d,0x700e,0x700f, + 0x7010,0x7011,0x7012,0x7013,0x7014,0x7015,0x7016,0x7017, + 0x7018,0x7019,0x701a,0x701b,0x701c,0x701d,0x701e,0x701f, + 0x7020,0x7021,0x7022,0x7023,0x7024,0x7025,0x7026,0x7027, + 0x7028,0x7029,0x702a,0x702b,0x702c,0x702d,0x702e,0x702f, + 0x7030,0x7031,0x7032,0x7033,0x7034,0x7035,0x7036,0x7037, + 0x7038,0x7039,0x703a,0x703b,0x703c,0x703d,0x703e,0x703f, + 0x7040,0x7041,0x7042,0x7043,0x7044,0x7045,0x7046,0x7047, + 0x7048,0x7049,0x704a,0x704b,0x704c,0x704d,0x704e,0x704f, + 0x7050,0x7051,0x7052,0x7053,0x7054,0x7055,0x7056,0x7057, + 0x7058,0x7059,0x705a,0x705b,0x705c,0x705d,0x705e,0x705f, + 0x7060,0x7061,0x7062,0x7063,0x7064,0x7065,0x7066,0x7067, + 0x7068,0x7069,0x706a,0x706b,0x706c,0x706d,0x706e,0x706f, + 0x7070,0x7071,0x7072,0x7073,0x7074,0x7075,0x7076,0x7077, + 0x7078,0x7079,0x707a,0x707b,0x707c,0x707d,0x707e,0x707f, + 0x7080,0x7081,0x7082,0x7083,0x7084,0x7085,0x7086,0x7087, + 0x7088,0x7089,0x708a,0x708b,0x708c,0x708d,0x708e,0x708f, + 0x7090,0x7091,0x7092,0x7093,0x7094,0x7095,0x7096,0x7097, + 0x7098,0x7099,0x709a,0x709b,0x709c,0x709d,0x709e,0x709f, + 0x70a0,0x70a1,0x70a2,0x70a3,0x70a4,0x70a5,0x70a6,0x70a7, + 0x70a8,0x70a9,0x70aa,0x70ab,0x70ac,0x70ad,0x70ae,0x70af, + 0x70b0,0x70b1,0x70b2,0x70b3,0x70b4,0x70b5,0x70b6,0x70b7, + 0x70b8,0x70b9,0x70ba,0x70bb,0x70bc,0x70bd,0x70be,0x70bf, + 0x70c0,0x70c1,0x70c2,0x70c3,0x70c4,0x70c5,0x70c6,0x70c7, + 0x70c8,0x70c9,0x70ca,0x70cb,0x70cc,0x70cd,0x70ce,0x70cf, + 0x70d0,0x70d1,0x70d2,0x70d3,0x70d4,0x70d5,0x70d6,0x70d7, + 0x70d8,0x70d9,0x70da,0x70db,0x70dc,0x70dd,0x70de,0x70df, + 0x70e0,0x70e1,0x70e2,0x70e3,0x70e4,0x70e5,0x70e6,0x70e7, + 0x70e8,0x70e9,0x70ea,0x70eb,0x70ec,0x70ed,0x70ee,0x70ef, + 0x70f0,0x70f1,0x70f2,0x70f3,0x70f4,0x70f5,0x70f6,0x70f7, + 0x70f8,0x70f9,0x70fa,0x70fb,0x70fc,0x70fd,0x70fe,0x70ff, + 0x7100,0x7101,0x7102,0x7103,0x7104,0x7105,0x7106,0x7107, + 0x7108,0x7109,0x710a,0x710b,0x710c,0x710d,0x710e,0x710f, + 0x7110,0x7111,0x7112,0x7113,0x7114,0x7115,0x7116,0x7117, + 0x7118,0x7119,0x711a,0x711b,0x711c,0x711d,0x711e,0x711f, + 0x7120,0x7121,0x7122,0x7123,0x7124,0x7125,0x7126,0x7127, + 0x7128,0x7129,0x712a,0x712b,0x712c,0x712d,0x712e,0x712f, + 0x7130,0x7131,0x7132,0x7133,0x7134,0x7135,0x7136,0x7137, + 0x7138,0x7139,0x713a,0x713b,0x713c,0x713d,0x713e,0x713f, + 0x7140,0x7141,0x7142,0x7143,0x7144,0x7145,0x7146,0x7147, + 0x7148,0x7149,0x714a,0x714b,0x714c,0x714d,0x714e,0x714f, + 0x7150,0x7151,0x7152,0x7153,0x7154,0x7155,0x7156,0x7157, + 0x7158,0x7159,0x715a,0x715b,0x715c,0x715d,0x715e,0x715f, + 0x7160,0x7161,0x7162,0x7163,0x7164,0x7165,0x7166,0x7167, + 0x7168,0x7169,0x716a,0x716b,0x716c,0x716d,0x716e,0x716f, + 0x7170,0x7171,0x7172,0x7173,0x7174,0x7175,0x7176,0x7177, + 0x7178,0x7179,0x717a,0x717b,0x717c,0x717d,0x717e,0x717f, + 0x7180,0x7181,0x7182,0x7183,0x7184,0x7185,0x7186,0x7187, + 0x7188,0x7189,0x718a,0x718b,0x718c,0x718d,0x718e,0x718f, + 0x7190,0x7191,0x7192,0x7193,0x7194,0x7195,0x7196,0x7197, + 0x7198,0x7199,0x719a,0x719b,0x719c,0x719d,0x719e,0x719f, + 0x71a0,0x71a1,0x71a2,0x71a3,0x71a4,0x71a5,0x71a6,0x71a7, + 0x71a8,0x71a9,0x71aa,0x71ab,0x71ac,0x71ad,0x71ae,0x71af, + 0x71b0,0x71b1,0x71b2,0x71b3,0x71b4,0x71b5,0x71b6,0x71b7, + 0x71b8,0x71b9,0x71ba,0x71bb,0x71bc,0x71bd,0x71be,0x71bf, + 0x71c0,0x71c1,0x71c2,0x71c3,0x71c4,0x71c5,0x71c6,0x71c7, + 0x71c8,0x71c9,0x71ca,0x71cb,0x71cc,0x71cd,0x71ce,0x71cf, + 0x71d0,0x71d1,0x71d2,0x71d3,0x71d4,0x71d5,0x71d6,0x71d7, + 0x71d8,0x71d9,0x71da,0x71db,0x71dc,0x71dd,0x71de,0x71df, + 0x71e0,0x71e1,0x71e2,0x71e3,0x71e4,0x71e5,0x71e6,0x71e7, + 0x71e8,0x71e9,0x71ea,0x71eb,0x71ec,0x71ed,0x71ee,0x71ef, + 0x71f0,0x71f1,0x71f2,0x71f3,0x71f4,0x71f5,0x71f6,0x71f7, + 0x71f8,0x71f9,0x71fa,0x71fb,0x71fc,0x71fd,0x71fe,0x71ff, + 0x7200,0x7201,0x7202,0x7203,0x7204,0x7205,0x7206,0x7207, + 0x7208,0x7209,0x720a,0x720b,0x720c,0x720d,0x720e,0x720f, + 0x7210,0x7211,0x7212,0x7213,0x7214,0x7215,0x7216,0x7217, + 0x7218,0x7219,0x721a,0x721b,0x721c,0x721d,0x721e,0x721f, + 0x7220,0x7221,0x7222,0x7223,0x7224,0x7225,0x7226,0x7227, + 0x7228,0x7229,0x722a,0x722b,0x722c,0x722d,0x722e,0x722f, + 0x7230,0x7231,0x7232,0x7233,0x7234,0x7235,0x7236,0x7237, + 0x7238,0x7239,0x723a,0x723b,0x723c,0x723d,0x723e,0x723f, + 0x7240,0x7241,0x7242,0x7243,0x7244,0x7245,0x7246,0x7247, + 0x7248,0x7249,0x724a,0x724b,0x724c,0x724d,0x724e,0x724f, + 0x7250,0x7251,0x7252,0x7253,0x7254,0x7255,0x7256,0x7257, + 0x7258,0x7259,0x725a,0x725b,0x725c,0x725d,0x725e,0x725f, + 0x7260,0x7261,0x7262,0x7263,0x7264,0x7265,0x7266,0x7267, + 0x7268,0x7269,0x726a,0x726b,0x726c,0x726d,0x726e,0x726f, + 0x7270,0x7271,0x7272,0x7273,0x7274,0x7275,0x7276,0x7277, + 0x7278,0x7279,0x727a,0x727b,0x727c,0x727d,0x727e,0x727f, + 0x7280,0x7281,0x7282,0x7283,0x7284,0x7285,0x7286,0x7287, + 0x7288,0x7289,0x728a,0x728b,0x728c,0x728d,0x728e,0x728f, + 0x7290,0x7291,0x7292,0x7293,0x7294,0x7295,0x7296,0x7297, + 0x7298,0x7299,0x729a,0x729b,0x729c,0x729d,0x729e,0x729f, + 0x72a0,0x72a1,0x72a2,0x72a3,0x72a4,0x72a5,0x72a6,0x72a7, + 0x72a8,0x72a9,0x72aa,0x72ab,0x72ac,0x72ad,0x72ae,0x72af, + 0x72b0,0x72b1,0x72b2,0x72b3,0x72b4,0x72b5,0x72b6,0x72b7, + 0x72b8,0x72b9,0x72ba,0x72bb,0x72bc,0x72bd,0x72be,0x72bf, + 0x72c0,0x72c1,0x72c2,0x72c3,0x72c4,0x72c5,0x72c6,0x72c7, + 0x72c8,0x72c9,0x72ca,0x72cb,0x72cc,0x72cd,0x72ce,0x72cf, + 0x72d0,0x72d1,0x72d2,0x72d3,0x72d4,0x72d5,0x72d6,0x72d7, + 0x72d8,0x72d9,0x72da,0x72db,0x72dc,0x72dd,0x72de,0x72df, + 0x72e0,0x72e1,0x72e2,0x72e3,0x72e4,0x72e5,0x72e6,0x72e7, + 0x72e8,0x72e9,0x72ea,0x72eb,0x72ec,0x72ed,0x72ee,0x72ef, + 0x72f0,0x72f1,0x72f2,0x72f3,0x72f4,0x72f5,0x72f6,0x72f7, + 0x72f8,0x72f9,0x72fa,0x72fb,0x72fc,0x72fd,0x72fe,0x72ff, + 0x7300,0x7301,0x7302,0x7303,0x7304,0x7305,0x7306,0x7307, + 0x7308,0x7309,0x730a,0x730b,0x730c,0x730d,0x730e,0x730f, + 0x7310,0x7311,0x7312,0x7313,0x7314,0x7315,0x7316,0x7317, + 0x7318,0x7319,0x731a,0x731b,0x731c,0x731d,0x731e,0x731f, + 0x7320,0x7321,0x7322,0x7323,0x7324,0x7325,0x7326,0x7327, + 0x7328,0x7329,0x732a,0x732b,0x732c,0x732d,0x732e,0x732f, + 0x7330,0x7331,0x7332,0x7333,0x7334,0x7335,0x7336,0x7337, + 0x7338,0x7339,0x733a,0x733b,0x733c,0x733d,0x733e,0x733f, + 0x7340,0x7341,0x7342,0x7343,0x7344,0x7345,0x7346,0x7347, + 0x7348,0x7349,0x734a,0x734b,0x734c,0x734d,0x734e,0x734f, + 0x7350,0x7351,0x7352,0x7353,0x7354,0x7355,0x7356,0x7357, + 0x7358,0x7359,0x735a,0x735b,0x735c,0x735d,0x735e,0x735f, + 0x7360,0x7361,0x7362,0x7363,0x7364,0x7365,0x7366,0x7367, + 0x7368,0x7369,0x736a,0x736b,0x736c,0x736d,0x736e,0x736f, + 0x7370,0x7371,0x7372,0x7373,0x7374,0x7375,0x7376,0x7377, + 0x7378,0x7379,0x737a,0x737b,0x737c,0x737d,0x737e,0x737f, + 0x7380,0x7381,0x7382,0x7383,0x7384,0x7385,0x7386,0x7387, + 0x7388,0x7389,0x738a,0x738b,0x738c,0x738d,0x738e,0x738f, + 0x7390,0x7391,0x7392,0x7393,0x7394,0x7395,0x7396,0x7397, + 0x7398,0x7399,0x739a,0x739b,0x739c,0x739d,0x739e,0x739f, + 0x73a0,0x73a1,0x73a2,0x73a3,0x73a4,0x73a5,0x73a6,0x73a7, + 0x73a8,0x73a9,0x73aa,0x73ab,0x73ac,0x73ad,0x73ae,0x73af, + 0x73b0,0x73b1,0x73b2,0x73b3,0x73b4,0x73b5,0x73b6,0x73b7, + 0x73b8,0x73b9,0x73ba,0x73bb,0x73bc,0x73bd,0x73be,0x73bf, + 0x73c0,0x73c1,0x73c2,0x73c3,0x73c4,0x73c5,0x73c6,0x73c7, + 0x73c8,0x73c9,0x73ca,0x73cb,0x73cc,0x73cd,0x73ce,0x73cf, + 0x73d0,0x73d1,0x73d2,0x73d3,0x73d4,0x73d5,0x73d6,0x73d7, + 0x73d8,0x73d9,0x73da,0x73db,0x73dc,0x73dd,0x73de,0x73df, + 0x73e0,0x73e1,0x73e2,0x73e3,0x73e4,0x73e5,0x73e6,0x73e7, + 0x73e8,0x73e9,0x73ea,0x73eb,0x73ec,0x73ed,0x73ee,0x73ef, + 0x73f0,0x73f1,0x73f2,0x73f3,0x73f4,0x73f5,0x73f6,0x73f7, + 0x73f8,0x73f9,0x73fa,0x73fb,0x73fc,0x73fd,0x73fe,0x73ff, + 0x7400,0x7401,0x7402,0x7403,0x7404,0x7405,0x7406,0x7407, + 0x7408,0x7409,0x740a,0x740b,0x740c,0x740d,0x740e,0x740f, + 0x7410,0x7411,0x7412,0x7413,0x7414,0x7415,0x7416,0x7417, + 0x7418,0x7419,0x741a,0x741b,0x741c,0x741d,0x741e,0x741f, + 0x7420,0x7421,0x7422,0x7423,0x7424,0x7425,0x7426,0x7427, + 0x7428,0x7429,0x742a,0x742b,0x742c,0x742d,0x742e,0x742f, + 0x7430,0x7431,0x7432,0x7433,0x7434,0x7435,0x7436,0x7437, + 0x7438,0x7439,0x743a,0x743b,0x743c,0x743d,0x743e,0x743f, + 0x7440,0x7441,0x7442,0x7443,0x7444,0x7445,0x7446,0x7447, + 0x7448,0x7449,0x744a,0x744b,0x744c,0x744d,0x744e,0x744f, + 0x7450,0x7451,0x7452,0x7453,0x7454,0x7455,0x7456,0x7457, + 0x7458,0x7459,0x745a,0x745b,0x745c,0x745d,0x745e,0x745f, + 0x7460,0x7461,0x7462,0x7463,0x7464,0x7465,0x7466,0x7467, + 0x7468,0x7469,0x746a,0x746b,0x746c,0x746d,0x746e,0x746f, + 0x7470,0x7471,0x7472,0x7473,0x7474,0x7475,0x7476,0x7477, + 0x7478,0x7479,0x747a,0x747b,0x747c,0x747d,0x747e,0x747f, + 0x7480,0x7481,0x7482,0x7483,0x7484,0x7485,0x7486,0x7487, + 0x7488,0x7489,0x748a,0x748b,0x748c,0x748d,0x748e,0x748f, + 0x7490,0x7491,0x7492,0x7493,0x7494,0x7495,0x7496,0x7497, + 0x7498,0x7499,0x749a,0x749b,0x749c,0x749d,0x749e,0x749f, + 0x74a0,0x74a1,0x74a2,0x74a3,0x74a4,0x74a5,0x74a6,0x74a7, + 0x74a8,0x74a9,0x74aa,0x74ab,0x74ac,0x74ad,0x74ae,0x74af, + 0x74b0,0x74b1,0x74b2,0x74b3,0x74b4,0x74b5,0x74b6,0x74b7, + 0x74b8,0x74b9,0x74ba,0x74bb,0x74bc,0x74bd,0x74be,0x74bf, + 0x74c0,0x74c1,0x74c2,0x74c3,0x74c4,0x74c5,0x74c6,0x74c7, + 0x74c8,0x74c9,0x74ca,0x74cb,0x74cc,0x74cd,0x74ce,0x74cf, + 0x74d0,0x74d1,0x74d2,0x74d3,0x74d4,0x74d5,0x74d6,0x74d7, + 0x74d8,0x74d9,0x74da,0x74db,0x74dc,0x74dd,0x74de,0x74df, + 0x74e0,0x74e1,0x74e2,0x74e3,0x74e4,0x74e5,0x74e6,0x74e7, + 0x74e8,0x74e9,0x74ea,0x74eb,0x74ec,0x74ed,0x74ee,0x74ef, + 0x74f0,0x74f1,0x74f2,0x74f3,0x74f4,0x74f5,0x74f6,0x74f7, + 0x74f8,0x74f9,0x74fa,0x74fb,0x74fc,0x74fd,0x74fe,0x74ff, + 0x7500,0x7501,0x7502,0x7503,0x7504,0x7505,0x7506,0x7507, + 0x7508,0x7509,0x750a,0x750b,0x750c,0x750d,0x750e,0x750f, + 0x7510,0x7511,0x7512,0x7513,0x7514,0x7515,0x7516,0x7517, + 0x7518,0x7519,0x751a,0x751b,0x751c,0x751d,0x751e,0x751f, + 0x7520,0x7521,0x7522,0x7523,0x7524,0x7525,0x7526,0x7527, + 0x7528,0x7529,0x752a,0x752b,0x752c,0x752d,0x752e,0x752f, + 0x7530,0x7531,0x7532,0x7533,0x7534,0x7535,0x7536,0x7537, + 0x7538,0x7539,0x753a,0x753b,0x753c,0x753d,0x753e,0x753f, + 0x7540,0x7541,0x7542,0x7543,0x7544,0x7545,0x7546,0x7547, + 0x7548,0x7549,0x754a,0x754b,0x754c,0x754d,0x754e,0x754f, + 0x7550,0x7551,0x7552,0x7553,0x7554,0x7555,0x7556,0x7557, + 0x7558,0x7559,0x755a,0x755b,0x755c,0x755d,0x755e,0x755f, + 0x7560,0x7561,0x7562,0x7563,0x7564,0x7565,0x7566,0x7567, + 0x7568,0x7569,0x756a,0x756b,0x756c,0x756d,0x756e,0x756f, + 0x7570,0x7571,0x7572,0x7573,0x7574,0x7575,0x7576,0x7577, + 0x7578,0x7579,0x757a,0x757b,0x757c,0x757d,0x757e,0x757f, + 0x7580,0x7581,0x7582,0x7583,0x7584,0x7585,0x7586,0x7587, + 0x7588,0x7589,0x758a,0x758b,0x758c,0x758d,0x758e,0x758f, + 0x7590,0x7591,0x7592,0x7593,0x7594,0x7595,0x7596,0x7597, + 0x7598,0x7599,0x759a,0x759b,0x759c,0x759d,0x759e,0x759f, + 0x75a0,0x75a1,0x75a2,0x75a3,0x75a4,0x75a5,0x75a6,0x75a7, + 0x75a8,0x75a9,0x75aa,0x75ab,0x75ac,0x75ad,0x75ae,0x75af, + 0x75b0,0x75b1,0x75b2,0x75b3,0x75b4,0x75b5,0x75b6,0x75b7, + 0x75b8,0x75b9,0x75ba,0x75bb,0x75bc,0x75bd,0x75be,0x75bf, + 0x75c0,0x75c1,0x75c2,0x75c3,0x75c4,0x75c5,0x75c6,0x75c7, + 0x75c8,0x75c9,0x75ca,0x75cb,0x75cc,0x75cd,0x75ce,0x75cf, + 0x75d0,0x75d1,0x75d2,0x75d3,0x75d4,0x75d5,0x75d6,0x75d7, + 0x75d8,0x75d9,0x75da,0x75db,0x75dc,0x75dd,0x75de,0x75df, + 0x75e0,0x75e1,0x75e2,0x75e3,0x75e4,0x75e5,0x75e6,0x75e7, + 0x75e8,0x75e9,0x75ea,0x75eb,0x75ec,0x75ed,0x75ee,0x75ef, + 0x75f0,0x75f1,0x75f2,0x75f3,0x75f4,0x75f5,0x75f6,0x75f7, + 0x75f8,0x75f9,0x75fa,0x75fb,0x75fc,0x75fd,0x75fe,0x75ff, + 0x7600,0x7601,0x7602,0x7603,0x7604,0x7605,0x7606,0x7607, + 0x7608,0x7609,0x760a,0x760b,0x760c,0x760d,0x760e,0x760f, + 0x7610,0x7611,0x7612,0x7613,0x7614,0x7615,0x7616,0x7617, + 0x7618,0x7619,0x761a,0x761b,0x761c,0x761d,0x761e,0x761f, + 0x7620,0x7621,0x7622,0x7623,0x7624,0x7625,0x7626,0x7627, + 0x7628,0x7629,0x762a,0x762b,0x762c,0x762d,0x762e,0x762f, + 0x7630,0x7631,0x7632,0x7633,0x7634,0x7635,0x7636,0x7637, + 0x7638,0x7639,0x763a,0x763b,0x763c,0x763d,0x763e,0x763f, + 0x7640,0x7641,0x7642,0x7643,0x7644,0x7645,0x7646,0x7647, + 0x7648,0x7649,0x764a,0x764b,0x764c,0x764d,0x764e,0x764f, + 0x7650,0x7651,0x7652,0x7653,0x7654,0x7655,0x7656,0x7657, + 0x7658,0x7659,0x765a,0x765b,0x765c,0x765d,0x765e,0x765f, + 0x7660,0x7661,0x7662,0x7663,0x7664,0x7665,0x7666,0x7667, + 0x7668,0x7669,0x766a,0x766b,0x766c,0x766d,0x766e,0x766f, + 0x7670,0x7671,0x7672,0x7673,0x7674,0x7675,0x7676,0x7677, + 0x7678,0x7679,0x767a,0x767b,0x767c,0x767d,0x767e,0x767f, + 0x7680,0x7681,0x7682,0x7683,0x7684,0x7685,0x7686,0x7687, + 0x7688,0x7689,0x768a,0x768b,0x768c,0x768d,0x768e,0x768f, + 0x7690,0x7691,0x7692,0x7693,0x7694,0x7695,0x7696,0x7697, + 0x7698,0x7699,0x769a,0x769b,0x769c,0x769d,0x769e,0x769f, + 0x76a0,0x76a1,0x76a2,0x76a3,0x76a4,0x76a5,0x76a6,0x76a7, + 0x76a8,0x76a9,0x76aa,0x76ab,0x76ac,0x76ad,0x76ae,0x76af, + 0x76b0,0x76b1,0x76b2,0x76b3,0x76b4,0x76b5,0x76b6,0x76b7, + 0x76b8,0x76b9,0x76ba,0x76bb,0x76bc,0x76bd,0x76be,0x76bf, + 0x76c0,0x76c1,0x76c2,0x76c3,0x76c4,0x76c5,0x76c6,0x76c7, + 0x76c8,0x76c9,0x76ca,0x76cb,0x76cc,0x76cd,0x76ce,0x76cf, + 0x76d0,0x76d1,0x76d2,0x76d3,0x76d4,0x76d5,0x76d6,0x76d7, + 0x76d8,0x76d9,0x76da,0x76db,0x76dc,0x76dd,0x76de,0x76df, + 0x76e0,0x76e1,0x76e2,0x76e3,0x76e4,0x76e5,0x76e6,0x76e7, + 0x76e8,0x76e9,0x76ea,0x76eb,0x76ec,0x76ed,0x76ee,0x76ef, + 0x76f0,0x76f1,0x76f2,0x76f3,0x76f4,0x76f5,0x76f6,0x76f7, + 0x76f8,0x76f9,0x76fa,0x76fb,0x76fc,0x76fd,0x76fe,0x76ff, + 0x7700,0x7701,0x7702,0x7703,0x7704,0x7705,0x7706,0x7707, + 0x7708,0x7709,0x770a,0x770b,0x770c,0x770d,0x770e,0x770f, + 0x7710,0x7711,0x7712,0x7713,0x7714,0x7715,0x7716,0x7717, + 0x7718,0x7719,0x771a,0x771b,0x771c,0x771d,0x771e,0x771f, + 0x7720,0x7721,0x7722,0x7723,0x7724,0x7725,0x7726,0x7727, + 0x7728,0x7729,0x772a,0x772b,0x772c,0x772d,0x772e,0x772f, + 0x7730,0x7731,0x7732,0x7733,0x7734,0x7735,0x7736,0x7737, + 0x7738,0x7739,0x773a,0x773b,0x773c,0x773d,0x773e,0x773f, + 0x7740,0x7741,0x7742,0x7743,0x7744,0x7745,0x7746,0x7747, + 0x7748,0x7749,0x774a,0x774b,0x774c,0x774d,0x774e,0x774f, + 0x7750,0x7751,0x7752,0x7753,0x7754,0x7755,0x7756,0x7757, + 0x7758,0x7759,0x775a,0x775b,0x775c,0x775d,0x775e,0x775f, + 0x7760,0x7761,0x7762,0x7763,0x7764,0x7765,0x7766,0x7767, + 0x7768,0x7769,0x776a,0x776b,0x776c,0x776d,0x776e,0x776f, + 0x7770,0x7771,0x7772,0x7773,0x7774,0x7775,0x7776,0x7777, + 0x7778,0x7779,0x777a,0x777b,0x777c,0x777d,0x777e,0x777f, + 0x7780,0x7781,0x7782,0x7783,0x7784,0x7785,0x7786,0x7787, + 0x7788,0x7789,0x778a,0x778b,0x778c,0x778d,0x778e,0x778f, + 0x7790,0x7791,0x7792,0x7793,0x7794,0x7795,0x7796,0x7797, + 0x7798,0x7799,0x779a,0x779b,0x779c,0x779d,0x779e,0x779f, + 0x77a0,0x77a1,0x77a2,0x77a3,0x77a4,0x77a5,0x77a6,0x77a7, + 0x77a8,0x77a9,0x77aa,0x77ab,0x77ac,0x77ad,0x77ae,0x77af, + 0x77b0,0x77b1,0x77b2,0x77b3,0x77b4,0x77b5,0x77b6,0x77b7, + 0x77b8,0x77b9,0x77ba,0x77bb,0x77bc,0x77bd,0x77be,0x77bf, + 0x77c0,0x77c1,0x77c2,0x77c3,0x77c4,0x77c5,0x77c6,0x77c7, + 0x77c8,0x77c9,0x77ca,0x77cb,0x77cc,0x77cd,0x77ce,0x77cf, + 0x77d0,0x77d1,0x77d2,0x77d3,0x77d4,0x77d5,0x77d6,0x77d7, + 0x77d8,0x77d9,0x77da,0x77db,0x77dc,0x77dd,0x77de,0x77df, + 0x77e0,0x77e1,0x77e2,0x77e3,0x77e4,0x77e5,0x77e6,0x77e7, + 0x77e8,0x77e9,0x77ea,0x77eb,0x77ec,0x77ed,0x77ee,0x77ef, + 0x77f0,0x77f1,0x77f2,0x77f3,0x77f4,0x77f5,0x77f6,0x77f7, + 0x77f8,0x77f9,0x77fa,0x77fb,0x77fc,0x77fd,0x77fe,0x77ff, + 0x7800,0x7801,0x7802,0x7803,0x7804,0x7805,0x7806,0x7807, + 0x7808,0x7809,0x780a,0x780b,0x780c,0x780d,0x780e,0x780f, + 0x7810,0x7811,0x7812,0x7813,0x7814,0x7815,0x7816,0x7817, + 0x7818,0x7819,0x781a,0x781b,0x781c,0x781d,0x781e,0x781f, + 0x7820,0x7821,0x7822,0x7823,0x7824,0x7825,0x7826,0x7827, + 0x7828,0x7829,0x782a,0x782b,0x782c,0x782d,0x782e,0x782f, + 0x7830,0x7831,0x7832,0x7833,0x7834,0x7835,0x7836,0x7837, + 0x7838,0x7839,0x783a,0x783b,0x783c,0x783d,0x783e,0x783f, + 0x7840,0x7841,0x7842,0x7843,0x7844,0x7845,0x7846,0x7847, + 0x7848,0x7849,0x784a,0x784b,0x784c,0x784d,0x784e,0x784f, + 0x7850,0x7851,0x7852,0x7853,0x7854,0x7855,0x7856,0x7857, + 0x7858,0x7859,0x785a,0x785b,0x785c,0x785d,0x785e,0x785f, + 0x7860,0x7861,0x7862,0x7863,0x7864,0x7865,0x7866,0x7867, + 0x7868,0x7869,0x786a,0x786b,0x786c,0x786d,0x786e,0x786f, + 0x7870,0x7871,0x7872,0x7873,0x7874,0x7875,0x7876,0x7877, + 0x7878,0x7879,0x787a,0x787b,0x787c,0x787d,0x787e,0x787f, + 0x7880,0x7881,0x7882,0x7883,0x7884,0x7885,0x7886,0x7887, + 0x7888,0x7889,0x788a,0x788b,0x788c,0x788d,0x788e,0x788f, + 0x7890,0x7891,0x7892,0x7893,0x7894,0x7895,0x7896,0x7897, + 0x7898,0x7899,0x789a,0x789b,0x789c,0x789d,0x789e,0x789f, + 0x78a0,0x78a1,0x78a2,0x78a3,0x78a4,0x78a5,0x78a6,0x78a7, + 0x78a8,0x78a9,0x78aa,0x78ab,0x78ac,0x78ad,0x78ae,0x78af, + 0x78b0,0x78b1,0x78b2,0x78b3,0x78b4,0x78b5,0x78b6,0x78b7, + 0x78b8,0x78b9,0x78ba,0x78bb,0x78bc,0x78bd,0x78be,0x78bf, + 0x78c0,0x78c1,0x78c2,0x78c3,0x78c4,0x78c5,0x78c6,0x78c7, + 0x78c8,0x78c9,0x78ca,0x78cb,0x78cc,0x78cd,0x78ce,0x78cf, + 0x78d0,0x78d1,0x78d2,0x78d3,0x78d4,0x78d5,0x78d6,0x78d7, + 0x78d8,0x78d9,0x78da,0x78db,0x78dc,0x78dd,0x78de,0x78df, + 0x78e0,0x78e1,0x78e2,0x78e3,0x78e4,0x78e5,0x78e6,0x78e7, + 0x78e8,0x78e9,0x78ea,0x78eb,0x78ec,0x78ed,0x78ee,0x78ef, + 0x78f0,0x78f1,0x78f2,0x78f3,0x78f4,0x78f5,0x78f6,0x78f7, + 0x78f8,0x78f9,0x78fa,0x78fb,0x78fc,0x78fd,0x78fe,0x78ff, + 0x7900,0x7901,0x7902,0x7903,0x7904,0x7905,0x7906,0x7907, + 0x7908,0x7909,0x790a,0x790b,0x790c,0x790d,0x790e,0x790f, + 0x7910,0x7911,0x7912,0x7913,0x7914,0x7915,0x7916,0x7917, + 0x7918,0x7919,0x791a,0x791b,0x791c,0x791d,0x791e,0x791f, + 0x7920,0x7921,0x7922,0x7923,0x7924,0x7925,0x7926,0x7927, + 0x7928,0x7929,0x792a,0x792b,0x792c,0x792d,0x792e,0x792f, + 0x7930,0x7931,0x7932,0x7933,0x7934,0x7935,0x7936,0x7937, + 0x7938,0x7939,0x793a,0x793b,0x793c,0x793d,0x793e,0x793f, + 0x7940,0x7941,0x7942,0x7943,0x7944,0x7945,0x7946,0x7947, + 0x7948,0x7949,0x794a,0x794b,0x794c,0x794d,0x794e,0x794f, + 0x7950,0x7951,0x7952,0x7953,0x7954,0x7955,0x7956,0x7957, + 0x7958,0x7959,0x795a,0x795b,0x795c,0x795d,0x795e,0x795f, + 0x7960,0x7961,0x7962,0x7963,0x7964,0x7965,0x7966,0x7967, + 0x7968,0x7969,0x796a,0x796b,0x796c,0x796d,0x796e,0x796f, + 0x7970,0x7971,0x7972,0x7973,0x7974,0x7975,0x7976,0x7977, + 0x7978,0x7979,0x797a,0x797b,0x797c,0x797d,0x797e,0x797f, + 0x7980,0x7981,0x7982,0x7983,0x7984,0x7985,0x7986,0x7987, + 0x7988,0x7989,0x798a,0x798b,0x798c,0x798d,0x798e,0x798f, + 0x7990,0x7991,0x7992,0x7993,0x7994,0x7995,0x7996,0x7997, + 0x7998,0x7999,0x799a,0x799b,0x799c,0x799d,0x799e,0x799f, + 0x79a0,0x79a1,0x79a2,0x79a3,0x79a4,0x79a5,0x79a6,0x79a7, + 0x79a8,0x79a9,0x79aa,0x79ab,0x79ac,0x79ad,0x79ae,0x79af, + 0x79b0,0x79b1,0x79b2,0x79b3,0x79b4,0x79b5,0x79b6,0x79b7, + 0x79b8,0x79b9,0x79ba,0x79bb,0x79bc,0x79bd,0x79be,0x79bf, + 0x79c0,0x79c1,0x79c2,0x79c3,0x79c4,0x79c5,0x79c6,0x79c7, + 0x79c8,0x79c9,0x79ca,0x79cb,0x79cc,0x79cd,0x79ce,0x79cf, + 0x79d0,0x79d1,0x79d2,0x79d3,0x79d4,0x79d5,0x79d6,0x79d7, + 0x79d8,0x79d9,0x79da,0x79db,0x79dc,0x79dd,0x79de,0x79df, + 0x79e0,0x79e1,0x79e2,0x79e3,0x79e4,0x79e5,0x79e6,0x79e7, + 0x79e8,0x79e9,0x79ea,0x79eb,0x79ec,0x79ed,0x79ee,0x79ef, + 0x79f0,0x79f1,0x79f2,0x79f3,0x79f4,0x79f5,0x79f6,0x79f7, + 0x79f8,0x79f9,0x79fa,0x79fb,0x79fc,0x79fd,0x79fe,0x79ff, + 0x7a00,0x7a01,0x7a02,0x7a03,0x7a04,0x7a05,0x7a06,0x7a07, + 0x7a08,0x7a09,0x7a0a,0x7a0b,0x7a0c,0x7a0d,0x7a0e,0x7a0f, + 0x7a10,0x7a11,0x7a12,0x7a13,0x7a14,0x7a15,0x7a16,0x7a17, + 0x7a18,0x7a19,0x7a1a,0x7a1b,0x7a1c,0x7a1d,0x7a1e,0x7a1f, + 0x7a20,0x7a21,0x7a22,0x7a23,0x7a24,0x7a25,0x7a26,0x7a27, + 0x7a28,0x7a29,0x7a2a,0x7a2b,0x7a2c,0x7a2d,0x7a2e,0x7a2f, + 0x7a30,0x7a31,0x7a32,0x7a33,0x7a34,0x7a35,0x7a36,0x7a37, + 0x7a38,0x7a39,0x7a3a,0x7a3b,0x7a3c,0x7a3d,0x7a3e,0x7a3f, + 0x7a40,0x7a41,0x7a42,0x7a43,0x7a44,0x7a45,0x7a46,0x7a47, + 0x7a48,0x7a49,0x7a4a,0x7a4b,0x7a4c,0x7a4d,0x7a4e,0x7a4f, + 0x7a50,0x7a51,0x7a52,0x7a53,0x7a54,0x7a55,0x7a56,0x7a57, + 0x7a58,0x7a59,0x7a5a,0x7a5b,0x7a5c,0x7a5d,0x7a5e,0x7a5f, + 0x7a60,0x7a61,0x7a62,0x7a63,0x7a64,0x7a65,0x7a66,0x7a67, + 0x7a68,0x7a69,0x7a6a,0x7a6b,0x7a6c,0x7a6d,0x7a6e,0x7a6f, + 0x7a70,0x7a71,0x7a72,0x7a73,0x7a74,0x7a75,0x7a76,0x7a77, + 0x7a78,0x7a79,0x7a7a,0x7a7b,0x7a7c,0x7a7d,0x7a7e,0x7a7f, + 0x7a80,0x7a81,0x7a82,0x7a83,0x7a84,0x7a85,0x7a86,0x7a87, + 0x7a88,0x7a89,0x7a8a,0x7a8b,0x7a8c,0x7a8d,0x7a8e,0x7a8f, + 0x7a90,0x7a91,0x7a92,0x7a93,0x7a94,0x7a95,0x7a96,0x7a97, + 0x7a98,0x7a99,0x7a9a,0x7a9b,0x7a9c,0x7a9d,0x7a9e,0x7a9f, + 0x7aa0,0x7aa1,0x7aa2,0x7aa3,0x7aa4,0x7aa5,0x7aa6,0x7aa7, + 0x7aa8,0x7aa9,0x7aaa,0x7aab,0x7aac,0x7aad,0x7aae,0x7aaf, + 0x7ab0,0x7ab1,0x7ab2,0x7ab3,0x7ab4,0x7ab5,0x7ab6,0x7ab7, + 0x7ab8,0x7ab9,0x7aba,0x7abb,0x7abc,0x7abd,0x7abe,0x7abf, + 0x7ac0,0x7ac1,0x7ac2,0x7ac3,0x7ac4,0x7ac5,0x7ac6,0x7ac7, + 0x7ac8,0x7ac9,0x7aca,0x7acb,0x7acc,0x7acd,0x7ace,0x7acf, + 0x7ad0,0x7ad1,0x7ad2,0x7ad3,0x7ad4,0x7ad5,0x7ad6,0x7ad7, + 0x7ad8,0x7ad9,0x7ada,0x7adb,0x7adc,0x7add,0x7ade,0x7adf, + 0x7ae0,0x7ae1,0x7ae2,0x7ae3,0x7ae4,0x7ae5,0x7ae6,0x7ae7, + 0x7ae8,0x7ae9,0x7aea,0x7aeb,0x7aec,0x7aed,0x7aee,0x7aef, + 0x7af0,0x7af1,0x7af2,0x7af3,0x7af4,0x7af5,0x7af6,0x7af7, + 0x7af8,0x7af9,0x7afa,0x7afb,0x7afc,0x7afd,0x7afe,0x7aff, + 0x7b00,0x7b01,0x7b02,0x7b03,0x7b04,0x7b05,0x7b06,0x7b07, + 0x7b08,0x7b09,0x7b0a,0x7b0b,0x7b0c,0x7b0d,0x7b0e,0x7b0f, + 0x7b10,0x7b11,0x7b12,0x7b13,0x7b14,0x7b15,0x7b16,0x7b17, + 0x7b18,0x7b19,0x7b1a,0x7b1b,0x7b1c,0x7b1d,0x7b1e,0x7b1f, + 0x7b20,0x7b21,0x7b22,0x7b23,0x7b24,0x7b25,0x7b26,0x7b27, + 0x7b28,0x7b29,0x7b2a,0x7b2b,0x7b2c,0x7b2d,0x7b2e,0x7b2f, + 0x7b30,0x7b31,0x7b32,0x7b33,0x7b34,0x7b35,0x7b36,0x7b37, + 0x7b38,0x7b39,0x7b3a,0x7b3b,0x7b3c,0x7b3d,0x7b3e,0x7b3f, + 0x7b40,0x7b41,0x7b42,0x7b43,0x7b44,0x7b45,0x7b46,0x7b47, + 0x7b48,0x7b49,0x7b4a,0x7b4b,0x7b4c,0x7b4d,0x7b4e,0x7b4f, + 0x7b50,0x7b51,0x7b52,0x7b53,0x7b54,0x7b55,0x7b56,0x7b57, + 0x7b58,0x7b59,0x7b5a,0x7b5b,0x7b5c,0x7b5d,0x7b5e,0x7b5f, + 0x7b60,0x7b61,0x7b62,0x7b63,0x7b64,0x7b65,0x7b66,0x7b67, + 0x7b68,0x7b69,0x7b6a,0x7b6b,0x7b6c,0x7b6d,0x7b6e,0x7b6f, + 0x7b70,0x7b71,0x7b72,0x7b73,0x7b74,0x7b75,0x7b76,0x7b77, + 0x7b78,0x7b79,0x7b7a,0x7b7b,0x7b7c,0x7b7d,0x7b7e,0x7b7f, + 0x7b80,0x7b81,0x7b82,0x7b83,0x7b84,0x7b85,0x7b86,0x7b87, + 0x7b88,0x7b89,0x7b8a,0x7b8b,0x7b8c,0x7b8d,0x7b8e,0x7b8f, + 0x7b90,0x7b91,0x7b92,0x7b93,0x7b94,0x7b95,0x7b96,0x7b97, + 0x7b98,0x7b99,0x7b9a,0x7b9b,0x7b9c,0x7b9d,0x7b9e,0x7b9f, + 0x7ba0,0x7ba1,0x7ba2,0x7ba3,0x7ba4,0x7ba5,0x7ba6,0x7ba7, + 0x7ba8,0x7ba9,0x7baa,0x7bab,0x7bac,0x7bad,0x7bae,0x7baf, + 0x7bb0,0x7bb1,0x7bb2,0x7bb3,0x7bb4,0x7bb5,0x7bb6,0x7bb7, + 0x7bb8,0x7bb9,0x7bba,0x7bbb,0x7bbc,0x7bbd,0x7bbe,0x7bbf, + 0x7bc0,0x7bc1,0x7bc2,0x7bc3,0x7bc4,0x7bc5,0x7bc6,0x7bc7, + 0x7bc8,0x7bc9,0x7bca,0x7bcb,0x7bcc,0x7bcd,0x7bce,0x7bcf, + 0x7bd0,0x7bd1,0x7bd2,0x7bd3,0x7bd4,0x7bd5,0x7bd6,0x7bd7, + 0x7bd8,0x7bd9,0x7bda,0x7bdb,0x7bdc,0x7bdd,0x7bde,0x7bdf, + 0x7be0,0x7be1,0x7be2,0x7be3,0x7be4,0x7be5,0x7be6,0x7be7, + 0x7be8,0x7be9,0x7bea,0x7beb,0x7bec,0x7bed,0x7bee,0x7bef, + 0x7bf0,0x7bf1,0x7bf2,0x7bf3,0x7bf4,0x7bf5,0x7bf6,0x7bf7, + 0x7bf8,0x7bf9,0x7bfa,0x7bfb,0x7bfc,0x7bfd,0x7bfe,0x7bff, + 0x7c00,0x7c01,0x7c02,0x7c03,0x7c04,0x7c05,0x7c06,0x7c07, + 0x7c08,0x7c09,0x7c0a,0x7c0b,0x7c0c,0x7c0d,0x7c0e,0x7c0f, + 0x7c10,0x7c11,0x7c12,0x7c13,0x7c14,0x7c15,0x7c16,0x7c17, + 0x7c18,0x7c19,0x7c1a,0x7c1b,0x7c1c,0x7c1d,0x7c1e,0x7c1f, + 0x7c20,0x7c21,0x7c22,0x7c23,0x7c24,0x7c25,0x7c26,0x7c27, + 0x7c28,0x7c29,0x7c2a,0x7c2b,0x7c2c,0x7c2d,0x7c2e,0x7c2f, + 0x7c30,0x7c31,0x7c32,0x7c33,0x7c34,0x7c35,0x7c36,0x7c37, + 0x7c38,0x7c39,0x7c3a,0x7c3b,0x7c3c,0x7c3d,0x7c3e,0x7c3f, + 0x7c40,0x7c41,0x7c42,0x7c43,0x7c44,0x7c45,0x7c46,0x7c47, + 0x7c48,0x7c49,0x7c4a,0x7c4b,0x7c4c,0x7c4d,0x7c4e,0x7c4f, + 0x7c50,0x7c51,0x7c52,0x7c53,0x7c54,0x7c55,0x7c56,0x7c57, + 0x7c58,0x7c59,0x7c5a,0x7c5b,0x7c5c,0x7c5d,0x7c5e,0x7c5f, + 0x7c60,0x7c61,0x7c62,0x7c63,0x7c64,0x7c65,0x7c66,0x7c67, + 0x7c68,0x7c69,0x7c6a,0x7c6b,0x7c6c,0x7c6d,0x7c6e,0x7c6f, + 0x7c70,0x7c71,0x7c72,0x7c73,0x7c74,0x7c75,0x7c76,0x7c77, + 0x7c78,0x7c79,0x7c7a,0x7c7b,0x7c7c,0x7c7d,0x7c7e,0x7c7f, + 0x7c80,0x7c81,0x7c82,0x7c83,0x7c84,0x7c85,0x7c86,0x7c87, + 0x7c88,0x7c89,0x7c8a,0x7c8b,0x7c8c,0x7c8d,0x7c8e,0x7c8f, + 0x7c90,0x7c91,0x7c92,0x7c93,0x7c94,0x7c95,0x7c96,0x7c97, + 0x7c98,0x7c99,0x7c9a,0x7c9b,0x7c9c,0x7c9d,0x7c9e,0x7c9f, + 0x7ca0,0x7ca1,0x7ca2,0x7ca3,0x7ca4,0x7ca5,0x7ca6,0x7ca7, + 0x7ca8,0x7ca9,0x7caa,0x7cab,0x7cac,0x7cad,0x7cae,0x7caf, + 0x7cb0,0x7cb1,0x7cb2,0x7cb3,0x7cb4,0x7cb5,0x7cb6,0x7cb7, + 0x7cb8,0x7cb9,0x7cba,0x7cbb,0x7cbc,0x7cbd,0x7cbe,0x7cbf, + 0x7cc0,0x7cc1,0x7cc2,0x7cc3,0x7cc4,0x7cc5,0x7cc6,0x7cc7, + 0x7cc8,0x7cc9,0x7cca,0x7ccb,0x7ccc,0x7ccd,0x7cce,0x7ccf, + 0x7cd0,0x7cd1,0x7cd2,0x7cd3,0x7cd4,0x7cd5,0x7cd6,0x7cd7, + 0x7cd8,0x7cd9,0x7cda,0x7cdb,0x7cdc,0x7cdd,0x7cde,0x7cdf, + 0x7ce0,0x7ce1,0x7ce2,0x7ce3,0x7ce4,0x7ce5,0x7ce6,0x7ce7, + 0x7ce8,0x7ce9,0x7cea,0x7ceb,0x7cec,0x7ced,0x7cee,0x7cef, + 0x7cf0,0x7cf1,0x7cf2,0x7cf3,0x7cf4,0x7cf5,0x7cf6,0x7cf7, + 0x7cf8,0x7cf9,0x7cfa,0x7cfb,0x7cfc,0x7cfd,0x7cfe,0x7cff, + 0x7d00,0x7d01,0x7d02,0x7d03,0x7d04,0x7d05,0x7d06,0x7d07, + 0x7d08,0x7d09,0x7d0a,0x7d0b,0x7d0c,0x7d0d,0x7d0e,0x7d0f, + 0x7d10,0x7d11,0x7d12,0x7d13,0x7d14,0x7d15,0x7d16,0x7d17, + 0x7d18,0x7d19,0x7d1a,0x7d1b,0x7d1c,0x7d1d,0x7d1e,0x7d1f, + 0x7d20,0x7d21,0x7d22,0x7d23,0x7d24,0x7d25,0x7d26,0x7d27, + 0x7d28,0x7d29,0x7d2a,0x7d2b,0x7d2c,0x7d2d,0x7d2e,0x7d2f, + 0x7d30,0x7d31,0x7d32,0x7d33,0x7d34,0x7d35,0x7d36,0x7d37, + 0x7d38,0x7d39,0x7d3a,0x7d3b,0x7d3c,0x7d3d,0x7d3e,0x7d3f, + 0x7d40,0x7d41,0x7d42,0x7d43,0x7d44,0x7d45,0x7d46,0x7d47, + 0x7d48,0x7d49,0x7d4a,0x7d4b,0x7d4c,0x7d4d,0x7d4e,0x7d4f, + 0x7d50,0x7d51,0x7d52,0x7d53,0x7d54,0x7d55,0x7d56,0x7d57, + 0x7d58,0x7d59,0x7d5a,0x7d5b,0x7d5c,0x7d5d,0x7d5e,0x7d5f, + 0x7d60,0x7d61,0x7d62,0x7d63,0x7d64,0x7d65,0x7d66,0x7d67, + 0x7d68,0x7d69,0x7d6a,0x7d6b,0x7d6c,0x7d6d,0x7d6e,0x7d6f, + 0x7d70,0x7d71,0x7d72,0x7d73,0x7d74,0x7d75,0x7d76,0x7d77, + 0x7d78,0x7d79,0x7d7a,0x7d7b,0x7d7c,0x7d7d,0x7d7e,0x7d7f, + 0x7d80,0x7d81,0x7d82,0x7d83,0x7d84,0x7d85,0x7d86,0x7d87, + 0x7d88,0x7d89,0x7d8a,0x7d8b,0x7d8c,0x7d8d,0x7d8e,0x7d8f, + 0x7d90,0x7d91,0x7d92,0x7d93,0x7d94,0x7d95,0x7d96,0x7d97, + 0x7d98,0x7d99,0x7d9a,0x7d9b,0x7d9c,0x7d9d,0x7d9e,0x7d9f, + 0x7da0,0x7da1,0x7da2,0x7da3,0x7da4,0x7da5,0x7da6,0x7da7, + 0x7da8,0x7da9,0x7daa,0x7dab,0x7dac,0x7dad,0x7dae,0x7daf, + 0x7db0,0x7db1,0x7db2,0x7db3,0x7db4,0x7db5,0x7db6,0x7db7, + 0x7db8,0x7db9,0x7dba,0x7dbb,0x7dbc,0x7dbd,0x7dbe,0x7dbf, + 0x7dc0,0x7dc1,0x7dc2,0x7dc3,0x7dc4,0x7dc5,0x7dc6,0x7dc7, + 0x7dc8,0x7dc9,0x7dca,0x7dcb,0x7dcc,0x7dcd,0x7dce,0x7dcf, + 0x7dd0,0x7dd1,0x7dd2,0x7dd3,0x7dd4,0x7dd5,0x7dd6,0x7dd7, + 0x7dd8,0x7dd9,0x7dda,0x7ddb,0x7ddc,0x7ddd,0x7dde,0x7ddf, + 0x7de0,0x7de1,0x7de2,0x7de3,0x7de4,0x7de5,0x7de6,0x7de7, + 0x7de8,0x7de9,0x7dea,0x7deb,0x7dec,0x7ded,0x7dee,0x7def, + 0x7df0,0x7df1,0x7df2,0x7df3,0x7df4,0x7df5,0x7df6,0x7df7, + 0x7df8,0x7df9,0x7dfa,0x7dfb,0x7dfc,0x7dfd,0x7dfe,0x7dff, + 0x7e00,0x7e01,0x7e02,0x7e03,0x7e04,0x7e05,0x7e06,0x7e07, + 0x7e08,0x7e09,0x7e0a,0x7e0b,0x7e0c,0x7e0d,0x7e0e,0x7e0f, + 0x7e10,0x7e11,0x7e12,0x7e13,0x7e14,0x7e15,0x7e16,0x7e17, + 0x7e18,0x7e19,0x7e1a,0x7e1b,0x7e1c,0x7e1d,0x7e1e,0x7e1f, + 0x7e20,0x7e21,0x7e22,0x7e23,0x7e24,0x7e25,0x7e26,0x7e27, + 0x7e28,0x7e29,0x7e2a,0x7e2b,0x7e2c,0x7e2d,0x7e2e,0x7e2f, + 0x7e30,0x7e31,0x7e32,0x7e33,0x7e34,0x7e35,0x7e36,0x7e37, + 0x7e38,0x7e39,0x7e3a,0x7e3b,0x7e3c,0x7e3d,0x7e3e,0x7e3f, + 0x7e40,0x7e41,0x7e42,0x7e43,0x7e44,0x7e45,0x7e46,0x7e47, + 0x7e48,0x7e49,0x7e4a,0x7e4b,0x7e4c,0x7e4d,0x7e4e,0x7e4f, + 0x7e50,0x7e51,0x7e52,0x7e53,0x7e54,0x7e55,0x7e56,0x7e57, + 0x7e58,0x7e59,0x7e5a,0x7e5b,0x7e5c,0x7e5d,0x7e5e,0x7e5f, + 0x7e60,0x7e61,0x7e62,0x7e63,0x7e64,0x7e65,0x7e66,0x7e67, + 0x7e68,0x7e69,0x7e6a,0x7e6b,0x7e6c,0x7e6d,0x7e6e,0x7e6f, + 0x7e70,0x7e71,0x7e72,0x7e73,0x7e74,0x7e75,0x7e76,0x7e77, + 0x7e78,0x7e79,0x7e7a,0x7e7b,0x7e7c,0x7e7d,0x7e7e,0x7e7f, + 0x7e80,0x7e81,0x7e82,0x7e83,0x7e84,0x7e85,0x7e86,0x7e87, + 0x7e88,0x7e89,0x7e8a,0x7e8b,0x7e8c,0x7e8d,0x7e8e,0x7e8f, + 0x7e90,0x7e91,0x7e92,0x7e93,0x7e94,0x7e95,0x7e96,0x7e97, + 0x7e98,0x7e99,0x7e9a,0x7e9b,0x7e9c,0x7e9d,0x7e9e,0x7e9f, + 0x7ea0,0x7ea1,0x7ea2,0x7ea3,0x7ea4,0x7ea5,0x7ea6,0x7ea7, + 0x7ea8,0x7ea9,0x7eaa,0x7eab,0x7eac,0x7ead,0x7eae,0x7eaf, + 0x7eb0,0x7eb1,0x7eb2,0x7eb3,0x7eb4,0x7eb5,0x7eb6,0x7eb7, + 0x7eb8,0x7eb9,0x7eba,0x7ebb,0x7ebc,0x7ebd,0x7ebe,0x7ebf, + 0x7ec0,0x7ec1,0x7ec2,0x7ec3,0x7ec4,0x7ec5,0x7ec6,0x7ec7, + 0x7ec8,0x7ec9,0x7eca,0x7ecb,0x7ecc,0x7ecd,0x7ece,0x7ecf, + 0x7ed0,0x7ed1,0x7ed2,0x7ed3,0x7ed4,0x7ed5,0x7ed6,0x7ed7, + 0x7ed8,0x7ed9,0x7eda,0x7edb,0x7edc,0x7edd,0x7ede,0x7edf, + 0x7ee0,0x7ee1,0x7ee2,0x7ee3,0x7ee4,0x7ee5,0x7ee6,0x7ee7, + 0x7ee8,0x7ee9,0x7eea,0x7eeb,0x7eec,0x7eed,0x7eee,0x7eef, + 0x7ef0,0x7ef1,0x7ef2,0x7ef3,0x7ef4,0x7ef5,0x7ef6,0x7ef7, + 0x7ef8,0x7ef9,0x7efa,0x7efb,0x7efc,0x7efd,0x7efe,0x7eff, + 0x7f00,0x7f01,0x7f02,0x7f03,0x7f04,0x7f05,0x7f06,0x7f07, + 0x7f08,0x7f09,0x7f0a,0x7f0b,0x7f0c,0x7f0d,0x7f0e,0x7f0f, + 0x7f10,0x7f11,0x7f12,0x7f13,0x7f14,0x7f15,0x7f16,0x7f17, + 0x7f18,0x7f19,0x7f1a,0x7f1b,0x7f1c,0x7f1d,0x7f1e,0x7f1f, + 0x7f20,0x7f21,0x7f22,0x7f23,0x7f24,0x7f25,0x7f26,0x7f27, + 0x7f28,0x7f29,0x7f2a,0x7f2b,0x7f2c,0x7f2d,0x7f2e,0x7f2f, + 0x7f30,0x7f31,0x7f32,0x7f33,0x7f34,0x7f35,0x7f36,0x7f37, + 0x7f38,0x7f39,0x7f3a,0x7f3b,0x7f3c,0x7f3d,0x7f3e,0x7f3f, + 0x7f40,0x7f41,0x7f42,0x7f43,0x7f44,0x7f45,0x7f46,0x7f47, + 0x7f48,0x7f49,0x7f4a,0x7f4b,0x7f4c,0x7f4d,0x7f4e,0x7f4f, + 0x7f50,0x7f51,0x7f52,0x7f53,0x7f54,0x7f55,0x7f56,0x7f57, + 0x7f58,0x7f59,0x7f5a,0x7f5b,0x7f5c,0x7f5d,0x7f5e,0x7f5f, + 0x7f60,0x7f61,0x7f62,0x7f63,0x7f64,0x7f65,0x7f66,0x7f67, + 0x7f68,0x7f69,0x7f6a,0x7f6b,0x7f6c,0x7f6d,0x7f6e,0x7f6f, + 0x7f70,0x7f71,0x7f72,0x7f73,0x7f74,0x7f75,0x7f76,0x7f77, + 0x7f78,0x7f79,0x7f7a,0x7f7b,0x7f7c,0x7f7d,0x7f7e,0x7f7f, + 0x7f80,0x7f81,0x7f82,0x7f83,0x7f84,0x7f85,0x7f86,0x7f87, + 0x7f88,0x7f89,0x7f8a,0x7f8b,0x7f8c,0x7f8d,0x7f8e,0x7f8f, + 0x7f90,0x7f91,0x7f92,0x7f93,0x7f94,0x7f95,0x7f96,0x7f97, + 0x7f98,0x7f99,0x7f9a,0x7f9b,0x7f9c,0x7f9d,0x7f9e,0x7f9f, + 0x7fa0,0x7fa1,0x7fa2,0x7fa3,0x7fa4,0x7fa5,0x7fa6,0x7fa7, + 0x7fa8,0x7fa9,0x7faa,0x7fab,0x7fac,0x7fad,0x7fae,0x7faf, + 0x7fb0,0x7fb1,0x7fb2,0x7fb3,0x7fb4,0x7fb5,0x7fb6,0x7fb7, + 0x7fb8,0x7fb9,0x7fba,0x7fbb,0x7fbc,0x7fbd,0x7fbe,0x7fbf, + 0x7fc0,0x7fc1,0x7fc2,0x7fc3,0x7fc4,0x7fc5,0x7fc6,0x7fc7, + 0x7fc8,0x7fc9,0x7fca,0x7fcb,0x7fcc,0x7fcd,0x7fce,0x7fcf, + 0x7fd0,0x7fd1,0x7fd2,0x7fd3,0x7fd4,0x7fd5,0x7fd6,0x7fd7, + 0x7fd8,0x7fd9,0x7fda,0x7fdb,0x7fdc,0x7fdd,0x7fde,0x7fdf, + 0x7fe0,0x7fe1,0x7fe2,0x7fe3,0x7fe4,0x7fe5,0x7fe6,0x7fe7, + 0x7fe8,0x7fe9,0x7fea,0x7feb,0x7fec,0x7fed,0x7fee,0x7fef, + 0x7ff0,0x7ff1,0x7ff2,0x7ff3,0x7ff4,0x7ff5,0x7ff6,0x7ff7, + 0x7ff8,0x7ff9,0x7ffa,0x7ffb,0x7ffc,0x7ffd,0x7ffe,0x7fff, + 0x8000,0x8001,0x8002,0x8003,0x8004,0x8005,0x8006,0x8007, + 0x8008,0x8009,0x800a,0x800b,0x800c,0x800d,0x800e,0x800f, + 0x8010,0x8011,0x8012,0x8013,0x8014,0x8015,0x8016,0x8017, + 0x8018,0x8019,0x801a,0x801b,0x801c,0x801d,0x801e,0x801f, + 0x8020,0x8021,0x8022,0x8023,0x8024,0x8025,0x8026,0x8027, + 0x8028,0x8029,0x802a,0x802b,0x802c,0x802d,0x802e,0x802f, + 0x8030,0x8031,0x8032,0x8033,0x8034,0x8035,0x8036,0x8037, + 0x8038,0x8039,0x803a,0x803b,0x803c,0x803d,0x803e,0x803f, + 0x8040,0x8041,0x8042,0x8043,0x8044,0x8045,0x8046,0x8047, + 0x8048,0x8049,0x804a,0x804b,0x804c,0x804d,0x804e,0x804f, + 0x8050,0x8051,0x8052,0x8053,0x8054,0x8055,0x8056,0x8057, + 0x8058,0x8059,0x805a,0x805b,0x805c,0x805d,0x805e,0x805f, + 0x8060,0x8061,0x8062,0x8063,0x8064,0x8065,0x8066,0x8067, + 0x8068,0x8069,0x806a,0x806b,0x806c,0x806d,0x806e,0x806f, + 0x8070,0x8071,0x8072,0x8073,0x8074,0x8075,0x8076,0x8077, + 0x8078,0x8079,0x807a,0x807b,0x807c,0x807d,0x807e,0x807f, + 0x8080,0x8081,0x8082,0x8083,0x8084,0x8085,0x8086,0x8087, + 0x8088,0x8089,0x808a,0x808b,0x808c,0x808d,0x808e,0x808f, + 0x8090,0x8091,0x8092,0x8093,0x8094,0x8095,0x8096,0x8097, + 0x8098,0x8099,0x809a,0x809b,0x809c,0x809d,0x809e,0x809f, + 0x80a0,0x80a1,0x80a2,0x80a3,0x80a4,0x80a5,0x80a6,0x80a7, + 0x80a8,0x80a9,0x80aa,0x80ab,0x80ac,0x80ad,0x80ae,0x80af, + 0x80b0,0x80b1,0x80b2,0x80b3,0x80b4,0x80b5,0x80b6,0x80b7, + 0x80b8,0x80b9,0x80ba,0x80bb,0x80bc,0x80bd,0x80be,0x80bf, + 0x80c0,0x80c1,0x80c2,0x80c3,0x80c4,0x80c5,0x80c6,0x80c7, + 0x80c8,0x80c9,0x80ca,0x80cb,0x80cc,0x80cd,0x80ce,0x80cf, + 0x80d0,0x80d1,0x80d2,0x80d3,0x80d4,0x80d5,0x80d6,0x80d7, + 0x80d8,0x80d9,0x80da,0x80db,0x80dc,0x80dd,0x80de,0x80df, + 0x80e0,0x80e1,0x80e2,0x80e3,0x80e4,0x80e5,0x80e6,0x80e7, + 0x80e8,0x80e9,0x80ea,0x80eb,0x80ec,0x80ed,0x80ee,0x80ef, + 0x80f0,0x80f1,0x80f2,0x80f3,0x80f4,0x80f5,0x80f6,0x80f7, + 0x80f8,0x80f9,0x80fa,0x80fb,0x80fc,0x80fd,0x80fe,0x80ff, + 0x8100,0x8101,0x8102,0x8103,0x8104,0x8105,0x8106,0x8107, + 0x8108,0x8109,0x810a,0x810b,0x810c,0x810d,0x810e,0x810f, + 0x8110,0x8111,0x8112,0x8113,0x8114,0x8115,0x8116,0x8117, + 0x8118,0x8119,0x811a,0x811b,0x811c,0x811d,0x811e,0x811f, + 0x8120,0x8121,0x8122,0x8123,0x8124,0x8125,0x8126,0x8127, + 0x8128,0x8129,0x812a,0x812b,0x812c,0x812d,0x812e,0x812f, + 0x8130,0x8131,0x8132,0x8133,0x8134,0x8135,0x8136,0x8137, + 0x8138,0x8139,0x813a,0x813b,0x813c,0x813d,0x813e,0x813f, + 0x8140,0x8141,0x8142,0x8143,0x8144,0x8145,0x8146,0x8147, + 0x8148,0x8149,0x814a,0x814b,0x814c,0x814d,0x814e,0x814f, + 0x8150,0x8151,0x8152,0x8153,0x8154,0x8155,0x8156,0x8157, + 0x8158,0x8159,0x815a,0x815b,0x815c,0x815d,0x815e,0x815f, + 0x8160,0x8161,0x8162,0x8163,0x8164,0x8165,0x8166,0x8167, + 0x8168,0x8169,0x816a,0x816b,0x816c,0x816d,0x816e,0x816f, + 0x8170,0x8171,0x8172,0x8173,0x8174,0x8175,0x8176,0x8177, + 0x8178,0x8179,0x817a,0x817b,0x817c,0x817d,0x817e,0x817f, + 0x8180,0x8181,0x8182,0x8183,0x8184,0x8185,0x8186,0x8187, + 0x8188,0x8189,0x818a,0x818b,0x818c,0x818d,0x818e,0x818f, + 0x8190,0x8191,0x8192,0x8193,0x8194,0x8195,0x8196,0x8197, + 0x8198,0x8199,0x819a,0x819b,0x819c,0x819d,0x819e,0x819f, + 0x81a0,0x81a1,0x81a2,0x81a3,0x81a4,0x81a5,0x81a6,0x81a7, + 0x81a8,0x81a9,0x81aa,0x81ab,0x81ac,0x81ad,0x81ae,0x81af, + 0x81b0,0x81b1,0x81b2,0x81b3,0x81b4,0x81b5,0x81b6,0x81b7, + 0x81b8,0x81b9,0x81ba,0x81bb,0x81bc,0x81bd,0x81be,0x81bf, + 0x81c0,0x81c1,0x81c2,0x81c3,0x81c4,0x81c5,0x81c6,0x81c7, + 0x81c8,0x81c9,0x81ca,0x81cb,0x81cc,0x81cd,0x81ce,0x81cf, + 0x81d0,0x81d1,0x81d2,0x81d3,0x81d4,0x81d5,0x81d6,0x81d7, + 0x81d8,0x81d9,0x81da,0x81db,0x81dc,0x81dd,0x81de,0x81df, + 0x81e0,0x81e1,0x81e2,0x81e3,0x81e4,0x81e5,0x81e6,0x81e7, + 0x81e8,0x81e9,0x81ea,0x81eb,0x81ec,0x81ed,0x81ee,0x81ef, + 0x81f0,0x81f1,0x81f2,0x81f3,0x81f4,0x81f5,0x81f6,0x81f7, + 0x81f8,0x81f9,0x81fa,0x81fb,0x81fc,0x81fd,0x81fe,0x81ff, + 0x8200,0x8201,0x8202,0x8203,0x8204,0x8205,0x8206,0x8207, + 0x8208,0x8209,0x820a,0x820b,0x820c,0x820d,0x820e,0x820f, + 0x8210,0x8211,0x8212,0x8213,0x8214,0x8215,0x8216,0x8217, + 0x8218,0x8219,0x821a,0x821b,0x821c,0x821d,0x821e,0x821f, + 0x8220,0x8221,0x8222,0x8223,0x8224,0x8225,0x8226,0x8227, + 0x8228,0x8229,0x822a,0x822b,0x822c,0x822d,0x822e,0x822f, + 0x8230,0x8231,0x8232,0x8233,0x8234,0x8235,0x8236,0x8237, + 0x8238,0x8239,0x823a,0x823b,0x823c,0x823d,0x823e,0x823f, + 0x8240,0x8241,0x8242,0x8243,0x8244,0x8245,0x8246,0x8247, + 0x8248,0x8249,0x824a,0x824b,0x824c,0x824d,0x824e,0x824f, + 0x8250,0x8251,0x8252,0x8253,0x8254,0x8255,0x8256,0x8257, + 0x8258,0x8259,0x825a,0x825b,0x825c,0x825d,0x825e,0x825f, + 0x8260,0x8261,0x8262,0x8263,0x8264,0x8265,0x8266,0x8267, + 0x8268,0x8269,0x826a,0x826b,0x826c,0x826d,0x826e,0x826f, + 0x8270,0x8271,0x8272,0x8273,0x8274,0x8275,0x8276,0x8277, + 0x8278,0x8279,0x827a,0x827b,0x827c,0x827d,0x827e,0x827f, + 0x8280,0x8281,0x8282,0x8283,0x8284,0x8285,0x8286,0x8287, + 0x8288,0x8289,0x828a,0x828b,0x828c,0x828d,0x828e,0x828f, + 0x8290,0x8291,0x8292,0x8293,0x8294,0x8295,0x8296,0x8297, + 0x8298,0x8299,0x829a,0x829b,0x829c,0x829d,0x829e,0x829f, + 0x82a0,0x82a1,0x82a2,0x82a3,0x82a4,0x82a5,0x82a6,0x82a7, + 0x82a8,0x82a9,0x82aa,0x82ab,0x82ac,0x82ad,0x82ae,0x82af, + 0x82b0,0x82b1,0x82b2,0x82b3,0x82b4,0x82b5,0x82b6,0x82b7, + 0x82b8,0x82b9,0x82ba,0x82bb,0x82bc,0x82bd,0x82be,0x82bf, + 0x82c0,0x82c1,0x82c2,0x82c3,0x82c4,0x82c5,0x82c6,0x82c7, + 0x82c8,0x82c9,0x82ca,0x82cb,0x82cc,0x82cd,0x82ce,0x82cf, + 0x82d0,0x82d1,0x82d2,0x82d3,0x82d4,0x82d5,0x82d6,0x82d7, + 0x82d8,0x82d9,0x82da,0x82db,0x82dc,0x82dd,0x82de,0x82df, + 0x82e0,0x82e1,0x82e2,0x82e3,0x82e4,0x82e5,0x82e6,0x82e7, + 0x82e8,0x82e9,0x82ea,0x82eb,0x82ec,0x82ed,0x82ee,0x82ef, + 0x82f0,0x82f1,0x82f2,0x82f3,0x82f4,0x82f5,0x82f6,0x82f7, + 0x82f8,0x82f9,0x82fa,0x82fb,0x82fc,0x82fd,0x82fe,0x82ff, + 0x8300,0x8301,0x8302,0x8303,0x8304,0x8305,0x8306,0x8307, + 0x8308,0x8309,0x830a,0x830b,0x830c,0x830d,0x830e,0x830f, + 0x8310,0x8311,0x8312,0x8313,0x8314,0x8315,0x8316,0x8317, + 0x8318,0x8319,0x831a,0x831b,0x831c,0x831d,0x831e,0x831f, + 0x8320,0x8321,0x8322,0x8323,0x8324,0x8325,0x8326,0x8327, + 0x8328,0x8329,0x832a,0x832b,0x832c,0x832d,0x832e,0x832f, + 0x8330,0x8331,0x8332,0x8333,0x8334,0x8335,0x8336,0x8337, + 0x8338,0x8339,0x833a,0x833b,0x833c,0x833d,0x833e,0x833f, + 0x8340,0x8341,0x8342,0x8343,0x8344,0x8345,0x8346,0x8347, + 0x8348,0x8349,0x834a,0x834b,0x834c,0x834d,0x834e,0x834f, + 0x8350,0x8351,0x8352,0x8353,0x8354,0x8355,0x8356,0x8357, + 0x8358,0x8359,0x835a,0x835b,0x835c,0x835d,0x835e,0x835f, + 0x8360,0x8361,0x8362,0x8363,0x8364,0x8365,0x8366,0x8367, + 0x8368,0x8369,0x836a,0x836b,0x836c,0x836d,0x836e,0x836f, + 0x8370,0x8371,0x8372,0x8373,0x8374,0x8375,0x8376,0x8377, + 0x8378,0x8379,0x837a,0x837b,0x837c,0x837d,0x837e,0x837f, + 0x8380,0x8381,0x8382,0x8383,0x8384,0x8385,0x8386,0x8387, + 0x8388,0x8389,0x838a,0x838b,0x838c,0x838d,0x838e,0x838f, + 0x8390,0x8391,0x8392,0x8393,0x8394,0x8395,0x8396,0x8397, + 0x8398,0x8399,0x839a,0x839b,0x839c,0x839d,0x839e,0x839f, + 0x83a0,0x83a1,0x83a2,0x83a3,0x83a4,0x83a5,0x83a6,0x83a7, + 0x83a8,0x83a9,0x83aa,0x83ab,0x83ac,0x83ad,0x83ae,0x83af, + 0x83b0,0x83b1,0x83b2,0x83b3,0x83b4,0x83b5,0x83b6,0x83b7, + 0x83b8,0x83b9,0x83ba,0x83bb,0x83bc,0x83bd,0x83be,0x83bf, + 0x83c0,0x83c1,0x83c2,0x83c3,0x83c4,0x83c5,0x83c6,0x83c7, + 0x83c8,0x83c9,0x83ca,0x83cb,0x83cc,0x83cd,0x83ce,0x83cf, + 0x83d0,0x83d1,0x83d2,0x83d3,0x83d4,0x83d5,0x83d6,0x83d7, + 0x83d8,0x83d9,0x83da,0x83db,0x83dc,0x83dd,0x83de,0x83df, + 0x83e0,0x83e1,0x83e2,0x83e3,0x83e4,0x83e5,0x83e6,0x83e7, + 0x83e8,0x83e9,0x83ea,0x83eb,0x83ec,0x83ed,0x83ee,0x83ef, + 0x83f0,0x83f1,0x83f2,0x83f3,0x83f4,0x83f5,0x83f6,0x83f7, + 0x83f8,0x83f9,0x83fa,0x83fb,0x83fc,0x83fd,0x83fe,0x83ff, + 0x8400,0x8401,0x8402,0x8403,0x8404,0x8405,0x8406,0x8407, + 0x8408,0x8409,0x840a,0x840b,0x840c,0x840d,0x840e,0x840f, + 0x8410,0x8411,0x8412,0x8413,0x8414,0x8415,0x8416,0x8417, + 0x8418,0x8419,0x841a,0x841b,0x841c,0x841d,0x841e,0x841f, + 0x8420,0x8421,0x8422,0x8423,0x8424,0x8425,0x8426,0x8427, + 0x8428,0x8429,0x842a,0x842b,0x842c,0x842d,0x842e,0x842f, + 0x8430,0x8431,0x8432,0x8433,0x8434,0x8435,0x8436,0x8437, + 0x8438,0x8439,0x843a,0x843b,0x843c,0x843d,0x843e,0x843f, + 0x8440,0x8441,0x8442,0x8443,0x8444,0x8445,0x8446,0x8447, + 0x8448,0x8449,0x844a,0x844b,0x844c,0x844d,0x844e,0x844f, + 0x8450,0x8451,0x8452,0x8453,0x8454,0x8455,0x8456,0x8457, + 0x8458,0x8459,0x845a,0x845b,0x845c,0x845d,0x845e,0x845f, + 0x8460,0x8461,0x8462,0x8463,0x8464,0x8465,0x8466,0x8467, + 0x8468,0x8469,0x846a,0x846b,0x846c,0x846d,0x846e,0x846f, + 0x8470,0x8471,0x8472,0x8473,0x8474,0x8475,0x8476,0x8477, + 0x8478,0x8479,0x847a,0x847b,0x847c,0x847d,0x847e,0x847f, + 0x8480,0x8481,0x8482,0x8483,0x8484,0x8485,0x8486,0x8487, + 0x8488,0x8489,0x848a,0x848b,0x848c,0x848d,0x848e,0x848f, + 0x8490,0x8491,0x8492,0x8493,0x8494,0x8495,0x8496,0x8497, + 0x8498,0x8499,0x849a,0x849b,0x849c,0x849d,0x849e,0x849f, + 0x84a0,0x84a1,0x84a2,0x84a3,0x84a4,0x84a5,0x84a6,0x84a7, + 0x84a8,0x84a9,0x84aa,0x84ab,0x84ac,0x84ad,0x84ae,0x84af, + 0x84b0,0x84b1,0x84b2,0x84b3,0x84b4,0x84b5,0x84b6,0x84b7, + 0x84b8,0x84b9,0x84ba,0x84bb,0x84bc,0x84bd,0x84be,0x84bf, + 0x84c0,0x84c1,0x84c2,0x84c3,0x84c4,0x84c5,0x84c6,0x84c7, + 0x84c8,0x84c9,0x84ca,0x84cb,0x84cc,0x84cd,0x84ce,0x84cf, + 0x84d0,0x84d1,0x84d2,0x84d3,0x84d4,0x84d5,0x84d6,0x84d7, + 0x84d8,0x84d9,0x84da,0x84db,0x84dc,0x84dd,0x84de,0x84df, + 0x84e0,0x84e1,0x84e2,0x84e3,0x84e4,0x84e5,0x84e6,0x84e7, + 0x84e8,0x84e9,0x84ea,0x84eb,0x84ec,0x84ed,0x84ee,0x84ef, + 0x84f0,0x84f1,0x84f2,0x84f3,0x84f4,0x84f5,0x84f6,0x84f7, + 0x84f8,0x84f9,0x84fa,0x84fb,0x84fc,0x84fd,0x84fe,0x84ff, + 0x8500,0x8501,0x8502,0x8503,0x8504,0x8505,0x8506,0x8507, + 0x8508,0x8509,0x850a,0x850b,0x850c,0x850d,0x850e,0x850f, + 0x8510,0x8511,0x8512,0x8513,0x8514,0x8515,0x8516,0x8517, + 0x8518,0x8519,0x851a,0x851b,0x851c,0x851d,0x851e,0x851f, + 0x8520,0x8521,0x8522,0x8523,0x8524,0x8525,0x8526,0x8527, + 0x8528,0x8529,0x852a,0x852b,0x852c,0x852d,0x852e,0x852f, + 0x8530,0x8531,0x8532,0x8533,0x8534,0x8535,0x8536,0x8537, + 0x8538,0x8539,0x853a,0x853b,0x853c,0x853d,0x853e,0x853f, + 0x8540,0x8541,0x8542,0x8543,0x8544,0x8545,0x8546,0x8547, + 0x8548,0x8549,0x854a,0x854b,0x854c,0x854d,0x854e,0x854f, + 0x8550,0x8551,0x8552,0x8553,0x8554,0x8555,0x8556,0x8557, + 0x8558,0x8559,0x855a,0x855b,0x855c,0x855d,0x855e,0x855f, + 0x8560,0x8561,0x8562,0x8563,0x8564,0x8565,0x8566,0x8567, + 0x8568,0x8569,0x856a,0x856b,0x856c,0x856d,0x856e,0x856f, + 0x8570,0x8571,0x8572,0x8573,0x8574,0x8575,0x8576,0x8577, + 0x8578,0x8579,0x857a,0x857b,0x857c,0x857d,0x857e,0x857f, + 0x8580,0x8581,0x8582,0x8583,0x8584,0x8585,0x8586,0x8587, + 0x8588,0x8589,0x858a,0x858b,0x858c,0x858d,0x858e,0x858f, + 0x8590,0x8591,0x8592,0x8593,0x8594,0x8595,0x8596,0x8597, + 0x8598,0x8599,0x859a,0x859b,0x859c,0x859d,0x859e,0x859f, + 0x85a0,0x85a1,0x85a2,0x85a3,0x85a4,0x85a5,0x85a6,0x85a7, + 0x85a8,0x85a9,0x85aa,0x85ab,0x85ac,0x85ad,0x85ae,0x85af, + 0x85b0,0x85b1,0x85b2,0x85b3,0x85b4,0x85b5,0x85b6,0x85b7, + 0x85b8,0x85b9,0x85ba,0x85bb,0x85bc,0x85bd,0x85be,0x85bf, + 0x85c0,0x85c1,0x85c2,0x85c3,0x85c4,0x85c5,0x85c6,0x85c7, + 0x85c8,0x85c9,0x85ca,0x85cb,0x85cc,0x85cd,0x85ce,0x85cf, + 0x85d0,0x85d1,0x85d2,0x85d3,0x85d4,0x85d5,0x85d6,0x85d7, + 0x85d8,0x85d9,0x85da,0x85db,0x85dc,0x85dd,0x85de,0x85df, + 0x85e0,0x85e1,0x85e2,0x85e3,0x85e4,0x85e5,0x85e6,0x85e7, + 0x85e8,0x85e9,0x85ea,0x85eb,0x85ec,0x85ed,0x85ee,0x85ef, + 0x85f0,0x85f1,0x85f2,0x85f3,0x85f4,0x85f5,0x85f6,0x85f7, + 0x85f8,0x85f9,0x85fa,0x85fb,0x85fc,0x85fd,0x85fe,0x85ff, + 0x8600,0x8601,0x8602,0x8603,0x8604,0x8605,0x8606,0x8607, + 0x8608,0x8609,0x860a,0x860b,0x860c,0x860d,0x860e,0x860f, + 0x8610,0x8611,0x8612,0x8613,0x8614,0x8615,0x8616,0x8617, + 0x8618,0x8619,0x861a,0x861b,0x861c,0x861d,0x861e,0x861f, + 0x8620,0x8621,0x8622,0x8623,0x8624,0x8625,0x8626,0x8627, + 0x8628,0x8629,0x862a,0x862b,0x862c,0x862d,0x862e,0x862f, + 0x8630,0x8631,0x8632,0x8633,0x8634,0x8635,0x8636,0x8637, + 0x8638,0x8639,0x863a,0x863b,0x863c,0x863d,0x863e,0x863f, + 0x8640,0x8641,0x8642,0x8643,0x8644,0x8645,0x8646,0x8647, + 0x8648,0x8649,0x864a,0x864b,0x864c,0x864d,0x864e,0x864f, + 0x8650,0x8651,0x8652,0x8653,0x8654,0x8655,0x8656,0x8657, + 0x8658,0x8659,0x865a,0x865b,0x865c,0x865d,0x865e,0x865f, + 0x8660,0x8661,0x8662,0x8663,0x8664,0x8665,0x8666,0x8667, + 0x8668,0x8669,0x866a,0x866b,0x866c,0x866d,0x866e,0x866f, + 0x8670,0x8671,0x8672,0x8673,0x8674,0x8675,0x8676,0x8677, + 0x8678,0x8679,0x867a,0x867b,0x867c,0x867d,0x867e,0x867f, + 0x8680,0x8681,0x8682,0x8683,0x8684,0x8685,0x8686,0x8687, + 0x8688,0x8689,0x868a,0x868b,0x868c,0x868d,0x868e,0x868f, + 0x8690,0x8691,0x8692,0x8693,0x8694,0x8695,0x8696,0x8697, + 0x8698,0x8699,0x869a,0x869b,0x869c,0x869d,0x869e,0x869f, + 0x86a0,0x86a1,0x86a2,0x86a3,0x86a4,0x86a5,0x86a6,0x86a7, + 0x86a8,0x86a9,0x86aa,0x86ab,0x86ac,0x86ad,0x86ae,0x86af, + 0x86b0,0x86b1,0x86b2,0x86b3,0x86b4,0x86b5,0x86b6,0x86b7, + 0x86b8,0x86b9,0x86ba,0x86bb,0x86bc,0x86bd,0x86be,0x86bf, + 0x86c0,0x86c1,0x86c2,0x86c3,0x86c4,0x86c5,0x86c6,0x86c7, + 0x86c8,0x86c9,0x86ca,0x86cb,0x86cc,0x86cd,0x86ce,0x86cf, + 0x86d0,0x86d1,0x86d2,0x86d3,0x86d4,0x86d5,0x86d6,0x86d7, + 0x86d8,0x86d9,0x86da,0x86db,0x86dc,0x86dd,0x86de,0x86df, + 0x86e0,0x86e1,0x86e2,0x86e3,0x86e4,0x86e5,0x86e6,0x86e7, + 0x86e8,0x86e9,0x86ea,0x86eb,0x86ec,0x86ed,0x86ee,0x86ef, + 0x86f0,0x86f1,0x86f2,0x86f3,0x86f4,0x86f5,0x86f6,0x86f7, + 0x86f8,0x86f9,0x86fa,0x86fb,0x86fc,0x86fd,0x86fe,0x86ff, + 0x8700,0x8701,0x8702,0x8703,0x8704,0x8705,0x8706,0x8707, + 0x8708,0x8709,0x870a,0x870b,0x870c,0x870d,0x870e,0x870f, + 0x8710,0x8711,0x8712,0x8713,0x8714,0x8715,0x8716,0x8717, + 0x8718,0x8719,0x871a,0x871b,0x871c,0x871d,0x871e,0x871f, + 0x8720,0x8721,0x8722,0x8723,0x8724,0x8725,0x8726,0x8727, + 0x8728,0x8729,0x872a,0x872b,0x872c,0x872d,0x872e,0x872f, + 0x8730,0x8731,0x8732,0x8733,0x8734,0x8735,0x8736,0x8737, + 0x8738,0x8739,0x873a,0x873b,0x873c,0x873d,0x873e,0x873f, + 0x8740,0x8741,0x8742,0x8743,0x8744,0x8745,0x8746,0x8747, + 0x8748,0x8749,0x874a,0x874b,0x874c,0x874d,0x874e,0x874f, + 0x8750,0x8751,0x8752,0x8753,0x8754,0x8755,0x8756,0x8757, + 0x8758,0x8759,0x875a,0x875b,0x875c,0x875d,0x875e,0x875f, + 0x8760,0x8761,0x8762,0x8763,0x8764,0x8765,0x8766,0x8767, + 0x8768,0x8769,0x876a,0x876b,0x876c,0x876d,0x876e,0x876f, + 0x8770,0x8771,0x8772,0x8773,0x8774,0x8775,0x8776,0x8777, + 0x8778,0x8779,0x877a,0x877b,0x877c,0x877d,0x877e,0x877f, + 0x8780,0x8781,0x8782,0x8783,0x8784,0x8785,0x8786,0x8787, + 0x8788,0x8789,0x878a,0x878b,0x878c,0x878d,0x878e,0x878f, + 0x8790,0x8791,0x8792,0x8793,0x8794,0x8795,0x8796,0x8797, + 0x8798,0x8799,0x879a,0x879b,0x879c,0x879d,0x879e,0x879f, + 0x87a0,0x87a1,0x87a2,0x87a3,0x87a4,0x87a5,0x87a6,0x87a7, + 0x87a8,0x87a9,0x87aa,0x87ab,0x87ac,0x87ad,0x87ae,0x87af, + 0x87b0,0x87b1,0x87b2,0x87b3,0x87b4,0x87b5,0x87b6,0x87b7, + 0x87b8,0x87b9,0x87ba,0x87bb,0x87bc,0x87bd,0x87be,0x87bf, + 0x87c0,0x87c1,0x87c2,0x87c3,0x87c4,0x87c5,0x87c6,0x87c7, + 0x87c8,0x87c9,0x87ca,0x87cb,0x87cc,0x87cd,0x87ce,0x87cf, + 0x87d0,0x87d1,0x87d2,0x87d3,0x87d4,0x87d5,0x87d6,0x87d7, + 0x87d8,0x87d9,0x87da,0x87db,0x87dc,0x87dd,0x87de,0x87df, + 0x87e0,0x87e1,0x87e2,0x87e3,0x87e4,0x87e5,0x87e6,0x87e7, + 0x87e8,0x87e9,0x87ea,0x87eb,0x87ec,0x87ed,0x87ee,0x87ef, + 0x87f0,0x87f1,0x87f2,0x87f3,0x87f4,0x87f5,0x87f6,0x87f7, + 0x87f8,0x87f9,0x87fa,0x87fb,0x87fc,0x87fd,0x87fe,0x87ff, + 0x8800,0x8801,0x8802,0x8803,0x8804,0x8805,0x8806,0x8807, + 0x8808,0x8809,0x880a,0x880b,0x880c,0x880d,0x880e,0x880f, + 0x8810,0x8811,0x8812,0x8813,0x8814,0x8815,0x8816,0x8817, + 0x8818,0x8819,0x881a,0x881b,0x881c,0x881d,0x881e,0x881f, + 0x8820,0x8821,0x8822,0x8823,0x8824,0x8825,0x8826,0x8827, + 0x8828,0x8829,0x882a,0x882b,0x882c,0x882d,0x882e,0x882f, + 0x8830,0x8831,0x8832,0x8833,0x8834,0x8835,0x8836,0x8837, + 0x8838,0x8839,0x883a,0x883b,0x883c,0x883d,0x883e,0x883f, + 0x8840,0x8841,0x8842,0x8843,0x8844,0x8845,0x8846,0x8847, + 0x8848,0x8849,0x884a,0x884b,0x884c,0x884d,0x884e,0x884f, + 0x8850,0x8851,0x8852,0x8853,0x8854,0x8855,0x8856,0x8857, + 0x8858,0x8859,0x885a,0x885b,0x885c,0x885d,0x885e,0x885f, + 0x8860,0x8861,0x8862,0x8863,0x8864,0x8865,0x8866,0x8867, + 0x8868,0x8869,0x886a,0x886b,0x886c,0x886d,0x886e,0x886f, + 0x8870,0x8871,0x8872,0x8873,0x8874,0x8875,0x8876,0x8877, + 0x8878,0x8879,0x887a,0x887b,0x887c,0x887d,0x887e,0x887f, + 0x8880,0x8881,0x8882,0x8883,0x8884,0x8885,0x8886,0x8887, + 0x8888,0x8889,0x888a,0x888b,0x888c,0x888d,0x888e,0x888f, + 0x8890,0x8891,0x8892,0x8893,0x8894,0x8895,0x8896,0x8897, + 0x8898,0x8899,0x889a,0x889b,0x889c,0x889d,0x889e,0x889f, + 0x88a0,0x88a1,0x88a2,0x88a3,0x88a4,0x88a5,0x88a6,0x88a7, + 0x88a8,0x88a9,0x88aa,0x88ab,0x88ac,0x88ad,0x88ae,0x88af, + 0x88b0,0x88b1,0x88b2,0x88b3,0x88b4,0x88b5,0x88b6,0x88b7, + 0x88b8,0x88b9,0x88ba,0x88bb,0x88bc,0x88bd,0x88be,0x88bf, + 0x88c0,0x88c1,0x88c2,0x88c3,0x88c4,0x88c5,0x88c6,0x88c7, + 0x88c8,0x88c9,0x88ca,0x88cb,0x88cc,0x88cd,0x88ce,0x88cf, + 0x88d0,0x88d1,0x88d2,0x88d3,0x88d4,0x88d5,0x88d6,0x88d7, + 0x88d8,0x88d9,0x88da,0x88db,0x88dc,0x88dd,0x88de,0x88df, + 0x88e0,0x88e1,0x88e2,0x88e3,0x88e4,0x88e5,0x88e6,0x88e7, + 0x88e8,0x88e9,0x88ea,0x88eb,0x88ec,0x88ed,0x88ee,0x88ef, + 0x88f0,0x88f1,0x88f2,0x88f3,0x88f4,0x88f5,0x88f6,0x88f7, + 0x88f8,0x88f9,0x88fa,0x88fb,0x88fc,0x88fd,0x88fe,0x88ff, + 0x8900,0x8901,0x8902,0x8903,0x8904,0x8905,0x8906,0x8907, + 0x8908,0x8909,0x890a,0x890b,0x890c,0x890d,0x890e,0x890f, + 0x8910,0x8911,0x8912,0x8913,0x8914,0x8915,0x8916,0x8917, + 0x8918,0x8919,0x891a,0x891b,0x891c,0x891d,0x891e,0x891f, + 0x8920,0x8921,0x8922,0x8923,0x8924,0x8925,0x8926,0x8927, + 0x8928,0x8929,0x892a,0x892b,0x892c,0x892d,0x892e,0x892f, + 0x8930,0x8931,0x8932,0x8933,0x8934,0x8935,0x8936,0x8937, + 0x8938,0x8939,0x893a,0x893b,0x893c,0x893d,0x893e,0x893f, + 0x8940,0x8941,0x8942,0x8943,0x8944,0x8945,0x8946,0x8947, + 0x8948,0x8949,0x894a,0x894b,0x894c,0x894d,0x894e,0x894f, + 0x8950,0x8951,0x8952,0x8953,0x8954,0x8955,0x8956,0x8957, + 0x8958,0x8959,0x895a,0x895b,0x895c,0x895d,0x895e,0x895f, + 0x8960,0x8961,0x8962,0x8963,0x8964,0x8965,0x8966,0x8967, + 0x8968,0x8969,0x896a,0x896b,0x896c,0x896d,0x896e,0x896f, + 0x8970,0x8971,0x8972,0x8973,0x8974,0x8975,0x8976,0x8977, + 0x8978,0x8979,0x897a,0x897b,0x897c,0x897d,0x897e,0x897f, + 0x8980,0x8981,0x8982,0x8983,0x8984,0x8985,0x8986,0x8987, + 0x8988,0x8989,0x898a,0x898b,0x898c,0x898d,0x898e,0x898f, + 0x8990,0x8991,0x8992,0x8993,0x8994,0x8995,0x8996,0x8997, + 0x8998,0x8999,0x899a,0x899b,0x899c,0x899d,0x899e,0x899f, + 0x89a0,0x89a1,0x89a2,0x89a3,0x89a4,0x89a5,0x89a6,0x89a7, + 0x89a8,0x89a9,0x89aa,0x89ab,0x89ac,0x89ad,0x89ae,0x89af, + 0x89b0,0x89b1,0x89b2,0x89b3,0x89b4,0x89b5,0x89b6,0x89b7, + 0x89b8,0x89b9,0x89ba,0x89bb,0x89bc,0x89bd,0x89be,0x89bf, + 0x89c0,0x89c1,0x89c2,0x89c3,0x89c4,0x89c5,0x89c6,0x89c7, + 0x89c8,0x89c9,0x89ca,0x89cb,0x89cc,0x89cd,0x89ce,0x89cf, + 0x89d0,0x89d1,0x89d2,0x89d3,0x89d4,0x89d5,0x89d6,0x89d7, + 0x89d8,0x89d9,0x89da,0x89db,0x89dc,0x89dd,0x89de,0x89df, + 0x89e0,0x89e1,0x89e2,0x89e3,0x89e4,0x89e5,0x89e6,0x89e7, + 0x89e8,0x89e9,0x89ea,0x89eb,0x89ec,0x89ed,0x89ee,0x89ef, + 0x89f0,0x89f1,0x89f2,0x89f3,0x89f4,0x89f5,0x89f6,0x89f7, + 0x89f8,0x89f9,0x89fa,0x89fb,0x89fc,0x89fd,0x89fe,0x89ff, + 0x8a00,0x8a01,0x8a02,0x8a03,0x8a04,0x8a05,0x8a06,0x8a07, + 0x8a08,0x8a09,0x8a0a,0x8a0b,0x8a0c,0x8a0d,0x8a0e,0x8a0f, + 0x8a10,0x8a11,0x8a12,0x8a13,0x8a14,0x8a15,0x8a16,0x8a17, + 0x8a18,0x8a19,0x8a1a,0x8a1b,0x8a1c,0x8a1d,0x8a1e,0x8a1f, + 0x8a20,0x8a21,0x8a22,0x8a23,0x8a24,0x8a25,0x8a26,0x8a27, + 0x8a28,0x8a29,0x8a2a,0x8a2b,0x8a2c,0x8a2d,0x8a2e,0x8a2f, + 0x8a30,0x8a31,0x8a32,0x8a33,0x8a34,0x8a35,0x8a36,0x8a37, + 0x8a38,0x8a39,0x8a3a,0x8a3b,0x8a3c,0x8a3d,0x8a3e,0x8a3f, + 0x8a40,0x8a41,0x8a42,0x8a43,0x8a44,0x8a45,0x8a46,0x8a47, + 0x8a48,0x8a49,0x8a4a,0x8a4b,0x8a4c,0x8a4d,0x8a4e,0x8a4f, + 0x8a50,0x8a51,0x8a52,0x8a53,0x8a54,0x8a55,0x8a56,0x8a57, + 0x8a58,0x8a59,0x8a5a,0x8a5b,0x8a5c,0x8a5d,0x8a5e,0x8a5f, + 0x8a60,0x8a61,0x8a62,0x8a63,0x8a64,0x8a65,0x8a66,0x8a67, + 0x8a68,0x8a69,0x8a6a,0x8a6b,0x8a6c,0x8a6d,0x8a6e,0x8a6f, + 0x8a70,0x8a71,0x8a72,0x8a73,0x8a74,0x8a75,0x8a76,0x8a77, + 0x8a78,0x8a79,0x8a7a,0x8a7b,0x8a7c,0x8a7d,0x8a7e,0x8a7f, + 0x8a80,0x8a81,0x8a82,0x8a83,0x8a84,0x8a85,0x8a86,0x8a87, + 0x8a88,0x8a89,0x8a8a,0x8a8b,0x8a8c,0x8a8d,0x8a8e,0x8a8f, + 0x8a90,0x8a91,0x8a92,0x8a93,0x8a94,0x8a95,0x8a96,0x8a97, + 0x8a98,0x8a99,0x8a9a,0x8a9b,0x8a9c,0x8a9d,0x8a9e,0x8a9f, + 0x8aa0,0x8aa1,0x8aa2,0x8aa3,0x8aa4,0x8aa5,0x8aa6,0x8aa7, + 0x8aa8,0x8aa9,0x8aaa,0x8aab,0x8aac,0x8aad,0x8aae,0x8aaf, + 0x8ab0,0x8ab1,0x8ab2,0x8ab3,0x8ab4,0x8ab5,0x8ab6,0x8ab7, + 0x8ab8,0x8ab9,0x8aba,0x8abb,0x8abc,0x8abd,0x8abe,0x8abf, + 0x8ac0,0x8ac1,0x8ac2,0x8ac3,0x8ac4,0x8ac5,0x8ac6,0x8ac7, + 0x8ac8,0x8ac9,0x8aca,0x8acb,0x8acc,0x8acd,0x8ace,0x8acf, + 0x8ad0,0x8ad1,0x8ad2,0x8ad3,0x8ad4,0x8ad5,0x8ad6,0x8ad7, + 0x8ad8,0x8ad9,0x8ada,0x8adb,0x8adc,0x8add,0x8ade,0x8adf, + 0x8ae0,0x8ae1,0x8ae2,0x8ae3,0x8ae4,0x8ae5,0x8ae6,0x8ae7, + 0x8ae8,0x8ae9,0x8aea,0x8aeb,0x8aec,0x8aed,0x8aee,0x8aef, + 0x8af0,0x8af1,0x8af2,0x8af3,0x8af4,0x8af5,0x8af6,0x8af7, + 0x8af8,0x8af9,0x8afa,0x8afb,0x8afc,0x8afd,0x8afe,0x8aff, + 0x8b00,0x8b01,0x8b02,0x8b03,0x8b04,0x8b05,0x8b06,0x8b07, + 0x8b08,0x8b09,0x8b0a,0x8b0b,0x8b0c,0x8b0d,0x8b0e,0x8b0f, + 0x8b10,0x8b11,0x8b12,0x8b13,0x8b14,0x8b15,0x8b16,0x8b17, + 0x8b18,0x8b19,0x8b1a,0x8b1b,0x8b1c,0x8b1d,0x8b1e,0x8b1f, + 0x8b20,0x8b21,0x8b22,0x8b23,0x8b24,0x8b25,0x8b26,0x8b27, + 0x8b28,0x8b29,0x8b2a,0x8b2b,0x8b2c,0x8b2d,0x8b2e,0x8b2f, + 0x8b30,0x8b31,0x8b32,0x8b33,0x8b34,0x8b35,0x8b36,0x8b37, + 0x8b38,0x8b39,0x8b3a,0x8b3b,0x8b3c,0x8b3d,0x8b3e,0x8b3f, + 0x8b40,0x8b41,0x8b42,0x8b43,0x8b44,0x8b45,0x8b46,0x8b47, + 0x8b48,0x8b49,0x8b4a,0x8b4b,0x8b4c,0x8b4d,0x8b4e,0x8b4f, + 0x8b50,0x8b51,0x8b52,0x8b53,0x8b54,0x8b55,0x8b56,0x8b57, + 0x8b58,0x8b59,0x8b5a,0x8b5b,0x8b5c,0x8b5d,0x8b5e,0x8b5f, + 0x8b60,0x8b61,0x8b62,0x8b63,0x8b64,0x8b65,0x8b66,0x8b67, + 0x8b68,0x8b69,0x8b6a,0x8b6b,0x8b6c,0x8b6d,0x8b6e,0x8b6f, + 0x8b70,0x8b71,0x8b72,0x8b73,0x8b74,0x8b75,0x8b76,0x8b77, + 0x8b78,0x8b79,0x8b7a,0x8b7b,0x8b7c,0x8b7d,0x8b7e,0x8b7f, + 0x8b80,0x8b81,0x8b82,0x8b83,0x8b84,0x8b85,0x8b86,0x8b87, + 0x8b88,0x8b89,0x8b8a,0x8b8b,0x8b8c,0x8b8d,0x8b8e,0x8b8f, + 0x8b90,0x8b91,0x8b92,0x8b93,0x8b94,0x8b95,0x8b96,0x8b97, + 0x8b98,0x8b99,0x8b9a,0x8b9b,0x8b9c,0x8b9d,0x8b9e,0x8b9f, + 0x8ba0,0x8ba1,0x8ba2,0x8ba3,0x8ba4,0x8ba5,0x8ba6,0x8ba7, + 0x8ba8,0x8ba9,0x8baa,0x8bab,0x8bac,0x8bad,0x8bae,0x8baf, + 0x8bb0,0x8bb1,0x8bb2,0x8bb3,0x8bb4,0x8bb5,0x8bb6,0x8bb7, + 0x8bb8,0x8bb9,0x8bba,0x8bbb,0x8bbc,0x8bbd,0x8bbe,0x8bbf, + 0x8bc0,0x8bc1,0x8bc2,0x8bc3,0x8bc4,0x8bc5,0x8bc6,0x8bc7, + 0x8bc8,0x8bc9,0x8bca,0x8bcb,0x8bcc,0x8bcd,0x8bce,0x8bcf, + 0x8bd0,0x8bd1,0x8bd2,0x8bd3,0x8bd4,0x8bd5,0x8bd6,0x8bd7, + 0x8bd8,0x8bd9,0x8bda,0x8bdb,0x8bdc,0x8bdd,0x8bde,0x8bdf, + 0x8be0,0x8be1,0x8be2,0x8be3,0x8be4,0x8be5,0x8be6,0x8be7, + 0x8be8,0x8be9,0x8bea,0x8beb,0x8bec,0x8bed,0x8bee,0x8bef, + 0x8bf0,0x8bf1,0x8bf2,0x8bf3,0x8bf4,0x8bf5,0x8bf6,0x8bf7, + 0x8bf8,0x8bf9,0x8bfa,0x8bfb,0x8bfc,0x8bfd,0x8bfe,0x8bff, + 0x8c00,0x8c01,0x8c02,0x8c03,0x8c04,0x8c05,0x8c06,0x8c07, + 0x8c08,0x8c09,0x8c0a,0x8c0b,0x8c0c,0x8c0d,0x8c0e,0x8c0f, + 0x8c10,0x8c11,0x8c12,0x8c13,0x8c14,0x8c15,0x8c16,0x8c17, + 0x8c18,0x8c19,0x8c1a,0x8c1b,0x8c1c,0x8c1d,0x8c1e,0x8c1f, + 0x8c20,0x8c21,0x8c22,0x8c23,0x8c24,0x8c25,0x8c26,0x8c27, + 0x8c28,0x8c29,0x8c2a,0x8c2b,0x8c2c,0x8c2d,0x8c2e,0x8c2f, + 0x8c30,0x8c31,0x8c32,0x8c33,0x8c34,0x8c35,0x8c36,0x8c37, + 0x8c38,0x8c39,0x8c3a,0x8c3b,0x8c3c,0x8c3d,0x8c3e,0x8c3f, + 0x8c40,0x8c41,0x8c42,0x8c43,0x8c44,0x8c45,0x8c46,0x8c47, + 0x8c48,0x8c49,0x8c4a,0x8c4b,0x8c4c,0x8c4d,0x8c4e,0x8c4f, + 0x8c50,0x8c51,0x8c52,0x8c53,0x8c54,0x8c55,0x8c56,0x8c57, + 0x8c58,0x8c59,0x8c5a,0x8c5b,0x8c5c,0x8c5d,0x8c5e,0x8c5f, + 0x8c60,0x8c61,0x8c62,0x8c63,0x8c64,0x8c65,0x8c66,0x8c67, + 0x8c68,0x8c69,0x8c6a,0x8c6b,0x8c6c,0x8c6d,0x8c6e,0x8c6f, + 0x8c70,0x8c71,0x8c72,0x8c73,0x8c74,0x8c75,0x8c76,0x8c77, + 0x8c78,0x8c79,0x8c7a,0x8c7b,0x8c7c,0x8c7d,0x8c7e,0x8c7f, + 0x8c80,0x8c81,0x8c82,0x8c83,0x8c84,0x8c85,0x8c86,0x8c87, + 0x8c88,0x8c89,0x8c8a,0x8c8b,0x8c8c,0x8c8d,0x8c8e,0x8c8f, + 0x8c90,0x8c91,0x8c92,0x8c93,0x8c94,0x8c95,0x8c96,0x8c97, + 0x8c98,0x8c99,0x8c9a,0x8c9b,0x8c9c,0x8c9d,0x8c9e,0x8c9f, + 0x8ca0,0x8ca1,0x8ca2,0x8ca3,0x8ca4,0x8ca5,0x8ca6,0x8ca7, + 0x8ca8,0x8ca9,0x8caa,0x8cab,0x8cac,0x8cad,0x8cae,0x8caf, + 0x8cb0,0x8cb1,0x8cb2,0x8cb3,0x8cb4,0x8cb5,0x8cb6,0x8cb7, + 0x8cb8,0x8cb9,0x8cba,0x8cbb,0x8cbc,0x8cbd,0x8cbe,0x8cbf, + 0x8cc0,0x8cc1,0x8cc2,0x8cc3,0x8cc4,0x8cc5,0x8cc6,0x8cc7, + 0x8cc8,0x8cc9,0x8cca,0x8ccb,0x8ccc,0x8ccd,0x8cce,0x8ccf, + 0x8cd0,0x8cd1,0x8cd2,0x8cd3,0x8cd4,0x8cd5,0x8cd6,0x8cd7, + 0x8cd8,0x8cd9,0x8cda,0x8cdb,0x8cdc,0x8cdd,0x8cde,0x8cdf, + 0x8ce0,0x8ce1,0x8ce2,0x8ce3,0x8ce4,0x8ce5,0x8ce6,0x8ce7, + 0x8ce8,0x8ce9,0x8cea,0x8ceb,0x8cec,0x8ced,0x8cee,0x8cef, + 0x8cf0,0x8cf1,0x8cf2,0x8cf3,0x8cf4,0x8cf5,0x8cf6,0x8cf7, + 0x8cf8,0x8cf9,0x8cfa,0x8cfb,0x8cfc,0x8cfd,0x8cfe,0x8cff, + 0x8d00,0x8d01,0x8d02,0x8d03,0x8d04,0x8d05,0x8d06,0x8d07, + 0x8d08,0x8d09,0x8d0a,0x8d0b,0x8d0c,0x8d0d,0x8d0e,0x8d0f, + 0x8d10,0x8d11,0x8d12,0x8d13,0x8d14,0x8d15,0x8d16,0x8d17, + 0x8d18,0x8d19,0x8d1a,0x8d1b,0x8d1c,0x8d1d,0x8d1e,0x8d1f, + 0x8d20,0x8d21,0x8d22,0x8d23,0x8d24,0x8d25,0x8d26,0x8d27, + 0x8d28,0x8d29,0x8d2a,0x8d2b,0x8d2c,0x8d2d,0x8d2e,0x8d2f, + 0x8d30,0x8d31,0x8d32,0x8d33,0x8d34,0x8d35,0x8d36,0x8d37, + 0x8d38,0x8d39,0x8d3a,0x8d3b,0x8d3c,0x8d3d,0x8d3e,0x8d3f, + 0x8d40,0x8d41,0x8d42,0x8d43,0x8d44,0x8d45,0x8d46,0x8d47, + 0x8d48,0x8d49,0x8d4a,0x8d4b,0x8d4c,0x8d4d,0x8d4e,0x8d4f, + 0x8d50,0x8d51,0x8d52,0x8d53,0x8d54,0x8d55,0x8d56,0x8d57, + 0x8d58,0x8d59,0x8d5a,0x8d5b,0x8d5c,0x8d5d,0x8d5e,0x8d5f, + 0x8d60,0x8d61,0x8d62,0x8d63,0x8d64,0x8d65,0x8d66,0x8d67, + 0x8d68,0x8d69,0x8d6a,0x8d6b,0x8d6c,0x8d6d,0x8d6e,0x8d6f, + 0x8d70,0x8d71,0x8d72,0x8d73,0x8d74,0x8d75,0x8d76,0x8d77, + 0x8d78,0x8d79,0x8d7a,0x8d7b,0x8d7c,0x8d7d,0x8d7e,0x8d7f, + 0x8d80,0x8d81,0x8d82,0x8d83,0x8d84,0x8d85,0x8d86,0x8d87, + 0x8d88,0x8d89,0x8d8a,0x8d8b,0x8d8c,0x8d8d,0x8d8e,0x8d8f, + 0x8d90,0x8d91,0x8d92,0x8d93,0x8d94,0x8d95,0x8d96,0x8d97, + 0x8d98,0x8d99,0x8d9a,0x8d9b,0x8d9c,0x8d9d,0x8d9e,0x8d9f, + 0x8da0,0x8da1,0x8da2,0x8da3,0x8da4,0x8da5,0x8da6,0x8da7, + 0x8da8,0x8da9,0x8daa,0x8dab,0x8dac,0x8dad,0x8dae,0x8daf, + 0x8db0,0x8db1,0x8db2,0x8db3,0x8db4,0x8db5,0x8db6,0x8db7, + 0x8db8,0x8db9,0x8dba,0x8dbb,0x8dbc,0x8dbd,0x8dbe,0x8dbf, + 0x8dc0,0x8dc1,0x8dc2,0x8dc3,0x8dc4,0x8dc5,0x8dc6,0x8dc7, + 0x8dc8,0x8dc9,0x8dca,0x8dcb,0x8dcc,0x8dcd,0x8dce,0x8dcf, + 0x8dd0,0x8dd1,0x8dd2,0x8dd3,0x8dd4,0x8dd5,0x8dd6,0x8dd7, + 0x8dd8,0x8dd9,0x8dda,0x8ddb,0x8ddc,0x8ddd,0x8dde,0x8ddf, + 0x8de0,0x8de1,0x8de2,0x8de3,0x8de4,0x8de5,0x8de6,0x8de7, + 0x8de8,0x8de9,0x8dea,0x8deb,0x8dec,0x8ded,0x8dee,0x8def, + 0x8df0,0x8df1,0x8df2,0x8df3,0x8df4,0x8df5,0x8df6,0x8df7, + 0x8df8,0x8df9,0x8dfa,0x8dfb,0x8dfc,0x8dfd,0x8dfe,0x8dff, + 0x8e00,0x8e01,0x8e02,0x8e03,0x8e04,0x8e05,0x8e06,0x8e07, + 0x8e08,0x8e09,0x8e0a,0x8e0b,0x8e0c,0x8e0d,0x8e0e,0x8e0f, + 0x8e10,0x8e11,0x8e12,0x8e13,0x8e14,0x8e15,0x8e16,0x8e17, + 0x8e18,0x8e19,0x8e1a,0x8e1b,0x8e1c,0x8e1d,0x8e1e,0x8e1f, + 0x8e20,0x8e21,0x8e22,0x8e23,0x8e24,0x8e25,0x8e26,0x8e27, + 0x8e28,0x8e29,0x8e2a,0x8e2b,0x8e2c,0x8e2d,0x8e2e,0x8e2f, + 0x8e30,0x8e31,0x8e32,0x8e33,0x8e34,0x8e35,0x8e36,0x8e37, + 0x8e38,0x8e39,0x8e3a,0x8e3b,0x8e3c,0x8e3d,0x8e3e,0x8e3f, + 0x8e40,0x8e41,0x8e42,0x8e43,0x8e44,0x8e45,0x8e46,0x8e47, + 0x8e48,0x8e49,0x8e4a,0x8e4b,0x8e4c,0x8e4d,0x8e4e,0x8e4f, + 0x8e50,0x8e51,0x8e52,0x8e53,0x8e54,0x8e55,0x8e56,0x8e57, + 0x8e58,0x8e59,0x8e5a,0x8e5b,0x8e5c,0x8e5d,0x8e5e,0x8e5f, + 0x8e60,0x8e61,0x8e62,0x8e63,0x8e64,0x8e65,0x8e66,0x8e67, + 0x8e68,0x8e69,0x8e6a,0x8e6b,0x8e6c,0x8e6d,0x8e6e,0x8e6f, + 0x8e70,0x8e71,0x8e72,0x8e73,0x8e74,0x8e75,0x8e76,0x8e77, + 0x8e78,0x8e79,0x8e7a,0x8e7b,0x8e7c,0x8e7d,0x8e7e,0x8e7f, + 0x8e80,0x8e81,0x8e82,0x8e83,0x8e84,0x8e85,0x8e86,0x8e87, + 0x8e88,0x8e89,0x8e8a,0x8e8b,0x8e8c,0x8e8d,0x8e8e,0x8e8f, + 0x8e90,0x8e91,0x8e92,0x8e93,0x8e94,0x8e95,0x8e96,0x8e97, + 0x8e98,0x8e99,0x8e9a,0x8e9b,0x8e9c,0x8e9d,0x8e9e,0x8e9f, + 0x8ea0,0x8ea1,0x8ea2,0x8ea3,0x8ea4,0x8ea5,0x8ea6,0x8ea7, + 0x8ea8,0x8ea9,0x8eaa,0x8eab,0x8eac,0x8ead,0x8eae,0x8eaf, + 0x8eb0,0x8eb1,0x8eb2,0x8eb3,0x8eb4,0x8eb5,0x8eb6,0x8eb7, + 0x8eb8,0x8eb9,0x8eba,0x8ebb,0x8ebc,0x8ebd,0x8ebe,0x8ebf, + 0x8ec0,0x8ec1,0x8ec2,0x8ec3,0x8ec4,0x8ec5,0x8ec6,0x8ec7, + 0x8ec8,0x8ec9,0x8eca,0x8ecb,0x8ecc,0x8ecd,0x8ece,0x8ecf, + 0x8ed0,0x8ed1,0x8ed2,0x8ed3,0x8ed4,0x8ed5,0x8ed6,0x8ed7, + 0x8ed8,0x8ed9,0x8eda,0x8edb,0x8edc,0x8edd,0x8ede,0x8edf, + 0x8ee0,0x8ee1,0x8ee2,0x8ee3,0x8ee4,0x8ee5,0x8ee6,0x8ee7, + 0x8ee8,0x8ee9,0x8eea,0x8eeb,0x8eec,0x8eed,0x8eee,0x8eef, + 0x8ef0,0x8ef1,0x8ef2,0x8ef3,0x8ef4,0x8ef5,0x8ef6,0x8ef7, + 0x8ef8,0x8ef9,0x8efa,0x8efb,0x8efc,0x8efd,0x8efe,0x8eff, + 0x8f00,0x8f01,0x8f02,0x8f03,0x8f04,0x8f05,0x8f06,0x8f07, + 0x8f08,0x8f09,0x8f0a,0x8f0b,0x8f0c,0x8f0d,0x8f0e,0x8f0f, + 0x8f10,0x8f11,0x8f12,0x8f13,0x8f14,0x8f15,0x8f16,0x8f17, + 0x8f18,0x8f19,0x8f1a,0x8f1b,0x8f1c,0x8f1d,0x8f1e,0x8f1f, + 0x8f20,0x8f21,0x8f22,0x8f23,0x8f24,0x8f25,0x8f26,0x8f27, + 0x8f28,0x8f29,0x8f2a,0x8f2b,0x8f2c,0x8f2d,0x8f2e,0x8f2f, + 0x8f30,0x8f31,0x8f32,0x8f33,0x8f34,0x8f35,0x8f36,0x8f37, + 0x8f38,0x8f39,0x8f3a,0x8f3b,0x8f3c,0x8f3d,0x8f3e,0x8f3f, + 0x8f40,0x8f41,0x8f42,0x8f43,0x8f44,0x8f45,0x8f46,0x8f47, + 0x8f48,0x8f49,0x8f4a,0x8f4b,0x8f4c,0x8f4d,0x8f4e,0x8f4f, + 0x8f50,0x8f51,0x8f52,0x8f53,0x8f54,0x8f55,0x8f56,0x8f57, + 0x8f58,0x8f59,0x8f5a,0x8f5b,0x8f5c,0x8f5d,0x8f5e,0x8f5f, + 0x8f60,0x8f61,0x8f62,0x8f63,0x8f64,0x8f65,0x8f66,0x8f67, + 0x8f68,0x8f69,0x8f6a,0x8f6b,0x8f6c,0x8f6d,0x8f6e,0x8f6f, + 0x8f70,0x8f71,0x8f72,0x8f73,0x8f74,0x8f75,0x8f76,0x8f77, + 0x8f78,0x8f79,0x8f7a,0x8f7b,0x8f7c,0x8f7d,0x8f7e,0x8f7f, + 0x8f80,0x8f81,0x8f82,0x8f83,0x8f84,0x8f85,0x8f86,0x8f87, + 0x8f88,0x8f89,0x8f8a,0x8f8b,0x8f8c,0x8f8d,0x8f8e,0x8f8f, + 0x8f90,0x8f91,0x8f92,0x8f93,0x8f94,0x8f95,0x8f96,0x8f97, + 0x8f98,0x8f99,0x8f9a,0x8f9b,0x8f9c,0x8f9d,0x8f9e,0x8f9f, + 0x8fa0,0x8fa1,0x8fa2,0x8fa3,0x8fa4,0x8fa5,0x8fa6,0x8fa7, + 0x8fa8,0x8fa9,0x8faa,0x8fab,0x8fac,0x8fad,0x8fae,0x8faf, + 0x8fb0,0x8fb1,0x8fb2,0x8fb3,0x8fb4,0x8fb5,0x8fb6,0x8fb7, + 0x8fb8,0x8fb9,0x8fba,0x8fbb,0x8fbc,0x8fbd,0x8fbe,0x8fbf, + 0x8fc0,0x8fc1,0x8fc2,0x8fc3,0x8fc4,0x8fc5,0x8fc6,0x8fc7, + 0x8fc8,0x8fc9,0x8fca,0x8fcb,0x8fcc,0x8fcd,0x8fce,0x8fcf, + 0x8fd0,0x8fd1,0x8fd2,0x8fd3,0x8fd4,0x8fd5,0x8fd6,0x8fd7, + 0x8fd8,0x8fd9,0x8fda,0x8fdb,0x8fdc,0x8fdd,0x8fde,0x8fdf, + 0x8fe0,0x8fe1,0x8fe2,0x8fe3,0x8fe4,0x8fe5,0x8fe6,0x8fe7, + 0x8fe8,0x8fe9,0x8fea,0x8feb,0x8fec,0x8fed,0x8fee,0x8fef, + 0x8ff0,0x8ff1,0x8ff2,0x8ff3,0x8ff4,0x8ff5,0x8ff6,0x8ff7, + 0x8ff8,0x8ff9,0x8ffa,0x8ffb,0x8ffc,0x8ffd,0x8ffe,0x8fff, + 0x9000,0x9001,0x9002,0x9003,0x9004,0x9005,0x9006,0x9007, + 0x9008,0x9009,0x900a,0x900b,0x900c,0x900d,0x900e,0x900f, + 0x9010,0x9011,0x9012,0x9013,0x9014,0x9015,0x9016,0x9017, + 0x9018,0x9019,0x901a,0x901b,0x901c,0x901d,0x901e,0x901f, + 0x9020,0x9021,0x9022,0x9023,0x9024,0x9025,0x9026,0x9027, + 0x9028,0x9029,0x902a,0x902b,0x902c,0x902d,0x902e,0x902f, + 0x9030,0x9031,0x9032,0x9033,0x9034,0x9035,0x9036,0x9037, + 0x9038,0x9039,0x903a,0x903b,0x903c,0x903d,0x903e,0x903f, + 0x9040,0x9041,0x9042,0x9043,0x9044,0x9045,0x9046,0x9047, + 0x9048,0x9049,0x904a,0x904b,0x904c,0x904d,0x904e,0x904f, + 0x9050,0x9051,0x9052,0x9053,0x9054,0x9055,0x9056,0x9057, + 0x9058,0x9059,0x905a,0x905b,0x905c,0x905d,0x905e,0x905f, + 0x9060,0x9061,0x9062,0x9063,0x9064,0x9065,0x9066,0x9067, + 0x9068,0x9069,0x906a,0x906b,0x906c,0x906d,0x906e,0x906f, + 0x9070,0x9071,0x9072,0x9073,0x9074,0x9075,0x9076,0x9077, + 0x9078,0x9079,0x907a,0x907b,0x907c,0x907d,0x907e,0x907f, + 0x9080,0x9081,0x9082,0x9083,0x9084,0x9085,0x9086,0x9087, + 0x9088,0x9089,0x908a,0x908b,0x908c,0x908d,0x908e,0x908f, + 0x9090,0x9091,0x9092,0x9093,0x9094,0x9095,0x9096,0x9097, + 0x9098,0x9099,0x909a,0x909b,0x909c,0x909d,0x909e,0x909f, + 0x90a0,0x90a1,0x90a2,0x90a3,0x90a4,0x90a5,0x90a6,0x90a7, + 0x90a8,0x90a9,0x90aa,0x90ab,0x90ac,0x90ad,0x90ae,0x90af, + 0x90b0,0x90b1,0x90b2,0x90b3,0x90b4,0x90b5,0x90b6,0x90b7, + 0x90b8,0x90b9,0x90ba,0x90bb,0x90bc,0x90bd,0x90be,0x90bf, + 0x90c0,0x90c1,0x90c2,0x90c3,0x90c4,0x90c5,0x90c6,0x90c7, + 0x90c8,0x90c9,0x90ca,0x90cb,0x90cc,0x90cd,0x90ce,0x90cf, + 0x90d0,0x90d1,0x90d2,0x90d3,0x90d4,0x90d5,0x90d6,0x90d7, + 0x90d8,0x90d9,0x90da,0x90db,0x90dc,0x90dd,0x90de,0x90df, + 0x90e0,0x90e1,0x90e2,0x90e3,0x90e4,0x90e5,0x90e6,0x90e7, + 0x90e8,0x90e9,0x90ea,0x90eb,0x90ec,0x90ed,0x90ee,0x90ef, + 0x90f0,0x90f1,0x90f2,0x90f3,0x90f4,0x90f5,0x90f6,0x90f7, + 0x90f8,0x90f9,0x90fa,0x90fb,0x90fc,0x90fd,0x90fe,0x90ff, + 0x9100,0x9101,0x9102,0x9103,0x9104,0x9105,0x9106,0x9107, + 0x9108,0x9109,0x910a,0x910b,0x910c,0x910d,0x910e,0x910f, + 0x9110,0x9111,0x9112,0x9113,0x9114,0x9115,0x9116,0x9117, + 0x9118,0x9119,0x911a,0x911b,0x911c,0x911d,0x911e,0x911f, + 0x9120,0x9121,0x9122,0x9123,0x9124,0x9125,0x9126,0x9127, + 0x9128,0x9129,0x912a,0x912b,0x912c,0x912d,0x912e,0x912f, + 0x9130,0x9131,0x9132,0x9133,0x9134,0x9135,0x9136,0x9137, + 0x9138,0x9139,0x913a,0x913b,0x913c,0x913d,0x913e,0x913f, + 0x9140,0x9141,0x9142,0x9143,0x9144,0x9145,0x9146,0x9147, + 0x9148,0x9149,0x914a,0x914b,0x914c,0x914d,0x914e,0x914f, + 0x9150,0x9151,0x9152,0x9153,0x9154,0x9155,0x9156,0x9157, + 0x9158,0x9159,0x915a,0x915b,0x915c,0x915d,0x915e,0x915f, + 0x9160,0x9161,0x9162,0x9163,0x9164,0x9165,0x9166,0x9167, + 0x9168,0x9169,0x916a,0x916b,0x916c,0x916d,0x916e,0x916f, + 0x9170,0x9171,0x9172,0x9173,0x9174,0x9175,0x9176,0x9177, + 0x9178,0x9179,0x917a,0x917b,0x917c,0x917d,0x917e,0x917f, + 0x9180,0x9181,0x9182,0x9183,0x9184,0x9185,0x9186,0x9187, + 0x9188,0x9189,0x918a,0x918b,0x918c,0x918d,0x918e,0x918f, + 0x9190,0x9191,0x9192,0x9193,0x9194,0x9195,0x9196,0x9197, + 0x9198,0x9199,0x919a,0x919b,0x919c,0x919d,0x919e,0x919f, + 0x91a0,0x91a1,0x91a2,0x91a3,0x91a4,0x91a5,0x91a6,0x91a7, + 0x91a8,0x91a9,0x91aa,0x91ab,0x91ac,0x91ad,0x91ae,0x91af, + 0x91b0,0x91b1,0x91b2,0x91b3,0x91b4,0x91b5,0x91b6,0x91b7, + 0x91b8,0x91b9,0x91ba,0x91bb,0x91bc,0x91bd,0x91be,0x91bf, + 0x91c0,0x91c1,0x91c2,0x91c3,0x91c4,0x91c5,0x91c6,0x91c7, + 0x91c8,0x91c9,0x91ca,0x91cb,0x91cc,0x91cd,0x91ce,0x91cf, + 0x91d0,0x91d1,0x91d2,0x91d3,0x91d4,0x91d5,0x91d6,0x91d7, + 0x91d8,0x91d9,0x91da,0x91db,0x91dc,0x91dd,0x91de,0x91df, + 0x91e0,0x91e1,0x91e2,0x91e3,0x91e4,0x91e5,0x91e6,0x91e7, + 0x91e8,0x91e9,0x91ea,0x91eb,0x91ec,0x91ed,0x91ee,0x91ef, + 0x91f0,0x91f1,0x91f2,0x91f3,0x91f4,0x91f5,0x91f6,0x91f7, + 0x91f8,0x91f9,0x91fa,0x91fb,0x91fc,0x91fd,0x91fe,0x91ff, + 0x9200,0x9201,0x9202,0x9203,0x9204,0x9205,0x9206,0x9207, + 0x9208,0x9209,0x920a,0x920b,0x920c,0x920d,0x920e,0x920f, + 0x9210,0x9211,0x9212,0x9213,0x9214,0x9215,0x9216,0x9217, + 0x9218,0x9219,0x921a,0x921b,0x921c,0x921d,0x921e,0x921f, + 0x9220,0x9221,0x9222,0x9223,0x9224,0x9225,0x9226,0x9227, + 0x9228,0x9229,0x922a,0x922b,0x922c,0x922d,0x922e,0x922f, + 0x9230,0x9231,0x9232,0x9233,0x9234,0x9235,0x9236,0x9237, + 0x9238,0x9239,0x923a,0x923b,0x923c,0x923d,0x923e,0x923f, + 0x9240,0x9241,0x9242,0x9243,0x9244,0x9245,0x9246,0x9247, + 0x9248,0x9249,0x924a,0x924b,0x924c,0x924d,0x924e,0x924f, + 0x9250,0x9251,0x9252,0x9253,0x9254,0x9255,0x9256,0x9257, + 0x9258,0x9259,0x925a,0x925b,0x925c,0x925d,0x925e,0x925f, + 0x9260,0x9261,0x9262,0x9263,0x9264,0x9265,0x9266,0x9267, + 0x9268,0x9269,0x926a,0x926b,0x926c,0x926d,0x926e,0x926f, + 0x9270,0x9271,0x9272,0x9273,0x9274,0x9275,0x9276,0x9277, + 0x9278,0x9279,0x927a,0x927b,0x927c,0x927d,0x927e,0x927f, + 0x9280,0x9281,0x9282,0x9283,0x9284,0x9285,0x9286,0x9287, + 0x9288,0x9289,0x928a,0x928b,0x928c,0x928d,0x928e,0x928f, + 0x9290,0x9291,0x9292,0x9293,0x9294,0x9295,0x9296,0x9297, + 0x9298,0x9299,0x929a,0x929b,0x929c,0x929d,0x929e,0x929f, + 0x92a0,0x92a1,0x92a2,0x92a3,0x92a4,0x92a5,0x92a6,0x92a7, + 0x92a8,0x92a9,0x92aa,0x92ab,0x92ac,0x92ad,0x92ae,0x92af, + 0x92b0,0x92b1,0x92b2,0x92b3,0x92b4,0x92b5,0x92b6,0x92b7, + 0x92b8,0x92b9,0x92ba,0x92bb,0x92bc,0x92bd,0x92be,0x92bf, + 0x92c0,0x92c1,0x92c2,0x92c3,0x92c4,0x92c5,0x92c6,0x92c7, + 0x92c8,0x92c9,0x92ca,0x92cb,0x92cc,0x92cd,0x92ce,0x92cf, + 0x92d0,0x92d1,0x92d2,0x92d3,0x92d4,0x92d5,0x92d6,0x92d7, + 0x92d8,0x92d9,0x92da,0x92db,0x92dc,0x92dd,0x92de,0x92df, + 0x92e0,0x92e1,0x92e2,0x92e3,0x92e4,0x92e5,0x92e6,0x92e7, + 0x92e8,0x92e9,0x92ea,0x92eb,0x92ec,0x92ed,0x92ee,0x92ef, + 0x92f0,0x92f1,0x92f2,0x92f3,0x92f4,0x92f5,0x92f6,0x92f7, + 0x92f8,0x92f9,0x92fa,0x92fb,0x92fc,0x92fd,0x92fe,0x92ff, + 0x9300,0x9301,0x9302,0x9303,0x9304,0x9305,0x9306,0x9307, + 0x9308,0x9309,0x930a,0x930b,0x930c,0x930d,0x930e,0x930f, + 0x9310,0x9311,0x9312,0x9313,0x9314,0x9315,0x9316,0x9317, + 0x9318,0x9319,0x931a,0x931b,0x931c,0x931d,0x931e,0x931f, + 0x9320,0x9321,0x9322,0x9323,0x9324,0x9325,0x9326,0x9327, + 0x9328,0x9329,0x932a,0x932b,0x932c,0x932d,0x932e,0x932f, + 0x9330,0x9331,0x9332,0x9333,0x9334,0x9335,0x9336,0x9337, + 0x9338,0x9339,0x933a,0x933b,0x933c,0x933d,0x933e,0x933f, + 0x9340,0x9341,0x9342,0x9343,0x9344,0x9345,0x9346,0x9347, + 0x9348,0x9349,0x934a,0x934b,0x934c,0x934d,0x934e,0x934f, + 0x9350,0x9351,0x9352,0x9353,0x9354,0x9355,0x9356,0x9357, + 0x9358,0x9359,0x935a,0x935b,0x935c,0x935d,0x935e,0x935f, + 0x9360,0x9361,0x9362,0x9363,0x9364,0x9365,0x9366,0x9367, + 0x9368,0x9369,0x936a,0x936b,0x936c,0x936d,0x936e,0x936f, + 0x9370,0x9371,0x9372,0x9373,0x9374,0x9375,0x9376,0x9377, + 0x9378,0x9379,0x937a,0x937b,0x937c,0x937d,0x937e,0x937f, + 0x9380,0x9381,0x9382,0x9383,0x9384,0x9385,0x9386,0x9387, + 0x9388,0x9389,0x938a,0x938b,0x938c,0x938d,0x938e,0x938f, + 0x9390,0x9391,0x9392,0x9393,0x9394,0x9395,0x9396,0x9397, + 0x9398,0x9399,0x939a,0x939b,0x939c,0x939d,0x939e,0x939f, + 0x93a0,0x93a1,0x93a2,0x93a3,0x93a4,0x93a5,0x93a6,0x93a7, + 0x93a8,0x93a9,0x93aa,0x93ab,0x93ac,0x93ad,0x93ae,0x93af, + 0x93b0,0x93b1,0x93b2,0x93b3,0x93b4,0x93b5,0x93b6,0x93b7, + 0x93b8,0x93b9,0x93ba,0x93bb,0x93bc,0x93bd,0x93be,0x93bf, + 0x93c0,0x93c1,0x93c2,0x93c3,0x93c4,0x93c5,0x93c6,0x93c7, + 0x93c8,0x93c9,0x93ca,0x93cb,0x93cc,0x93cd,0x93ce,0x93cf, + 0x93d0,0x93d1,0x93d2,0x93d3,0x93d4,0x93d5,0x93d6,0x93d7, + 0x93d8,0x93d9,0x93da,0x93db,0x93dc,0x93dd,0x93de,0x93df, + 0x93e0,0x93e1,0x93e2,0x93e3,0x93e4,0x93e5,0x93e6,0x93e7, + 0x93e8,0x93e9,0x93ea,0x93eb,0x93ec,0x93ed,0x93ee,0x93ef, + 0x93f0,0x93f1,0x93f2,0x93f3,0x93f4,0x93f5,0x93f6,0x93f7, + 0x93f8,0x93f9,0x93fa,0x93fb,0x93fc,0x93fd,0x93fe,0x93ff, + 0x9400,0x9401,0x9402,0x9403,0x9404,0x9405,0x9406,0x9407, + 0x9408,0x9409,0x940a,0x940b,0x940c,0x940d,0x940e,0x940f, + 0x9410,0x9411,0x9412,0x9413,0x9414,0x9415,0x9416,0x9417, + 0x9418,0x9419,0x941a,0x941b,0x941c,0x941d,0x941e,0x941f, + 0x9420,0x9421,0x9422,0x9423,0x9424,0x9425,0x9426,0x9427, + 0x9428,0x9429,0x942a,0x942b,0x942c,0x942d,0x942e,0x942f, + 0x9430,0x9431,0x9432,0x9433,0x9434,0x9435,0x9436,0x9437, + 0x9438,0x9439,0x943a,0x943b,0x943c,0x943d,0x943e,0x943f, + 0x9440,0x9441,0x9442,0x9443,0x9444,0x9445,0x9446,0x9447, + 0x9448,0x9449,0x944a,0x944b,0x944c,0x944d,0x944e,0x944f, + 0x9450,0x9451,0x9452,0x9453,0x9454,0x9455,0x9456,0x9457, + 0x9458,0x9459,0x945a,0x945b,0x945c,0x945d,0x945e,0x945f, + 0x9460,0x9461,0x9462,0x9463,0x9464,0x9465,0x9466,0x9467, + 0x9468,0x9469,0x946a,0x946b,0x946c,0x946d,0x946e,0x946f, + 0x9470,0x9471,0x9472,0x9473,0x9474,0x9475,0x9476,0x9477, + 0x9478,0x9479,0x947a,0x947b,0x947c,0x947d,0x947e,0x947f, + 0x9480,0x9481,0x9482,0x9483,0x9484,0x9485,0x9486,0x9487, + 0x9488,0x9489,0x948a,0x948b,0x948c,0x948d,0x948e,0x948f, + 0x9490,0x9491,0x9492,0x9493,0x9494,0x9495,0x9496,0x9497, + 0x9498,0x9499,0x949a,0x949b,0x949c,0x949d,0x949e,0x949f, + 0x94a0,0x94a1,0x94a2,0x94a3,0x94a4,0x94a5,0x94a6,0x94a7, + 0x94a8,0x94a9,0x94aa,0x94ab,0x94ac,0x94ad,0x94ae,0x94af, + 0x94b0,0x94b1,0x94b2,0x94b3,0x94b4,0x94b5,0x94b6,0x94b7, + 0x94b8,0x94b9,0x94ba,0x94bb,0x94bc,0x94bd,0x94be,0x94bf, + 0x94c0,0x94c1,0x94c2,0x94c3,0x94c4,0x94c5,0x94c6,0x94c7, + 0x94c8,0x94c9,0x94ca,0x94cb,0x94cc,0x94cd,0x94ce,0x94cf, + 0x94d0,0x94d1,0x94d2,0x94d3,0x94d4,0x94d5,0x94d6,0x94d7, + 0x94d8,0x94d9,0x94da,0x94db,0x94dc,0x94dd,0x94de,0x94df, + 0x94e0,0x94e1,0x94e2,0x94e3,0x94e4,0x94e5,0x94e6,0x94e7, + 0x94e8,0x94e9,0x94ea,0x94eb,0x94ec,0x94ed,0x94ee,0x94ef, + 0x94f0,0x94f1,0x94f2,0x94f3,0x94f4,0x94f5,0x94f6,0x94f7, + 0x94f8,0x94f9,0x94fa,0x94fb,0x94fc,0x94fd,0x94fe,0x94ff, + 0x9500,0x9501,0x9502,0x9503,0x9504,0x9505,0x9506,0x9507, + 0x9508,0x9509,0x950a,0x950b,0x950c,0x950d,0x950e,0x950f, + 0x9510,0x9511,0x9512,0x9513,0x9514,0x9515,0x9516,0x9517, + 0x9518,0x9519,0x951a,0x951b,0x951c,0x951d,0x951e,0x951f, + 0x9520,0x9521,0x9522,0x9523,0x9524,0x9525,0x9526,0x9527, + 0x9528,0x9529,0x952a,0x952b,0x952c,0x952d,0x952e,0x952f, + 0x9530,0x9531,0x9532,0x9533,0x9534,0x9535,0x9536,0x9537, + 0x9538,0x9539,0x953a,0x953b,0x953c,0x953d,0x953e,0x953f, + 0x9540,0x9541,0x9542,0x9543,0x9544,0x9545,0x9546,0x9547, + 0x9548,0x9549,0x954a,0x954b,0x954c,0x954d,0x954e,0x954f, + 0x9550,0x9551,0x9552,0x9553,0x9554,0x9555,0x9556,0x9557, + 0x9558,0x9559,0x955a,0x955b,0x955c,0x955d,0x955e,0x955f, + 0x9560,0x9561,0x9562,0x9563,0x9564,0x9565,0x9566,0x9567, + 0x9568,0x9569,0x956a,0x956b,0x956c,0x956d,0x956e,0x956f, + 0x9570,0x9571,0x9572,0x9573,0x9574,0x9575,0x9576,0x9577, + 0x9578,0x9579,0x957a,0x957b,0x957c,0x957d,0x957e,0x957f, + 0x9580,0x9581,0x9582,0x9583,0x9584,0x9585,0x9586,0x9587, + 0x9588,0x9589,0x958a,0x958b,0x958c,0x958d,0x958e,0x958f, + 0x9590,0x9591,0x9592,0x9593,0x9594,0x9595,0x9596,0x9597, + 0x9598,0x9599,0x959a,0x959b,0x959c,0x959d,0x959e,0x959f, + 0x95a0,0x95a1,0x95a2,0x95a3,0x95a4,0x95a5,0x95a6,0x95a7, + 0x95a8,0x95a9,0x95aa,0x95ab,0x95ac,0x95ad,0x95ae,0x95af, + 0x95b0,0x95b1,0x95b2,0x95b3,0x95b4,0x95b5,0x95b6,0x95b7, + 0x95b8,0x95b9,0x95ba,0x95bb,0x95bc,0x95bd,0x95be,0x95bf, + 0x95c0,0x95c1,0x95c2,0x95c3,0x95c4,0x95c5,0x95c6,0x95c7, + 0x95c8,0x95c9,0x95ca,0x95cb,0x95cc,0x95cd,0x95ce,0x95cf, + 0x95d0,0x95d1,0x95d2,0x95d3,0x95d4,0x95d5,0x95d6,0x95d7, + 0x95d8,0x95d9,0x95da,0x95db,0x95dc,0x95dd,0x95de,0x95df, + 0x95e0,0x95e1,0x95e2,0x95e3,0x95e4,0x95e5,0x95e6,0x95e7, + 0x95e8,0x95e9,0x95ea,0x95eb,0x95ec,0x95ed,0x95ee,0x95ef, + 0x95f0,0x95f1,0x95f2,0x95f3,0x95f4,0x95f5,0x95f6,0x95f7, + 0x95f8,0x95f9,0x95fa,0x95fb,0x95fc,0x95fd,0x95fe,0x95ff, + 0x9600,0x9601,0x9602,0x9603,0x9604,0x9605,0x9606,0x9607, + 0x9608,0x9609,0x960a,0x960b,0x960c,0x960d,0x960e,0x960f, + 0x9610,0x9611,0x9612,0x9613,0x9614,0x9615,0x9616,0x9617, + 0x9618,0x9619,0x961a,0x961b,0x961c,0x961d,0x961e,0x961f, + 0x9620,0x9621,0x9622,0x9623,0x9624,0x9625,0x9626,0x9627, + 0x9628,0x9629,0x962a,0x962b,0x962c,0x962d,0x962e,0x962f, + 0x9630,0x9631,0x9632,0x9633,0x9634,0x9635,0x9636,0x9637, + 0x9638,0x9639,0x963a,0x963b,0x963c,0x963d,0x963e,0x963f, + 0x9640,0x9641,0x9642,0x9643,0x9644,0x9645,0x9646,0x9647, + 0x9648,0x9649,0x964a,0x964b,0x964c,0x964d,0x964e,0x964f, + 0x9650,0x9651,0x9652,0x9653,0x9654,0x9655,0x9656,0x9657, + 0x9658,0x9659,0x965a,0x965b,0x965c,0x965d,0x965e,0x965f, + 0x9660,0x9661,0x9662,0x9663,0x9664,0x9665,0x9666,0x9667, + 0x9668,0x9669,0x966a,0x966b,0x966c,0x966d,0x966e,0x966f, + 0x9670,0x9671,0x9672,0x9673,0x9674,0x9675,0x9676,0x9677, + 0x9678,0x9679,0x967a,0x967b,0x967c,0x967d,0x967e,0x967f, + 0x9680,0x9681,0x9682,0x9683,0x9684,0x9685,0x9686,0x9687, + 0x9688,0x9689,0x968a,0x968b,0x968c,0x968d,0x968e,0x968f, + 0x9690,0x9691,0x9692,0x9693,0x9694,0x9695,0x9696,0x9697, + 0x9698,0x9699,0x969a,0x969b,0x969c,0x969d,0x969e,0x969f, + 0x96a0,0x96a1,0x96a2,0x96a3,0x96a4,0x96a5,0x96a6,0x96a7, + 0x96a8,0x96a9,0x96aa,0x96ab,0x96ac,0x96ad,0x96ae,0x96af, + 0x96b0,0x96b1,0x96b2,0x96b3,0x96b4,0x96b5,0x96b6,0x96b7, + 0x96b8,0x96b9,0x96ba,0x96bb,0x96bc,0x96bd,0x96be,0x96bf, + 0x96c0,0x96c1,0x96c2,0x96c3,0x96c4,0x96c5,0x96c6,0x96c7, + 0x96c8,0x96c9,0x96ca,0x96cb,0x96cc,0x96cd,0x96ce,0x96cf, + 0x96d0,0x96d1,0x96d2,0x96d3,0x96d4,0x96d5,0x96d6,0x96d7, + 0x96d8,0x96d9,0x96da,0x96db,0x96dc,0x96dd,0x96de,0x96df, + 0x96e0,0x96e1,0x96e2,0x96e3,0x96e4,0x96e5,0x96e6,0x96e7, + 0x96e8,0x96e9,0x96ea,0x96eb,0x96ec,0x96ed,0x96ee,0x96ef, + 0x96f0,0x96f1,0x96f2,0x96f3,0x96f4,0x96f5,0x96f6,0x96f7, + 0x96f8,0x96f9,0x96fa,0x96fb,0x96fc,0x96fd,0x96fe,0x96ff, + 0x9700,0x9701,0x9702,0x9703,0x9704,0x9705,0x9706,0x9707, + 0x9708,0x9709,0x970a,0x970b,0x970c,0x970d,0x970e,0x970f, + 0x9710,0x9711,0x9712,0x9713,0x9714,0x9715,0x9716,0x9717, + 0x9718,0x9719,0x971a,0x971b,0x971c,0x971d,0x971e,0x971f, + 0x9720,0x9721,0x9722,0x9723,0x9724,0x9725,0x9726,0x9727, + 0x9728,0x9729,0x972a,0x972b,0x972c,0x972d,0x972e,0x972f, + 0x9730,0x9731,0x9732,0x9733,0x9734,0x9735,0x9736,0x9737, + 0x9738,0x9739,0x973a,0x973b,0x973c,0x973d,0x973e,0x973f, + 0x9740,0x9741,0x9742,0x9743,0x9744,0x9745,0x9746,0x9747, + 0x9748,0x9749,0x974a,0x974b,0x974c,0x974d,0x974e,0x974f, + 0x9750,0x9751,0x9752,0x9753,0x9754,0x9755,0x9756,0x9757, + 0x9758,0x9759,0x975a,0x975b,0x975c,0x975d,0x975e,0x975f, + 0x9760,0x9761,0x9762,0x9763,0x9764,0x9765,0x9766,0x9767, + 0x9768,0x9769,0x976a,0x976b,0x976c,0x976d,0x976e,0x976f, + 0x9770,0x9771,0x9772,0x9773,0x9774,0x9775,0x9776,0x9777, + 0x9778,0x9779,0x977a,0x977b,0x977c,0x977d,0x977e,0x977f, + 0x9780,0x9781,0x9782,0x9783,0x9784,0x9785,0x9786,0x9787, + 0x9788,0x9789,0x978a,0x978b,0x978c,0x978d,0x978e,0x978f, + 0x9790,0x9791,0x9792,0x9793,0x9794,0x9795,0x9796,0x9797, + 0x9798,0x9799,0x979a,0x979b,0x979c,0x979d,0x979e,0x979f, + 0x97a0,0x97a1,0x97a2,0x97a3,0x97a4,0x97a5,0x97a6,0x97a7, + 0x97a8,0x97a9,0x97aa,0x97ab,0x97ac,0x97ad,0x97ae,0x97af, + 0x97b0,0x97b1,0x97b2,0x97b3,0x97b4,0x97b5,0x97b6,0x97b7, + 0x97b8,0x97b9,0x97ba,0x97bb,0x97bc,0x97bd,0x97be,0x97bf, + 0x97c0,0x97c1,0x97c2,0x97c3,0x97c4,0x97c5,0x97c6,0x97c7, + 0x97c8,0x97c9,0x97ca,0x97cb,0x97cc,0x97cd,0x97ce,0x97cf, + 0x97d0,0x97d1,0x97d2,0x97d3,0x97d4,0x97d5,0x97d6,0x97d7, + 0x97d8,0x97d9,0x97da,0x97db,0x97dc,0x97dd,0x97de,0x97df, + 0x97e0,0x97e1,0x97e2,0x97e3,0x97e4,0x97e5,0x97e6,0x97e7, + 0x97e8,0x97e9,0x97ea,0x97eb,0x97ec,0x97ed,0x97ee,0x97ef, + 0x97f0,0x97f1,0x97f2,0x97f3,0x97f4,0x97f5,0x97f6,0x97f7, + 0x97f8,0x97f9,0x97fa,0x97fb,0x97fc,0x97fd,0x97fe,0x97ff, + 0x9800,0x9801,0x9802,0x9803,0x9804,0x9805,0x9806,0x9807, + 0x9808,0x9809,0x980a,0x980b,0x980c,0x980d,0x980e,0x980f, + 0x9810,0x9811,0x9812,0x9813,0x9814,0x9815,0x9816,0x9817, + 0x9818,0x9819,0x981a,0x981b,0x981c,0x981d,0x981e,0x981f, + 0x9820,0x9821,0x9822,0x9823,0x9824,0x9825,0x9826,0x9827, + 0x9828,0x9829,0x982a,0x982b,0x982c,0x982d,0x982e,0x982f, + 0x9830,0x9831,0x9832,0x9833,0x9834,0x9835,0x9836,0x9837, + 0x9838,0x9839,0x983a,0x983b,0x983c,0x983d,0x983e,0x983f, + 0x9840,0x9841,0x9842,0x9843,0x9844,0x9845,0x9846,0x9847, + 0x9848,0x9849,0x984a,0x984b,0x984c,0x984d,0x984e,0x984f, + 0x9850,0x9851,0x9852,0x9853,0x9854,0x9855,0x9856,0x9857, + 0x9858,0x9859,0x985a,0x985b,0x985c,0x985d,0x985e,0x985f, + 0x9860,0x9861,0x9862,0x9863,0x9864,0x9865,0x9866,0x9867, + 0x9868,0x9869,0x986a,0x986b,0x986c,0x986d,0x986e,0x986f, + 0x9870,0x9871,0x9872,0x9873,0x9874,0x9875,0x9876,0x9877, + 0x9878,0x9879,0x987a,0x987b,0x987c,0x987d,0x987e,0x987f, + 0x9880,0x9881,0x9882,0x9883,0x9884,0x9885,0x9886,0x9887, + 0x9888,0x9889,0x988a,0x988b,0x988c,0x988d,0x988e,0x988f, + 0x9890,0x9891,0x9892,0x9893,0x9894,0x9895,0x9896,0x9897, + 0x9898,0x9899,0x989a,0x989b,0x989c,0x989d,0x989e,0x989f, + 0x98a0,0x98a1,0x98a2,0x98a3,0x98a4,0x98a5,0x98a6,0x98a7, + 0x98a8,0x98a9,0x98aa,0x98ab,0x98ac,0x98ad,0x98ae,0x98af, + 0x98b0,0x98b1,0x98b2,0x98b3,0x98b4,0x98b5,0x98b6,0x98b7, + 0x98b8,0x98b9,0x98ba,0x98bb,0x98bc,0x98bd,0x98be,0x98bf, + 0x98c0,0x98c1,0x98c2,0x98c3,0x98c4,0x98c5,0x98c6,0x98c7, + 0x98c8,0x98c9,0x98ca,0x98cb,0x98cc,0x98cd,0x98ce,0x98cf, + 0x98d0,0x98d1,0x98d2,0x98d3,0x98d4,0x98d5,0x98d6,0x98d7, + 0x98d8,0x98d9,0x98da,0x98db,0x98dc,0x98dd,0x98de,0x98df, + 0x98e0,0x98e1,0x98e2,0x98e3,0x98e4,0x98e5,0x98e6,0x98e7, + 0x98e8,0x98e9,0x98ea,0x98eb,0x98ec,0x98ed,0x98ee,0x98ef, + 0x98f0,0x98f1,0x98f2,0x98f3,0x98f4,0x98f5,0x98f6,0x98f7, + 0x98f8,0x98f9,0x98fa,0x98fb,0x98fc,0x98fd,0x98fe,0x98ff, + 0x9900,0x9901,0x9902,0x9903,0x9904,0x9905,0x9906,0x9907, + 0x9908,0x9909,0x990a,0x990b,0x990c,0x990d,0x990e,0x990f, + 0x9910,0x9911,0x9912,0x9913,0x9914,0x9915,0x9916,0x9917, + 0x9918,0x9919,0x991a,0x991b,0x991c,0x991d,0x991e,0x991f, + 0x9920,0x9921,0x9922,0x9923,0x9924,0x9925,0x9926,0x9927, + 0x9928,0x9929,0x992a,0x992b,0x992c,0x992d,0x992e,0x992f, + 0x9930,0x9931,0x9932,0x9933,0x9934,0x9935,0x9936,0x9937, + 0x9938,0x9939,0x993a,0x993b,0x993c,0x993d,0x993e,0x993f, + 0x9940,0x9941,0x9942,0x9943,0x9944,0x9945,0x9946,0x9947, + 0x9948,0x9949,0x994a,0x994b,0x994c,0x994d,0x994e,0x994f, + 0x9950,0x9951,0x9952,0x9953,0x9954,0x9955,0x9956,0x9957, + 0x9958,0x9959,0x995a,0x995b,0x995c,0x995d,0x995e,0x995f, + 0x9960,0x9961,0x9962,0x9963,0x9964,0x9965,0x9966,0x9967, + 0x9968,0x9969,0x996a,0x996b,0x996c,0x996d,0x996e,0x996f, + 0x9970,0x9971,0x9972,0x9973,0x9974,0x9975,0x9976,0x9977, + 0x9978,0x9979,0x997a,0x997b,0x997c,0x997d,0x997e,0x997f, + 0x9980,0x9981,0x9982,0x9983,0x9984,0x9985,0x9986,0x9987, + 0x9988,0x9989,0x998a,0x998b,0x998c,0x998d,0x998e,0x998f, + 0x9990,0x9991,0x9992,0x9993,0x9994,0x9995,0x9996,0x9997, + 0x9998,0x9999,0x999a,0x999b,0x999c,0x999d,0x999e,0x999f, + 0x99a0,0x99a1,0x99a2,0x99a3,0x99a4,0x99a5,0x99a6,0x99a7, + 0x99a8,0x99a9,0x99aa,0x99ab,0x99ac,0x99ad,0x99ae,0x99af, + 0x99b0,0x99b1,0x99b2,0x99b3,0x99b4,0x99b5,0x99b6,0x99b7, + 0x99b8,0x99b9,0x99ba,0x99bb,0x99bc,0x99bd,0x99be,0x99bf, + 0x99c0,0x99c1,0x99c2,0x99c3,0x99c4,0x99c5,0x99c6,0x99c7, + 0x99c8,0x99c9,0x99ca,0x99cb,0x99cc,0x99cd,0x99ce,0x99cf, + 0x99d0,0x99d1,0x99d2,0x99d3,0x99d4,0x99d5,0x99d6,0x99d7, + 0x99d8,0x99d9,0x99da,0x99db,0x99dc,0x99dd,0x99de,0x99df, + 0x99e0,0x99e1,0x99e2,0x99e3,0x99e4,0x99e5,0x99e6,0x99e7, + 0x99e8,0x99e9,0x99ea,0x99eb,0x99ec,0x99ed,0x99ee,0x99ef, + 0x99f0,0x99f1,0x99f2,0x99f3,0x99f4,0x99f5,0x99f6,0x99f7, + 0x99f8,0x99f9,0x99fa,0x99fb,0x99fc,0x99fd,0x99fe,0x99ff, + 0x9a00,0x9a01,0x9a02,0x9a03,0x9a04,0x9a05,0x9a06,0x9a07, + 0x9a08,0x9a09,0x9a0a,0x9a0b,0x9a0c,0x9a0d,0x9a0e,0x9a0f, + 0x9a10,0x9a11,0x9a12,0x9a13,0x9a14,0x9a15,0x9a16,0x9a17, + 0x9a18,0x9a19,0x9a1a,0x9a1b,0x9a1c,0x9a1d,0x9a1e,0x9a1f, + 0x9a20,0x9a21,0x9a22,0x9a23,0x9a24,0x9a25,0x9a26,0x9a27, + 0x9a28,0x9a29,0x9a2a,0x9a2b,0x9a2c,0x9a2d,0x9a2e,0x9a2f, + 0x9a30,0x9a31,0x9a32,0x9a33,0x9a34,0x9a35,0x9a36,0x9a37, + 0x9a38,0x9a39,0x9a3a,0x9a3b,0x9a3c,0x9a3d,0x9a3e,0x9a3f, + 0x9a40,0x9a41,0x9a42,0x9a43,0x9a44,0x9a45,0x9a46,0x9a47, + 0x9a48,0x9a49,0x9a4a,0x9a4b,0x9a4c,0x9a4d,0x9a4e,0x9a4f, + 0x9a50,0x9a51,0x9a52,0x9a53,0x9a54,0x9a55,0x9a56,0x9a57, + 0x9a58,0x9a59,0x9a5a,0x9a5b,0x9a5c,0x9a5d,0x9a5e,0x9a5f, + 0x9a60,0x9a61,0x9a62,0x9a63,0x9a64,0x9a65,0x9a66,0x9a67, + 0x9a68,0x9a69,0x9a6a,0x9a6b,0x9a6c,0x9a6d,0x9a6e,0x9a6f, + 0x9a70,0x9a71,0x9a72,0x9a73,0x9a74,0x9a75,0x9a76,0x9a77, + 0x9a78,0x9a79,0x9a7a,0x9a7b,0x9a7c,0x9a7d,0x9a7e,0x9a7f, + 0x9a80,0x9a81,0x9a82,0x9a83,0x9a84,0x9a85,0x9a86,0x9a87, + 0x9a88,0x9a89,0x9a8a,0x9a8b,0x9a8c,0x9a8d,0x9a8e,0x9a8f, + 0x9a90,0x9a91,0x9a92,0x9a93,0x9a94,0x9a95,0x9a96,0x9a97, + 0x9a98,0x9a99,0x9a9a,0x9a9b,0x9a9c,0x9a9d,0x9a9e,0x9a9f, + 0x9aa0,0x9aa1,0x9aa2,0x9aa3,0x9aa4,0x9aa5,0x9aa6,0x9aa7, + 0x9aa8,0x9aa9,0x9aaa,0x9aab,0x9aac,0x9aad,0x9aae,0x9aaf, + 0x9ab0,0x9ab1,0x9ab2,0x9ab3,0x9ab4,0x9ab5,0x9ab6,0x9ab7, + 0x9ab8,0x9ab9,0x9aba,0x9abb,0x9abc,0x9abd,0x9abe,0x9abf, + 0x9ac0,0x9ac1,0x9ac2,0x9ac3,0x9ac4,0x9ac5,0x9ac6,0x9ac7, + 0x9ac8,0x9ac9,0x9aca,0x9acb,0x9acc,0x9acd,0x9ace,0x9acf, + 0x9ad0,0x9ad1,0x9ad2,0x9ad3,0x9ad4,0x9ad5,0x9ad6,0x9ad7, + 0x9ad8,0x9ad9,0x9ada,0x9adb,0x9adc,0x9add,0x9ade,0x9adf, + 0x9ae0,0x9ae1,0x9ae2,0x9ae3,0x9ae4,0x9ae5,0x9ae6,0x9ae7, + 0x9ae8,0x9ae9,0x9aea,0x9aeb,0x9aec,0x9aed,0x9aee,0x9aef, + 0x9af0,0x9af1,0x9af2,0x9af3,0x9af4,0x9af5,0x9af6,0x9af7, + 0x9af8,0x9af9,0x9afa,0x9afb,0x9afc,0x9afd,0x9afe,0x9aff, + 0x9b00,0x9b01,0x9b02,0x9b03,0x9b04,0x9b05,0x9b06,0x9b07, + 0x9b08,0x9b09,0x9b0a,0x9b0b,0x9b0c,0x9b0d,0x9b0e,0x9b0f, + 0x9b10,0x9b11,0x9b12,0x9b13,0x9b14,0x9b15,0x9b16,0x9b17, + 0x9b18,0x9b19,0x9b1a,0x9b1b,0x9b1c,0x9b1d,0x9b1e,0x9b1f, + 0x9b20,0x9b21,0x9b22,0x9b23,0x9b24,0x9b25,0x9b26,0x9b27, + 0x9b28,0x9b29,0x9b2a,0x9b2b,0x9b2c,0x9b2d,0x9b2e,0x9b2f, + 0x9b30,0x9b31,0x9b32,0x9b33,0x9b34,0x9b35,0x9b36,0x9b37, + 0x9b38,0x9b39,0x9b3a,0x9b3b,0x9b3c,0x9b3d,0x9b3e,0x9b3f, + 0x9b40,0x9b41,0x9b42,0x9b43,0x9b44,0x9b45,0x9b46,0x9b47, + 0x9b48,0x9b49,0x9b4a,0x9b4b,0x9b4c,0x9b4d,0x9b4e,0x9b4f, + 0x9b50,0x9b51,0x9b52,0x9b53,0x9b54,0x9b55,0x9b56,0x9b57, + 0x9b58,0x9b59,0x9b5a,0x9b5b,0x9b5c,0x9b5d,0x9b5e,0x9b5f, + 0x9b60,0x9b61,0x9b62,0x9b63,0x9b64,0x9b65,0x9b66,0x9b67, + 0x9b68,0x9b69,0x9b6a,0x9b6b,0x9b6c,0x9b6d,0x9b6e,0x9b6f, + 0x9b70,0x9b71,0x9b72,0x9b73,0x9b74,0x9b75,0x9b76,0x9b77, + 0x9b78,0x9b79,0x9b7a,0x9b7b,0x9b7c,0x9b7d,0x9b7e,0x9b7f, + 0x9b80,0x9b81,0x9b82,0x9b83,0x9b84,0x9b85,0x9b86,0x9b87, + 0x9b88,0x9b89,0x9b8a,0x9b8b,0x9b8c,0x9b8d,0x9b8e,0x9b8f, + 0x9b90,0x9b91,0x9b92,0x9b93,0x9b94,0x9b95,0x9b96,0x9b97, + 0x9b98,0x9b99,0x9b9a,0x9b9b,0x9b9c,0x9b9d,0x9b9e,0x9b9f, + 0x9ba0,0x9ba1,0x9ba2,0x9ba3,0x9ba4,0x9ba5,0x9ba6,0x9ba7, + 0x9ba8,0x9ba9,0x9baa,0x9bab,0x9bac,0x9bad,0x9bae,0x9baf, + 0x9bb0,0x9bb1,0x9bb2,0x9bb3,0x9bb4,0x9bb5,0x9bb6,0x9bb7, + 0x9bb8,0x9bb9,0x9bba,0x9bbb,0x9bbc,0x9bbd,0x9bbe,0x9bbf, + 0x9bc0,0x9bc1,0x9bc2,0x9bc3,0x9bc4,0x9bc5,0x9bc6,0x9bc7, + 0x9bc8,0x9bc9,0x9bca,0x9bcb,0x9bcc,0x9bcd,0x9bce,0x9bcf, + 0x9bd0,0x9bd1,0x9bd2,0x9bd3,0x9bd4,0x9bd5,0x9bd6,0x9bd7, + 0x9bd8,0x9bd9,0x9bda,0x9bdb,0x9bdc,0x9bdd,0x9bde,0x9bdf, + 0x9be0,0x9be1,0x9be2,0x9be3,0x9be4,0x9be5,0x9be6,0x9be7, + 0x9be8,0x9be9,0x9bea,0x9beb,0x9bec,0x9bed,0x9bee,0x9bef, + 0x9bf0,0x9bf1,0x9bf2,0x9bf3,0x9bf4,0x9bf5,0x9bf6,0x9bf7, + 0x9bf8,0x9bf9,0x9bfa,0x9bfb,0x9bfc,0x9bfd,0x9bfe,0x9bff, + 0x9c00,0x9c01,0x9c02,0x9c03,0x9c04,0x9c05,0x9c06,0x9c07, + 0x9c08,0x9c09,0x9c0a,0x9c0b,0x9c0c,0x9c0d,0x9c0e,0x9c0f, + 0x9c10,0x9c11,0x9c12,0x9c13,0x9c14,0x9c15,0x9c16,0x9c17, + 0x9c18,0x9c19,0x9c1a,0x9c1b,0x9c1c,0x9c1d,0x9c1e,0x9c1f, + 0x9c20,0x9c21,0x9c22,0x9c23,0x9c24,0x9c25,0x9c26,0x9c27, + 0x9c28,0x9c29,0x9c2a,0x9c2b,0x9c2c,0x9c2d,0x9c2e,0x9c2f, + 0x9c30,0x9c31,0x9c32,0x9c33,0x9c34,0x9c35,0x9c36,0x9c37, + 0x9c38,0x9c39,0x9c3a,0x9c3b,0x9c3c,0x9c3d,0x9c3e,0x9c3f, + 0x9c40,0x9c41,0x9c42,0x9c43,0x9c44,0x9c45,0x9c46,0x9c47, + 0x9c48,0x9c49,0x9c4a,0x9c4b,0x9c4c,0x9c4d,0x9c4e,0x9c4f, + 0x9c50,0x9c51,0x9c52,0x9c53,0x9c54,0x9c55,0x9c56,0x9c57, + 0x9c58,0x9c59,0x9c5a,0x9c5b,0x9c5c,0x9c5d,0x9c5e,0x9c5f, + 0x9c60,0x9c61,0x9c62,0x9c63,0x9c64,0x9c65,0x9c66,0x9c67, + 0x9c68,0x9c69,0x9c6a,0x9c6b,0x9c6c,0x9c6d,0x9c6e,0x9c6f, + 0x9c70,0x9c71,0x9c72,0x9c73,0x9c74,0x9c75,0x9c76,0x9c77, + 0x9c78,0x9c79,0x9c7a,0x9c7b,0x9c7c,0x9c7d,0x9c7e,0x9c7f, + 0x9c80,0x9c81,0x9c82,0x9c83,0x9c84,0x9c85,0x9c86,0x9c87, + 0x9c88,0x9c89,0x9c8a,0x9c8b,0x9c8c,0x9c8d,0x9c8e,0x9c8f, + 0x9c90,0x9c91,0x9c92,0x9c93,0x9c94,0x9c95,0x9c96,0x9c97, + 0x9c98,0x9c99,0x9c9a,0x9c9b,0x9c9c,0x9c9d,0x9c9e,0x9c9f, + 0x9ca0,0x9ca1,0x9ca2,0x9ca3,0x9ca4,0x9ca5,0x9ca6,0x9ca7, + 0x9ca8,0x9ca9,0x9caa,0x9cab,0x9cac,0x9cad,0x9cae,0x9caf, + 0x9cb0,0x9cb1,0x9cb2,0x9cb3,0x9cb4,0x9cb5,0x9cb6,0x9cb7, + 0x9cb8,0x9cb9,0x9cba,0x9cbb,0x9cbc,0x9cbd,0x9cbe,0x9cbf, + 0x9cc0,0x9cc1,0x9cc2,0x9cc3,0x9cc4,0x9cc5,0x9cc6,0x9cc7, + 0x9cc8,0x9cc9,0x9cca,0x9ccb,0x9ccc,0x9ccd,0x9cce,0x9ccf, + 0x9cd0,0x9cd1,0x9cd2,0x9cd3,0x9cd4,0x9cd5,0x9cd6,0x9cd7, + 0x9cd8,0x9cd9,0x9cda,0x9cdb,0x9cdc,0x9cdd,0x9cde,0x9cdf, + 0x9ce0,0x9ce1,0x9ce2,0x9ce3,0x9ce4,0x9ce5,0x9ce6,0x9ce7, + 0x9ce8,0x9ce9,0x9cea,0x9ceb,0x9cec,0x9ced,0x9cee,0x9cef, + 0x9cf0,0x9cf1,0x9cf2,0x9cf3,0x9cf4,0x9cf5,0x9cf6,0x9cf7, + 0x9cf8,0x9cf9,0x9cfa,0x9cfb,0x9cfc,0x9cfd,0x9cfe,0x9cff, + 0x9d00,0x9d01,0x9d02,0x9d03,0x9d04,0x9d05,0x9d06,0x9d07, + 0x9d08,0x9d09,0x9d0a,0x9d0b,0x9d0c,0x9d0d,0x9d0e,0x9d0f, + 0x9d10,0x9d11,0x9d12,0x9d13,0x9d14,0x9d15,0x9d16,0x9d17, + 0x9d18,0x9d19,0x9d1a,0x9d1b,0x9d1c,0x9d1d,0x9d1e,0x9d1f, + 0x9d20,0x9d21,0x9d22,0x9d23,0x9d24,0x9d25,0x9d26,0x9d27, + 0x9d28,0x9d29,0x9d2a,0x9d2b,0x9d2c,0x9d2d,0x9d2e,0x9d2f, + 0x9d30,0x9d31,0x9d32,0x9d33,0x9d34,0x9d35,0x9d36,0x9d37, + 0x9d38,0x9d39,0x9d3a,0x9d3b,0x9d3c,0x9d3d,0x9d3e,0x9d3f, + 0x9d40,0x9d41,0x9d42,0x9d43,0x9d44,0x9d45,0x9d46,0x9d47, + 0x9d48,0x9d49,0x9d4a,0x9d4b,0x9d4c,0x9d4d,0x9d4e,0x9d4f, + 0x9d50,0x9d51,0x9d52,0x9d53,0x9d54,0x9d55,0x9d56,0x9d57, + 0x9d58,0x9d59,0x9d5a,0x9d5b,0x9d5c,0x9d5d,0x9d5e,0x9d5f, + 0x9d60,0x9d61,0x9d62,0x9d63,0x9d64,0x9d65,0x9d66,0x9d67, + 0x9d68,0x9d69,0x9d6a,0x9d6b,0x9d6c,0x9d6d,0x9d6e,0x9d6f, + 0x9d70,0x9d71,0x9d72,0x9d73,0x9d74,0x9d75,0x9d76,0x9d77, + 0x9d78,0x9d79,0x9d7a,0x9d7b,0x9d7c,0x9d7d,0x9d7e,0x9d7f, + 0x9d80,0x9d81,0x9d82,0x9d83,0x9d84,0x9d85,0x9d86,0x9d87, + 0x9d88,0x9d89,0x9d8a,0x9d8b,0x9d8c,0x9d8d,0x9d8e,0x9d8f, + 0x9d90,0x9d91,0x9d92,0x9d93,0x9d94,0x9d95,0x9d96,0x9d97, + 0x9d98,0x9d99,0x9d9a,0x9d9b,0x9d9c,0x9d9d,0x9d9e,0x9d9f, + 0x9da0,0x9da1,0x9da2,0x9da3,0x9da4,0x9da5,0x9da6,0x9da7, + 0x9da8,0x9da9,0x9daa,0x9dab,0x9dac,0x9dad,0x9dae,0x9daf, + 0x9db0,0x9db1,0x9db2,0x9db3,0x9db4,0x9db5,0x9db6,0x9db7, + 0x9db8,0x9db9,0x9dba,0x9dbb,0x9dbc,0x9dbd,0x9dbe,0x9dbf, + 0x9dc0,0x9dc1,0x9dc2,0x9dc3,0x9dc4,0x9dc5,0x9dc6,0x9dc7, + 0x9dc8,0x9dc9,0x9dca,0x9dcb,0x9dcc,0x9dcd,0x9dce,0x9dcf, + 0x9dd0,0x9dd1,0x9dd2,0x9dd3,0x9dd4,0x9dd5,0x9dd6,0x9dd7, + 0x9dd8,0x9dd9,0x9dda,0x9ddb,0x9ddc,0x9ddd,0x9dde,0x9ddf, + 0x9de0,0x9de1,0x9de2,0x9de3,0x9de4,0x9de5,0x9de6,0x9de7, + 0x9de8,0x9de9,0x9dea,0x9deb,0x9dec,0x9ded,0x9dee,0x9def, + 0x9df0,0x9df1,0x9df2,0x9df3,0x9df4,0x9df5,0x9df6,0x9df7, + 0x9df8,0x9df9,0x9dfa,0x9dfb,0x9dfc,0x9dfd,0x9dfe,0x9dff, + 0x9e00,0x9e01,0x9e02,0x9e03,0x9e04,0x9e05,0x9e06,0x9e07, + 0x9e08,0x9e09,0x9e0a,0x9e0b,0x9e0c,0x9e0d,0x9e0e,0x9e0f, + 0x9e10,0x9e11,0x9e12,0x9e13,0x9e14,0x9e15,0x9e16,0x9e17, + 0x9e18,0x9e19,0x9e1a,0x9e1b,0x9e1c,0x9e1d,0x9e1e,0x9e1f, + 0x9e20,0x9e21,0x9e22,0x9e23,0x9e24,0x9e25,0x9e26,0x9e27, + 0x9e28,0x9e29,0x9e2a,0x9e2b,0x9e2c,0x9e2d,0x9e2e,0x9e2f, + 0x9e30,0x9e31,0x9e32,0x9e33,0x9e34,0x9e35,0x9e36,0x9e37, + 0x9e38,0x9e39,0x9e3a,0x9e3b,0x9e3c,0x9e3d,0x9e3e,0x9e3f, + 0x9e40,0x9e41,0x9e42,0x9e43,0x9e44,0x9e45,0x9e46,0x9e47, + 0x9e48,0x9e49,0x9e4a,0x9e4b,0x9e4c,0x9e4d,0x9e4e,0x9e4f, + 0x9e50,0x9e51,0x9e52,0x9e53,0x9e54,0x9e55,0x9e56,0x9e57, + 0x9e58,0x9e59,0x9e5a,0x9e5b,0x9e5c,0x9e5d,0x9e5e,0x9e5f, + 0x9e60,0x9e61,0x9e62,0x9e63,0x9e64,0x9e65,0x9e66,0x9e67, + 0x9e68,0x9e69,0x9e6a,0x9e6b,0x9e6c,0x9e6d,0x9e6e,0x9e6f, + 0x9e70,0x9e71,0x9e72,0x9e73,0x9e74,0x9e75,0x9e76,0x9e77, + 0x9e78,0x9e79,0x9e7a,0x9e7b,0x9e7c,0x9e7d,0x9e7e,0x9e7f, + 0x9e80,0x9e81,0x9e82,0x9e83,0x9e84,0x9e85,0x9e86,0x9e87, + 0x9e88,0x9e89,0x9e8a,0x9e8b,0x9e8c,0x9e8d,0x9e8e,0x9e8f, + 0x9e90,0x9e91,0x9e92,0x9e93,0x9e94,0x9e95,0x9e96,0x9e97, + 0x9e98,0x9e99,0x9e9a,0x9e9b,0x9e9c,0x9e9d,0x9e9e,0x9e9f, + 0x9ea0,0x9ea1,0x9ea2,0x9ea3,0x9ea4,0x9ea5,0x9ea6,0x9ea7, + 0x9ea8,0x9ea9,0x9eaa,0x9eab,0x9eac,0x9ead,0x9eae,0x9eaf, + 0x9eb0,0x9eb1,0x9eb2,0x9eb3,0x9eb4,0x9eb5,0x9eb6,0x9eb7, + 0x9eb8,0x9eb9,0x9eba,0x9ebb,0x9ebc,0x9ebd,0x9ebe,0x9ebf, + 0x9ec0,0x9ec1,0x9ec2,0x9ec3,0x9ec4,0x9ec5,0x9ec6,0x9ec7, + 0x9ec8,0x9ec9,0x9eca,0x9ecb,0x9ecc,0x9ecd,0x9ece,0x9ecf, + 0x9ed0,0x9ed1,0x9ed2,0x9ed3,0x9ed4,0x9ed5,0x9ed6,0x9ed7, + 0x9ed8,0x9ed9,0x9eda,0x9edb,0x9edc,0x9edd,0x9ede,0x9edf, + 0x9ee0,0x9ee1,0x9ee2,0x9ee3,0x9ee4,0x9ee5,0x9ee6,0x9ee7, + 0x9ee8,0x9ee9,0x9eea,0x9eeb,0x9eec,0x9eed,0x9eee,0x9eef, + 0x9ef0,0x9ef1,0x9ef2,0x9ef3,0x9ef4,0x9ef5,0x9ef6,0x9ef7, + 0x9ef8,0x9ef9,0x9efa,0x9efb,0x9efc,0x9efd,0x9efe,0x9eff, + 0x9f00,0x9f01,0x9f02,0x9f03,0x9f04,0x9f05,0x9f06,0x9f07, + 0x9f08,0x9f09,0x9f0a,0x9f0b,0x9f0c,0x9f0d,0x9f0e,0x9f0f, + 0x9f10,0x9f11,0x9f12,0x9f13,0x9f14,0x9f15,0x9f16,0x9f17, + 0x9f18,0x9f19,0x9f1a,0x9f1b,0x9f1c,0x9f1d,0x9f1e,0x9f1f, + 0x9f20,0x9f21,0x9f22,0x9f23,0x9f24,0x9f25,0x9f26,0x9f27, + 0x9f28,0x9f29,0x9f2a,0x9f2b,0x9f2c,0x9f2d,0x9f2e,0x9f2f, + 0x9f30,0x9f31,0x9f32,0x9f33,0x9f34,0x9f35,0x9f36,0x9f37, + 0x9f38,0x9f39,0x9f3a,0x9f3b,0x9f3c,0x9f3d,0x9f3e,0x9f3f, + 0x9f40,0x9f41,0x9f42,0x9f43,0x9f44,0x9f45,0x9f46,0x9f47, + 0x9f48,0x9f49,0x9f4a,0x9f4b,0x9f4c,0x9f4d,0x9f4e,0x9f4f, + 0x9f50,0x9f51,0x9f52,0x9f53,0x9f54,0x9f55,0x9f56,0x9f57, + 0x9f58,0x9f59,0x9f5a,0x9f5b,0x9f5c,0x9f5d,0x9f5e,0x9f5f, + 0x9f60,0x9f61,0x9f62,0x9f63,0x9f64,0x9f65,0x9f66,0x9f67, + 0x9f68,0x9f69,0x9f6a,0x9f6b,0x9f6c,0x9f6d,0x9f6e,0x9f6f, + 0x9f70,0x9f71,0x9f72,0x9f73,0x9f74,0x9f75,0x9f76,0x9f77, + 0x9f78,0x9f79,0x9f7a,0x9f7b,0x9f7c,0x9f7d,0x9f7e,0x9f7f, + 0x9f80,0x9f81,0x9f82,0x9f83,0x9f84,0x9f85,0x9f86,0x9f87, + 0x9f88,0x9f89,0x9f8a,0x9f8b,0x9f8c,0x9f8d,0x9f8e,0x9f8f, + 0x9f90,0x9f91,0x9f92,0x9f93,0x9f94,0x9f95,0x9f96,0x9f97, + 0x9f98,0x9f99,0x9f9a,0x9f9b,0x9f9c,0x9f9d,0x9f9e,0x9f9f, + 0x9fa0,0x9fa1,0x9fa2,0x9fa3,0x9fa4,0x9fa5,0x9fa6,0x9fa7, + 0x9fa8,0x9fa9,0x9faa,0x9fab,0x9fac,0x9fad,0x9fae,0x9faf, + 0x9fb0,0x9fb1,0x9fb2,0x9fb3,0x9fb4,0x9fb5,0x9fb6,0x9fb7, + 0x9fb8,0x9fb9,0x9fba,0x9fbb,0x9fbc,0x9fbd,0x9fbe,0x9fbf, + 0x9fc0,0x9fc1,0x9fc2,0x9fc3,0x9fc4,0x9fc5,0x9fc6,0x9fc7, + 0x9fc8,0x9fc9,0x9fca,0x9fcb,0x9fcc,0x9fcd,0x9fce,0x9fcf, + 0x9fd0,0x9fd1,0x9fd2,0x9fd3,0x9fd4,0x9fd5,0x9fd6,0x9fd7, + 0x9fd8,0x9fd9,0x9fda,0x9fdb,0x9fdc,0x9fdd,0x9fde,0x9fdf, + 0x9fe0,0x9fe1,0x9fe2,0x9fe3,0x9fe4,0x9fe5,0x9fe6,0x9fe7, + 0x9fe8,0x9fe9,0x9fea,0x9feb,0x9fec,0x9fed,0x9fee,0x9fef, + 0x9ff0,0x9ff1,0x9ff2,0x9ff3,0x9ff4,0x9ff5,0x9ff6,0x9ff7, + 0x9ff8,0x9ff9,0x9ffa,0x9ffb,0x9ffc,0x9ffd,0x9ffe,0x9fff, + 0xa000,0xa001,0xa002,0xa003,0xa004,0xa005,0xa006,0xa007, + 0xa008,0xa009,0xa00a,0xa00b,0xa00c,0xa00d,0xa00e,0xa00f, + 0xa010,0xa011,0xa012,0xa013,0xa014,0xa015,0xa016,0xa017, + 0xa018,0xa019,0xa01a,0xa01b,0xa01c,0xa01d,0xa01e,0xa01f, + 0xa020,0xa021,0xa022,0xa023,0xa024,0xa025,0xa026,0xa027, + 0xa028,0xa029,0xa02a,0xa02b,0xa02c,0xa02d,0xa02e,0xa02f, + 0xa030,0xa031,0xa032,0xa033,0xa034,0xa035,0xa036,0xa037, + 0xa038,0xa039,0xa03a,0xa03b,0xa03c,0xa03d,0xa03e,0xa03f, + 0xa040,0xa041,0xa042,0xa043,0xa044,0xa045,0xa046,0xa047, + 0xa048,0xa049,0xa04a,0xa04b,0xa04c,0xa04d,0xa04e,0xa04f, + 0xa050,0xa051,0xa052,0xa053,0xa054,0xa055,0xa056,0xa057, + 0xa058,0xa059,0xa05a,0xa05b,0xa05c,0xa05d,0xa05e,0xa05f, + 0xa060,0xa061,0xa062,0xa063,0xa064,0xa065,0xa066,0xa067, + 0xa068,0xa069,0xa06a,0xa06b,0xa06c,0xa06d,0xa06e,0xa06f, + 0xa070,0xa071,0xa072,0xa073,0xa074,0xa075,0xa076,0xa077, + 0xa078,0xa079,0xa07a,0xa07b,0xa07c,0xa07d,0xa07e,0xa07f, + 0xa080,0xa081,0xa082,0xa083,0xa084,0xa085,0xa086,0xa087, + 0xa088,0xa089,0xa08a,0xa08b,0xa08c,0xa08d,0xa08e,0xa08f, + 0xa090,0xa091,0xa092,0xa093,0xa094,0xa095,0xa096,0xa097, + 0xa098,0xa099,0xa09a,0xa09b,0xa09c,0xa09d,0xa09e,0xa09f, + 0xa0a0,0xa0a1,0xa0a2,0xa0a3,0xa0a4,0xa0a5,0xa0a6,0xa0a7, + 0xa0a8,0xa0a9,0xa0aa,0xa0ab,0xa0ac,0xa0ad,0xa0ae,0xa0af, + 0xa0b0,0xa0b1,0xa0b2,0xa0b3,0xa0b4,0xa0b5,0xa0b6,0xa0b7, + 0xa0b8,0xa0b9,0xa0ba,0xa0bb,0xa0bc,0xa0bd,0xa0be,0xa0bf, + 0xa0c0,0xa0c1,0xa0c2,0xa0c3,0xa0c4,0xa0c5,0xa0c6,0xa0c7, + 0xa0c8,0xa0c9,0xa0ca,0xa0cb,0xa0cc,0xa0cd,0xa0ce,0xa0cf, + 0xa0d0,0xa0d1,0xa0d2,0xa0d3,0xa0d4,0xa0d5,0xa0d6,0xa0d7, + 0xa0d8,0xa0d9,0xa0da,0xa0db,0xa0dc,0xa0dd,0xa0de,0xa0df, + 0xa0e0,0xa0e1,0xa0e2,0xa0e3,0xa0e4,0xa0e5,0xa0e6,0xa0e7, + 0xa0e8,0xa0e9,0xa0ea,0xa0eb,0xa0ec,0xa0ed,0xa0ee,0xa0ef, + 0xa0f0,0xa0f1,0xa0f2,0xa0f3,0xa0f4,0xa0f5,0xa0f6,0xa0f7, + 0xa0f8,0xa0f9,0xa0fa,0xa0fb,0xa0fc,0xa0fd,0xa0fe,0xa0ff, + 0xa100,0xa101,0xa102,0xa103,0xa104,0xa105,0xa106,0xa107, + 0xa108,0xa109,0xa10a,0xa10b,0xa10c,0xa10d,0xa10e,0xa10f, + 0xa110,0xa111,0xa112,0xa113,0xa114,0xa115,0xa116,0xa117, + 0xa118,0xa119,0xa11a,0xa11b,0xa11c,0xa11d,0xa11e,0xa11f, + 0xa120,0xa121,0xa122,0xa123,0xa124,0xa125,0xa126,0xa127, + 0xa128,0xa129,0xa12a,0xa12b,0xa12c,0xa12d,0xa12e,0xa12f, + 0xa130,0xa131,0xa132,0xa133,0xa134,0xa135,0xa136,0xa137, + 0xa138,0xa139,0xa13a,0xa13b,0xa13c,0xa13d,0xa13e,0xa13f, + 0xa140,0xa141,0xa142,0xa143,0xa144,0xa145,0xa146,0xa147, + 0xa148,0xa149,0xa14a,0xa14b,0xa14c,0xa14d,0xa14e,0xa14f, + 0xa150,0xa151,0xa152,0xa153,0xa154,0xa155,0xa156,0xa157, + 0xa158,0xa159,0xa15a,0xa15b,0xa15c,0xa15d,0xa15e,0xa15f, + 0xa160,0xa161,0xa162,0xa163,0xa164,0xa165,0xa166,0xa167, + 0xa168,0xa169,0xa16a,0xa16b,0xa16c,0xa16d,0xa16e,0xa16f, + 0xa170,0xa171,0xa172,0xa173,0xa174,0xa175,0xa176,0xa177, + 0xa178,0xa179,0xa17a,0xa17b,0xa17c,0xa17d,0xa17e,0xa17f, + 0xa180,0xa181,0xa182,0xa183,0xa184,0xa185,0xa186,0xa187, + 0xa188,0xa189,0xa18a,0xa18b,0xa18c,0xa18d,0xa18e,0xa18f, + 0xa190,0xa191,0xa192,0xa193,0xa194,0xa195,0xa196,0xa197, + 0xa198,0xa199,0xa19a,0xa19b,0xa19c,0xa19d,0xa19e,0xa19f, + 0xa1a0,0xa1a1,0xa1a2,0xa1a3,0xa1a4,0xa1a5,0xa1a6,0xa1a7, + 0xa1a8,0xa1a9,0xa1aa,0xa1ab,0xa1ac,0xa1ad,0xa1ae,0xa1af, + 0xa1b0,0xa1b1,0xa1b2,0xa1b3,0xa1b4,0xa1b5,0xa1b6,0xa1b7, + 0xa1b8,0xa1b9,0xa1ba,0xa1bb,0xa1bc,0xa1bd,0xa1be,0xa1bf, + 0xa1c0,0xa1c1,0xa1c2,0xa1c3,0xa1c4,0xa1c5,0xa1c6,0xa1c7, + 0xa1c8,0xa1c9,0xa1ca,0xa1cb,0xa1cc,0xa1cd,0xa1ce,0xa1cf, + 0xa1d0,0xa1d1,0xa1d2,0xa1d3,0xa1d4,0xa1d5,0xa1d6,0xa1d7, + 0xa1d8,0xa1d9,0xa1da,0xa1db,0xa1dc,0xa1dd,0xa1de,0xa1df, + 0xa1e0,0xa1e1,0xa1e2,0xa1e3,0xa1e4,0xa1e5,0xa1e6,0xa1e7, + 0xa1e8,0xa1e9,0xa1ea,0xa1eb,0xa1ec,0xa1ed,0xa1ee,0xa1ef, + 0xa1f0,0xa1f1,0xa1f2,0xa1f3,0xa1f4,0xa1f5,0xa1f6,0xa1f7, + 0xa1f8,0xa1f9,0xa1fa,0xa1fb,0xa1fc,0xa1fd,0xa1fe,0xa1ff, + 0xa200,0xa201,0xa202,0xa203,0xa204,0xa205,0xa206,0xa207, + 0xa208,0xa209,0xa20a,0xa20b,0xa20c,0xa20d,0xa20e,0xa20f, + 0xa210,0xa211,0xa212,0xa213,0xa214,0xa215,0xa216,0xa217, + 0xa218,0xa219,0xa21a,0xa21b,0xa21c,0xa21d,0xa21e,0xa21f, + 0xa220,0xa221,0xa222,0xa223,0xa224,0xa225,0xa226,0xa227, + 0xa228,0xa229,0xa22a,0xa22b,0xa22c,0xa22d,0xa22e,0xa22f, + 0xa230,0xa231,0xa232,0xa233,0xa234,0xa235,0xa236,0xa237, + 0xa238,0xa239,0xa23a,0xa23b,0xa23c,0xa23d,0xa23e,0xa23f, + 0xa240,0xa241,0xa242,0xa243,0xa244,0xa245,0xa246,0xa247, + 0xa248,0xa249,0xa24a,0xa24b,0xa24c,0xa24d,0xa24e,0xa24f, + 0xa250,0xa251,0xa252,0xa253,0xa254,0xa255,0xa256,0xa257, + 0xa258,0xa259,0xa25a,0xa25b,0xa25c,0xa25d,0xa25e,0xa25f, + 0xa260,0xa261,0xa262,0xa263,0xa264,0xa265,0xa266,0xa267, + 0xa268,0xa269,0xa26a,0xa26b,0xa26c,0xa26d,0xa26e,0xa26f, + 0xa270,0xa271,0xa272,0xa273,0xa274,0xa275,0xa276,0xa277, + 0xa278,0xa279,0xa27a,0xa27b,0xa27c,0xa27d,0xa27e,0xa27f, + 0xa280,0xa281,0xa282,0xa283,0xa284,0xa285,0xa286,0xa287, + 0xa288,0xa289,0xa28a,0xa28b,0xa28c,0xa28d,0xa28e,0xa28f, + 0xa290,0xa291,0xa292,0xa293,0xa294,0xa295,0xa296,0xa297, + 0xa298,0xa299,0xa29a,0xa29b,0xa29c,0xa29d,0xa29e,0xa29f, + 0xa2a0,0xa2a1,0xa2a2,0xa2a3,0xa2a4,0xa2a5,0xa2a6,0xa2a7, + 0xa2a8,0xa2a9,0xa2aa,0xa2ab,0xa2ac,0xa2ad,0xa2ae,0xa2af, + 0xa2b0,0xa2b1,0xa2b2,0xa2b3,0xa2b4,0xa2b5,0xa2b6,0xa2b7, + 0xa2b8,0xa2b9,0xa2ba,0xa2bb,0xa2bc,0xa2bd,0xa2be,0xa2bf, + 0xa2c0,0xa2c1,0xa2c2,0xa2c3,0xa2c4,0xa2c5,0xa2c6,0xa2c7, + 0xa2c8,0xa2c9,0xa2ca,0xa2cb,0xa2cc,0xa2cd,0xa2ce,0xa2cf, + 0xa2d0,0xa2d1,0xa2d2,0xa2d3,0xa2d4,0xa2d5,0xa2d6,0xa2d7, + 0xa2d8,0xa2d9,0xa2da,0xa2db,0xa2dc,0xa2dd,0xa2de,0xa2df, + 0xa2e0,0xa2e1,0xa2e2,0xa2e3,0xa2e4,0xa2e5,0xa2e6,0xa2e7, + 0xa2e8,0xa2e9,0xa2ea,0xa2eb,0xa2ec,0xa2ed,0xa2ee,0xa2ef, + 0xa2f0,0xa2f1,0xa2f2,0xa2f3,0xa2f4,0xa2f5,0xa2f6,0xa2f7, + 0xa2f8,0xa2f9,0xa2fa,0xa2fb,0xa2fc,0xa2fd,0xa2fe,0xa2ff, + 0xa300,0xa301,0xa302,0xa303,0xa304,0xa305,0xa306,0xa307, + 0xa308,0xa309,0xa30a,0xa30b,0xa30c,0xa30d,0xa30e,0xa30f, + 0xa310,0xa311,0xa312,0xa313,0xa314,0xa315,0xa316,0xa317, + 0xa318,0xa319,0xa31a,0xa31b,0xa31c,0xa31d,0xa31e,0xa31f, + 0xa320,0xa321,0xa322,0xa323,0xa324,0xa325,0xa326,0xa327, + 0xa328,0xa329,0xa32a,0xa32b,0xa32c,0xa32d,0xa32e,0xa32f, + 0xa330,0xa331,0xa332,0xa333,0xa334,0xa335,0xa336,0xa337, + 0xa338,0xa339,0xa33a,0xa33b,0xa33c,0xa33d,0xa33e,0xa33f, + 0xa340,0xa341,0xa342,0xa343,0xa344,0xa345,0xa346,0xa347, + 0xa348,0xa349,0xa34a,0xa34b,0xa34c,0xa34d,0xa34e,0xa34f, + 0xa350,0xa351,0xa352,0xa353,0xa354,0xa355,0xa356,0xa357, + 0xa358,0xa359,0xa35a,0xa35b,0xa35c,0xa35d,0xa35e,0xa35f, + 0xa360,0xa361,0xa362,0xa363,0xa364,0xa365,0xa366,0xa367, + 0xa368,0xa369,0xa36a,0xa36b,0xa36c,0xa36d,0xa36e,0xa36f, + 0xa370,0xa371,0xa372,0xa373,0xa374,0xa375,0xa376,0xa377, + 0xa378,0xa379,0xa37a,0xa37b,0xa37c,0xa37d,0xa37e,0xa37f, + 0xa380,0xa381,0xa382,0xa383,0xa384,0xa385,0xa386,0xa387, + 0xa388,0xa389,0xa38a,0xa38b,0xa38c,0xa38d,0xa38e,0xa38f, + 0xa390,0xa391,0xa392,0xa393,0xa394,0xa395,0xa396,0xa397, + 0xa398,0xa399,0xa39a,0xa39b,0xa39c,0xa39d,0xa39e,0xa39f, + 0xa3a0,0xa3a1,0xa3a2,0xa3a3,0xa3a4,0xa3a5,0xa3a6,0xa3a7, + 0xa3a8,0xa3a9,0xa3aa,0xa3ab,0xa3ac,0xa3ad,0xa3ae,0xa3af, + 0xa3b0,0xa3b1,0xa3b2,0xa3b3,0xa3b4,0xa3b5,0xa3b6,0xa3b7, + 0xa3b8,0xa3b9,0xa3ba,0xa3bb,0xa3bc,0xa3bd,0xa3be,0xa3bf, + 0xa3c0,0xa3c1,0xa3c2,0xa3c3,0xa3c4,0xa3c5,0xa3c6,0xa3c7, + 0xa3c8,0xa3c9,0xa3ca,0xa3cb,0xa3cc,0xa3cd,0xa3ce,0xa3cf, + 0xa3d0,0xa3d1,0xa3d2,0xa3d3,0xa3d4,0xa3d5,0xa3d6,0xa3d7, + 0xa3d8,0xa3d9,0xa3da,0xa3db,0xa3dc,0xa3dd,0xa3de,0xa3df, + 0xa3e0,0xa3e1,0xa3e2,0xa3e3,0xa3e4,0xa3e5,0xa3e6,0xa3e7, + 0xa3e8,0xa3e9,0xa3ea,0xa3eb,0xa3ec,0xa3ed,0xa3ee,0xa3ef, + 0xa3f0,0xa3f1,0xa3f2,0xa3f3,0xa3f4,0xa3f5,0xa3f6,0xa3f7, + 0xa3f8,0xa3f9,0xa3fa,0xa3fb,0xa3fc,0xa3fd,0xa3fe,0xa3ff, + 0xa400,0xa401,0xa402,0xa403,0xa404,0xa405,0xa406,0xa407, + 0xa408,0xa409,0xa40a,0xa40b,0xa40c,0xa40d,0xa40e,0xa40f, + 0xa410,0xa411,0xa412,0xa413,0xa414,0xa415,0xa416,0xa417, + 0xa418,0xa419,0xa41a,0xa41b,0xa41c,0xa41d,0xa41e,0xa41f, + 0xa420,0xa421,0xa422,0xa423,0xa424,0xa425,0xa426,0xa427, + 0xa428,0xa429,0xa42a,0xa42b,0xa42c,0xa42d,0xa42e,0xa42f, + 0xa430,0xa431,0xa432,0xa433,0xa434,0xa435,0xa436,0xa437, + 0xa438,0xa439,0xa43a,0xa43b,0xa43c,0xa43d,0xa43e,0xa43f, + 0xa440,0xa441,0xa442,0xa443,0xa444,0xa445,0xa446,0xa447, + 0xa448,0xa449,0xa44a,0xa44b,0xa44c,0xa44d,0xa44e,0xa44f, + 0xa450,0xa451,0xa452,0xa453,0xa454,0xa455,0xa456,0xa457, + 0xa458,0xa459,0xa45a,0xa45b,0xa45c,0xa45d,0xa45e,0xa45f, + 0xa460,0xa461,0xa462,0xa463,0xa464,0xa465,0xa466,0xa467, + 0xa468,0xa469,0xa46a,0xa46b,0xa46c,0xa46d,0xa46e,0xa46f, + 0xa470,0xa471,0xa472,0xa473,0xa474,0xa475,0xa476,0xa477, + 0xa478,0xa479,0xa47a,0xa47b,0xa47c,0xa47d,0xa47e,0xa47f, + 0xa480,0xa481,0xa482,0xa483,0xa484,0xa485,0xa486,0xa487, + 0xa488,0xa489,0xa48a,0xa48b,0xa48c,0xa48d,0xa48e,0xa48f, + 0xa490,0xa491,0xa492,0xa493,0xa494,0xa495,0xa496,0xa497, + 0xa498,0xa499,0xa49a,0xa49b,0xa49c,0xa49d,0xa49e,0xa49f, + 0xa4a0,0xa4a1,0xa4a2,0xa4a3,0xa4a4,0xa4a5,0xa4a6,0xa4a7, + 0xa4a8,0xa4a9,0xa4aa,0xa4ab,0xa4ac,0xa4ad,0xa4ae,0xa4af, + 0xa4b0,0xa4b1,0xa4b2,0xa4b3,0xa4b4,0xa4b5,0xa4b6,0xa4b7, + 0xa4b8,0xa4b9,0xa4ba,0xa4bb,0xa4bc,0xa4bd,0xa4be,0xa4bf, + 0xa4c0,0xa4c1,0xa4c2,0xa4c3,0xa4c4,0xa4c5,0xa4c6,0xa4c7, + 0xa4c8,0xa4c9,0xa4ca,0xa4cb,0xa4cc,0xa4cd,0xa4ce,0xa4cf, + 0xa4d0,0xa4d1,0xa4d2,0xa4d3,0xa4d4,0xa4d5,0xa4d6,0xa4d7, + 0xa4d8,0xa4d9,0xa4da,0xa4db,0xa4dc,0xa4dd,0xa4de,0xa4df, + 0xa4e0,0xa4e1,0xa4e2,0xa4e3,0xa4e4,0xa4e5,0xa4e6,0xa4e7, + 0xa4e8,0xa4e9,0xa4ea,0xa4eb,0xa4ec,0xa4ed,0xa4ee,0xa4ef, + 0xa4f0,0xa4f1,0xa4f2,0xa4f3,0xa4f4,0xa4f5,0xa4f6,0xa4f7, + 0xa4f8,0xa4f9,0xa4fa,0xa4fb,0xa4fc,0xa4fd,0xa4fe,0xa4ff, + 0xa500,0xa501,0xa502,0xa503,0xa504,0xa505,0xa506,0xa507, + 0xa508,0xa509,0xa50a,0xa50b,0xa50c,0xa50d,0xa50e,0xa50f, + 0xa510,0xa511,0xa512,0xa513,0xa514,0xa515,0xa516,0xa517, + 0xa518,0xa519,0xa51a,0xa51b,0xa51c,0xa51d,0xa51e,0xa51f, + 0xa520,0xa521,0xa522,0xa523,0xa524,0xa525,0xa526,0xa527, + 0xa528,0xa529,0xa52a,0xa52b,0xa52c,0xa52d,0xa52e,0xa52f, + 0xa530,0xa531,0xa532,0xa533,0xa534,0xa535,0xa536,0xa537, + 0xa538,0xa539,0xa53a,0xa53b,0xa53c,0xa53d,0xa53e,0xa53f, + 0xa540,0xa541,0xa542,0xa543,0xa544,0xa545,0xa546,0xa547, + 0xa548,0xa549,0xa54a,0xa54b,0xa54c,0xa54d,0xa54e,0xa54f, + 0xa550,0xa551,0xa552,0xa553,0xa554,0xa555,0xa556,0xa557, + 0xa558,0xa559,0xa55a,0xa55b,0xa55c,0xa55d,0xa55e,0xa55f, + 0xa560,0xa561,0xa562,0xa563,0xa564,0xa565,0xa566,0xa567, + 0xa568,0xa569,0xa56a,0xa56b,0xa56c,0xa56d,0xa56e,0xa56f, + 0xa570,0xa571,0xa572,0xa573,0xa574,0xa575,0xa576,0xa577, + 0xa578,0xa579,0xa57a,0xa57b,0xa57c,0xa57d,0xa57e,0xa57f, + 0xa580,0xa581,0xa582,0xa583,0xa584,0xa585,0xa586,0xa587, + 0xa588,0xa589,0xa58a,0xa58b,0xa58c,0xa58d,0xa58e,0xa58f, + 0xa590,0xa591,0xa592,0xa593,0xa594,0xa595,0xa596,0xa597, + 0xa598,0xa599,0xa59a,0xa59b,0xa59c,0xa59d,0xa59e,0xa59f, + 0xa5a0,0xa5a1,0xa5a2,0xa5a3,0xa5a4,0xa5a5,0xa5a6,0xa5a7, + 0xa5a8,0xa5a9,0xa5aa,0xa5ab,0xa5ac,0xa5ad,0xa5ae,0xa5af, + 0xa5b0,0xa5b1,0xa5b2,0xa5b3,0xa5b4,0xa5b5,0xa5b6,0xa5b7, + 0xa5b8,0xa5b9,0xa5ba,0xa5bb,0xa5bc,0xa5bd,0xa5be,0xa5bf, + 0xa5c0,0xa5c1,0xa5c2,0xa5c3,0xa5c4,0xa5c5,0xa5c6,0xa5c7, + 0xa5c8,0xa5c9,0xa5ca,0xa5cb,0xa5cc,0xa5cd,0xa5ce,0xa5cf, + 0xa5d0,0xa5d1,0xa5d2,0xa5d3,0xa5d4,0xa5d5,0xa5d6,0xa5d7, + 0xa5d8,0xa5d9,0xa5da,0xa5db,0xa5dc,0xa5dd,0xa5de,0xa5df, + 0xa5e0,0xa5e1,0xa5e2,0xa5e3,0xa5e4,0xa5e5,0xa5e6,0xa5e7, + 0xa5e8,0xa5e9,0xa5ea,0xa5eb,0xa5ec,0xa5ed,0xa5ee,0xa5ef, + 0xa5f0,0xa5f1,0xa5f2,0xa5f3,0xa5f4,0xa5f5,0xa5f6,0xa5f7, + 0xa5f8,0xa5f9,0xa5fa,0xa5fb,0xa5fc,0xa5fd,0xa5fe,0xa5ff, + 0xa600,0xa601,0xa602,0xa603,0xa604,0xa605,0xa606,0xa607, + 0xa608,0xa609,0xa60a,0xa60b,0xa60c,0xa60d,0xa60e,0xa60f, + 0xa610,0xa611,0xa612,0xa613,0xa614,0xa615,0xa616,0xa617, + 0xa618,0xa619,0xa61a,0xa61b,0xa61c,0xa61d,0xa61e,0xa61f, + 0xa620,0xa621,0xa622,0xa623,0xa624,0xa625,0xa626,0xa627, + 0xa628,0xa629,0xa62a,0xa62b,0xa62c,0xa62d,0xa62e,0xa62f, + 0xa630,0xa631,0xa632,0xa633,0xa634,0xa635,0xa636,0xa637, + 0xa638,0xa639,0xa63a,0xa63b,0xa63c,0xa63d,0xa63e,0xa63f, + 0xa640,0xa641,0xa642,0xa643,0xa644,0xa645,0xa646,0xa647, + 0xa648,0xa649,0xa64a,0xa64b,0xa64c,0xa64d,0xa64e,0xa64f, + 0xa650,0xa651,0xa652,0xa653,0xa654,0xa655,0xa656,0xa657, + 0xa658,0xa659,0xa65a,0xa65b,0xa65c,0xa65d,0xa65e,0xa65f, + 0xa660,0xa661,0xa662,0xa663,0xa664,0xa665,0xa666,0xa667, + 0xa668,0xa669,0xa66a,0xa66b,0xa66c,0xa66d,0xa66e,0xa66f, + 0xa670,0xa671,0xa672,0xa673,0xa674,0xa675,0xa676,0xa677, + 0xa678,0xa679,0xa67a,0xa67b,0xa67c,0xa67d,0xa67e,0xa67f, + 0xa680,0xa681,0xa682,0xa683,0xa684,0xa685,0xa686,0xa687, + 0xa688,0xa689,0xa68a,0xa68b,0xa68c,0xa68d,0xa68e,0xa68f, + 0xa690,0xa691,0xa692,0xa693,0xa694,0xa695,0xa696,0xa697, + 0xa698,0xa699,0xa69a,0xa69b,0xa69c,0xa69d,0xa69e,0xa69f, + 0xa6a0,0xa6a1,0xa6a2,0xa6a3,0xa6a4,0xa6a5,0xa6a6,0xa6a7, + 0xa6a8,0xa6a9,0xa6aa,0xa6ab,0xa6ac,0xa6ad,0xa6ae,0xa6af, + 0xa6b0,0xa6b1,0xa6b2,0xa6b3,0xa6b4,0xa6b5,0xa6b6,0xa6b7, + 0xa6b8,0xa6b9,0xa6ba,0xa6bb,0xa6bc,0xa6bd,0xa6be,0xa6bf, + 0xa6c0,0xa6c1,0xa6c2,0xa6c3,0xa6c4,0xa6c5,0xa6c6,0xa6c7, + 0xa6c8,0xa6c9,0xa6ca,0xa6cb,0xa6cc,0xa6cd,0xa6ce,0xa6cf, + 0xa6d0,0xa6d1,0xa6d2,0xa6d3,0xa6d4,0xa6d5,0xa6d6,0xa6d7, + 0xa6d8,0xa6d9,0xa6da,0xa6db,0xa6dc,0xa6dd,0xa6de,0xa6df, + 0xa6e0,0xa6e1,0xa6e2,0xa6e3,0xa6e4,0xa6e5,0xa6e6,0xa6e7, + 0xa6e8,0xa6e9,0xa6ea,0xa6eb,0xa6ec,0xa6ed,0xa6ee,0xa6ef, + 0xa6f0,0xa6f1,0xa6f2,0xa6f3,0xa6f4,0xa6f5,0xa6f6,0xa6f7, + 0xa6f8,0xa6f9,0xa6fa,0xa6fb,0xa6fc,0xa6fd,0xa6fe,0xa6ff, + 0xa700,0xa701,0xa702,0xa703,0xa704,0xa705,0xa706,0xa707, + 0xa708,0xa709,0xa70a,0xa70b,0xa70c,0xa70d,0xa70e,0xa70f, + 0xa710,0xa711,0xa712,0xa713,0xa714,0xa715,0xa716,0xa717, + 0xa718,0xa719,0xa71a,0xa71b,0xa71c,0xa71d,0xa71e,0xa71f, + 0xa720,0xa721,0xa722,0xa723,0xa724,0xa725,0xa726,0xa727, + 0xa728,0xa729,0xa72a,0xa72b,0xa72c,0xa72d,0xa72e,0xa72f, + 0xa730,0xa731,0xa732,0xa733,0xa734,0xa735,0xa736,0xa737, + 0xa738,0xa739,0xa73a,0xa73b,0xa73c,0xa73d,0xa73e,0xa73f, + 0xa740,0xa741,0xa742,0xa743,0xa744,0xa745,0xa746,0xa747, + 0xa748,0xa749,0xa74a,0xa74b,0xa74c,0xa74d,0xa74e,0xa74f, + 0xa750,0xa751,0xa752,0xa753,0xa754,0xa755,0xa756,0xa757, + 0xa758,0xa759,0xa75a,0xa75b,0xa75c,0xa75d,0xa75e,0xa75f, + 0xa760,0xa761,0xa762,0xa763,0xa764,0xa765,0xa766,0xa767, + 0xa768,0xa769,0xa76a,0xa76b,0xa76c,0xa76d,0xa76e,0xa76f, + 0xa770,0xa771,0xa772,0xa773,0xa774,0xa775,0xa776,0xa777, + 0xa778,0xa779,0xa77a,0xa77b,0xa77c,0xa77d,0xa77e,0xa77f, + 0xa780,0xa781,0xa782,0xa783,0xa784,0xa785,0xa786,0xa787, + 0xa788,0xa789,0xa78a,0xa78b,0xa78c,0xa78d,0xa78e,0xa78f, + 0xa790,0xa791,0xa792,0xa793,0xa794,0xa795,0xa796,0xa797, + 0xa798,0xa799,0xa79a,0xa79b,0xa79c,0xa79d,0xa79e,0xa79f, + 0xa7a0,0xa7a1,0xa7a2,0xa7a3,0xa7a4,0xa7a5,0xa7a6,0xa7a7, + 0xa7a8,0xa7a9,0xa7aa,0xa7ab,0xa7ac,0xa7ad,0xa7ae,0xa7af, + 0xa7b0,0xa7b1,0xa7b2,0xa7b3,0xa7b4,0xa7b5,0xa7b6,0xa7b7, + 0xa7b8,0xa7b9,0xa7ba,0xa7bb,0xa7bc,0xa7bd,0xa7be,0xa7bf, + 0xa7c0,0xa7c1,0xa7c2,0xa7c3,0xa7c4,0xa7c5,0xa7c6,0xa7c7, + 0xa7c8,0xa7c9,0xa7ca,0xa7cb,0xa7cc,0xa7cd,0xa7ce,0xa7cf, + 0xa7d0,0xa7d1,0xa7d2,0xa7d3,0xa7d4,0xa7d5,0xa7d6,0xa7d7, + 0xa7d8,0xa7d9,0xa7da,0xa7db,0xa7dc,0xa7dd,0xa7de,0xa7df, + 0xa7e0,0xa7e1,0xa7e2,0xa7e3,0xa7e4,0xa7e5,0xa7e6,0xa7e7, + 0xa7e8,0xa7e9,0xa7ea,0xa7eb,0xa7ec,0xa7ed,0xa7ee,0xa7ef, + 0xa7f0,0xa7f1,0xa7f2,0xa7f3,0xa7f4,0xa7f5,0xa7f6,0xa7f7, + 0xa7f8,0xa7f9,0xa7fa,0xa7fb,0xa7fc,0xa7fd,0xa7fe,0xa7ff, + 0xa800,0xa801,0xa802,0xa803,0xa804,0xa805,0xa806,0xa807, + 0xa808,0xa809,0xa80a,0xa80b,0xa80c,0xa80d,0xa80e,0xa80f, + 0xa810,0xa811,0xa812,0xa813,0xa814,0xa815,0xa816,0xa817, + 0xa818,0xa819,0xa81a,0xa81b,0xa81c,0xa81d,0xa81e,0xa81f, + 0xa820,0xa821,0xa822,0xa823,0xa824,0xa825,0xa826,0xa827, + 0xa828,0xa829,0xa82a,0xa82b,0xa82c,0xa82d,0xa82e,0xa82f, + 0xa830,0xa831,0xa832,0xa833,0xa834,0xa835,0xa836,0xa837, + 0xa838,0xa839,0xa83a,0xa83b,0xa83c,0xa83d,0xa83e,0xa83f, + 0xa840,0xa841,0xa842,0xa843,0xa844,0xa845,0xa846,0xa847, + 0xa848,0xa849,0xa84a,0xa84b,0xa84c,0xa84d,0xa84e,0xa84f, + 0xa850,0xa851,0xa852,0xa853,0xa854,0xa855,0xa856,0xa857, + 0xa858,0xa859,0xa85a,0xa85b,0xa85c,0xa85d,0xa85e,0xa85f, + 0xa860,0xa861,0xa862,0xa863,0xa864,0xa865,0xa866,0xa867, + 0xa868,0xa869,0xa86a,0xa86b,0xa86c,0xa86d,0xa86e,0xa86f, + 0xa870,0xa871,0xa872,0xa873,0xa874,0xa875,0xa876,0xa877, + 0xa878,0xa879,0xa87a,0xa87b,0xa87c,0xa87d,0xa87e,0xa87f, + 0xa880,0xa881,0xa882,0xa883,0xa884,0xa885,0xa886,0xa887, + 0xa888,0xa889,0xa88a,0xa88b,0xa88c,0xa88d,0xa88e,0xa88f, + 0xa890,0xa891,0xa892,0xa893,0xa894,0xa895,0xa896,0xa897, + 0xa898,0xa899,0xa89a,0xa89b,0xa89c,0xa89d,0xa89e,0xa89f, + 0xa8a0,0xa8a1,0xa8a2,0xa8a3,0xa8a4,0xa8a5,0xa8a6,0xa8a7, + 0xa8a8,0xa8a9,0xa8aa,0xa8ab,0xa8ac,0xa8ad,0xa8ae,0xa8af, + 0xa8b0,0xa8b1,0xa8b2,0xa8b3,0xa8b4,0xa8b5,0xa8b6,0xa8b7, + 0xa8b8,0xa8b9,0xa8ba,0xa8bb,0xa8bc,0xa8bd,0xa8be,0xa8bf, + 0xa8c0,0xa8c1,0xa8c2,0xa8c3,0xa8c4,0xa8c5,0xa8c6,0xa8c7, + 0xa8c8,0xa8c9,0xa8ca,0xa8cb,0xa8cc,0xa8cd,0xa8ce,0xa8cf, + 0xa8d0,0xa8d1,0xa8d2,0xa8d3,0xa8d4,0xa8d5,0xa8d6,0xa8d7, + 0xa8d8,0xa8d9,0xa8da,0xa8db,0xa8dc,0xa8dd,0xa8de,0xa8df, + 0xa8e0,0xa8e1,0xa8e2,0xa8e3,0xa8e4,0xa8e5,0xa8e6,0xa8e7, + 0xa8e8,0xa8e9,0xa8ea,0xa8eb,0xa8ec,0xa8ed,0xa8ee,0xa8ef, + 0xa8f0,0xa8f1,0xa8f2,0xa8f3,0xa8f4,0xa8f5,0xa8f6,0xa8f7, + 0xa8f8,0xa8f9,0xa8fa,0xa8fb,0xa8fc,0xa8fd,0xa8fe,0xa8ff, + 0xa900,0xa901,0xa902,0xa903,0xa904,0xa905,0xa906,0xa907, + 0xa908,0xa909,0xa90a,0xa90b,0xa90c,0xa90d,0xa90e,0xa90f, + 0xa910,0xa911,0xa912,0xa913,0xa914,0xa915,0xa916,0xa917, + 0xa918,0xa919,0xa91a,0xa91b,0xa91c,0xa91d,0xa91e,0xa91f, + 0xa920,0xa921,0xa922,0xa923,0xa924,0xa925,0xa926,0xa927, + 0xa928,0xa929,0xa92a,0xa92b,0xa92c,0xa92d,0xa92e,0xa92f, + 0xa930,0xa931,0xa932,0xa933,0xa934,0xa935,0xa936,0xa937, + 0xa938,0xa939,0xa93a,0xa93b,0xa93c,0xa93d,0xa93e,0xa93f, + 0xa940,0xa941,0xa942,0xa943,0xa944,0xa945,0xa946,0xa947, + 0xa948,0xa949,0xa94a,0xa94b,0xa94c,0xa94d,0xa94e,0xa94f, + 0xa950,0xa951,0xa952,0xa953,0xa954,0xa955,0xa956,0xa957, + 0xa958,0xa959,0xa95a,0xa95b,0xa95c,0xa95d,0xa95e,0xa95f, + 0xa960,0xa961,0xa962,0xa963,0xa964,0xa965,0xa966,0xa967, + 0xa968,0xa969,0xa96a,0xa96b,0xa96c,0xa96d,0xa96e,0xa96f, + 0xa970,0xa971,0xa972,0xa973,0xa974,0xa975,0xa976,0xa977, + 0xa978,0xa979,0xa97a,0xa97b,0xa97c,0xa97d,0xa97e,0xa97f, + 0xa980,0xa981,0xa982,0xa983,0xa984,0xa985,0xa986,0xa987, + 0xa988,0xa989,0xa98a,0xa98b,0xa98c,0xa98d,0xa98e,0xa98f, + 0xa990,0xa991,0xa992,0xa993,0xa994,0xa995,0xa996,0xa997, + 0xa998,0xa999,0xa99a,0xa99b,0xa99c,0xa99d,0xa99e,0xa99f, + 0xa9a0,0xa9a1,0xa9a2,0xa9a3,0xa9a4,0xa9a5,0xa9a6,0xa9a7, + 0xa9a8,0xa9a9,0xa9aa,0xa9ab,0xa9ac,0xa9ad,0xa9ae,0xa9af, + 0xa9b0,0xa9b1,0xa9b2,0xa9b3,0xa9b4,0xa9b5,0xa9b6,0xa9b7, + 0xa9b8,0xa9b9,0xa9ba,0xa9bb,0xa9bc,0xa9bd,0xa9be,0xa9bf, + 0xa9c0,0xa9c1,0xa9c2,0xa9c3,0xa9c4,0xa9c5,0xa9c6,0xa9c7, + 0xa9c8,0xa9c9,0xa9ca,0xa9cb,0xa9cc,0xa9cd,0xa9ce,0xa9cf, + 0xa9d0,0xa9d1,0xa9d2,0xa9d3,0xa9d4,0xa9d5,0xa9d6,0xa9d7, + 0xa9d8,0xa9d9,0xa9da,0xa9db,0xa9dc,0xa9dd,0xa9de,0xa9df, + 0xa9e0,0xa9e1,0xa9e2,0xa9e3,0xa9e4,0xa9e5,0xa9e6,0xa9e7, + 0xa9e8,0xa9e9,0xa9ea,0xa9eb,0xa9ec,0xa9ed,0xa9ee,0xa9ef, + 0xa9f0,0xa9f1,0xa9f2,0xa9f3,0xa9f4,0xa9f5,0xa9f6,0xa9f7, + 0xa9f8,0xa9f9,0xa9fa,0xa9fb,0xa9fc,0xa9fd,0xa9fe,0xa9ff, + 0xaa00,0xaa01,0xaa02,0xaa03,0xaa04,0xaa05,0xaa06,0xaa07, + 0xaa08,0xaa09,0xaa0a,0xaa0b,0xaa0c,0xaa0d,0xaa0e,0xaa0f, + 0xaa10,0xaa11,0xaa12,0xaa13,0xaa14,0xaa15,0xaa16,0xaa17, + 0xaa18,0xaa19,0xaa1a,0xaa1b,0xaa1c,0xaa1d,0xaa1e,0xaa1f, + 0xaa20,0xaa21,0xaa22,0xaa23,0xaa24,0xaa25,0xaa26,0xaa27, + 0xaa28,0xaa29,0xaa2a,0xaa2b,0xaa2c,0xaa2d,0xaa2e,0xaa2f, + 0xaa30,0xaa31,0xaa32,0xaa33,0xaa34,0xaa35,0xaa36,0xaa37, + 0xaa38,0xaa39,0xaa3a,0xaa3b,0xaa3c,0xaa3d,0xaa3e,0xaa3f, + 0xaa40,0xaa41,0xaa42,0xaa43,0xaa44,0xaa45,0xaa46,0xaa47, + 0xaa48,0xaa49,0xaa4a,0xaa4b,0xaa4c,0xaa4d,0xaa4e,0xaa4f, + 0xaa50,0xaa51,0xaa52,0xaa53,0xaa54,0xaa55,0xaa56,0xaa57, + 0xaa58,0xaa59,0xaa5a,0xaa5b,0xaa5c,0xaa5d,0xaa5e,0xaa5f, + 0xaa60,0xaa61,0xaa62,0xaa63,0xaa64,0xaa65,0xaa66,0xaa67, + 0xaa68,0xaa69,0xaa6a,0xaa6b,0xaa6c,0xaa6d,0xaa6e,0xaa6f, + 0xaa70,0xaa71,0xaa72,0xaa73,0xaa74,0xaa75,0xaa76,0xaa77, + 0xaa78,0xaa79,0xaa7a,0xaa7b,0xaa7c,0xaa7d,0xaa7e,0xaa7f, + 0xaa80,0xaa81,0xaa82,0xaa83,0xaa84,0xaa85,0xaa86,0xaa87, + 0xaa88,0xaa89,0xaa8a,0xaa8b,0xaa8c,0xaa8d,0xaa8e,0xaa8f, + 0xaa90,0xaa91,0xaa92,0xaa93,0xaa94,0xaa95,0xaa96,0xaa97, + 0xaa98,0xaa99,0xaa9a,0xaa9b,0xaa9c,0xaa9d,0xaa9e,0xaa9f, + 0xaaa0,0xaaa1,0xaaa2,0xaaa3,0xaaa4,0xaaa5,0xaaa6,0xaaa7, + 0xaaa8,0xaaa9,0xaaaa,0xaaab,0xaaac,0xaaad,0xaaae,0xaaaf, + 0xaab0,0xaab1,0xaab2,0xaab3,0xaab4,0xaab5,0xaab6,0xaab7, + 0xaab8,0xaab9,0xaaba,0xaabb,0xaabc,0xaabd,0xaabe,0xaabf, + 0xaac0,0xaac1,0xaac2,0xaac3,0xaac4,0xaac5,0xaac6,0xaac7, + 0xaac8,0xaac9,0xaaca,0xaacb,0xaacc,0xaacd,0xaace,0xaacf, + 0xaad0,0xaad1,0xaad2,0xaad3,0xaad4,0xaad5,0xaad6,0xaad7, + 0xaad8,0xaad9,0xaada,0xaadb,0xaadc,0xaadd,0xaade,0xaadf, + 0xaae0,0xaae1,0xaae2,0xaae3,0xaae4,0xaae5,0xaae6,0xaae7, + 0xaae8,0xaae9,0xaaea,0xaaeb,0xaaec,0xaaed,0xaaee,0xaaef, + 0xaaf0,0xaaf1,0xaaf2,0xaaf3,0xaaf4,0xaaf5,0xaaf6,0xaaf7, + 0xaaf8,0xaaf9,0xaafa,0xaafb,0xaafc,0xaafd,0xaafe,0xaaff, + 0xab00,0xab01,0xab02,0xab03,0xab04,0xab05,0xab06,0xab07, + 0xab08,0xab09,0xab0a,0xab0b,0xab0c,0xab0d,0xab0e,0xab0f, + 0xab10,0xab11,0xab12,0xab13,0xab14,0xab15,0xab16,0xab17, + 0xab18,0xab19,0xab1a,0xab1b,0xab1c,0xab1d,0xab1e,0xab1f, + 0xab20,0xab21,0xab22,0xab23,0xab24,0xab25,0xab26,0xab27, + 0xab28,0xab29,0xab2a,0xab2b,0xab2c,0xab2d,0xab2e,0xab2f, + 0xab30,0xab31,0xab32,0xab33,0xab34,0xab35,0xab36,0xab37, + 0xab38,0xab39,0xab3a,0xab3b,0xab3c,0xab3d,0xab3e,0xab3f, + 0xab40,0xab41,0xab42,0xab43,0xab44,0xab45,0xab46,0xab47, + 0xab48,0xab49,0xab4a,0xab4b,0xab4c,0xab4d,0xab4e,0xab4f, + 0xab50,0xab51,0xab52,0xab53,0xab54,0xab55,0xab56,0xab57, + 0xab58,0xab59,0xab5a,0xab5b,0xab5c,0xab5d,0xab5e,0xab5f, + 0xab60,0xab61,0xab62,0xab63,0xab64,0xab65,0xab66,0xab67, + 0xab68,0xab69,0xab6a,0xab6b,0xab6c,0xab6d,0xab6e,0xab6f, + 0xab70,0xab71,0xab72,0xab73,0xab74,0xab75,0xab76,0xab77, + 0xab78,0xab79,0xab7a,0xab7b,0xab7c,0xab7d,0xab7e,0xab7f, + 0xab80,0xab81,0xab82,0xab83,0xab84,0xab85,0xab86,0xab87, + 0xab88,0xab89,0xab8a,0xab8b,0xab8c,0xab8d,0xab8e,0xab8f, + 0xab90,0xab91,0xab92,0xab93,0xab94,0xab95,0xab96,0xab97, + 0xab98,0xab99,0xab9a,0xab9b,0xab9c,0xab9d,0xab9e,0xab9f, + 0xaba0,0xaba1,0xaba2,0xaba3,0xaba4,0xaba5,0xaba6,0xaba7, + 0xaba8,0xaba9,0xabaa,0xabab,0xabac,0xabad,0xabae,0xabaf, + 0xabb0,0xabb1,0xabb2,0xabb3,0xabb4,0xabb5,0xabb6,0xabb7, + 0xabb8,0xabb9,0xabba,0xabbb,0xabbc,0xabbd,0xabbe,0xabbf, + 0xabc0,0xabc1,0xabc2,0xabc3,0xabc4,0xabc5,0xabc6,0xabc7, + 0xabc8,0xabc9,0xabca,0xabcb,0xabcc,0xabcd,0xabce,0xabcf, + 0xabd0,0xabd1,0xabd2,0xabd3,0xabd4,0xabd5,0xabd6,0xabd7, + 0xabd8,0xabd9,0xabda,0xabdb,0xabdc,0xabdd,0xabde,0xabdf, + 0xabe0,0xabe1,0xabe2,0xabe3,0xabe4,0xabe5,0xabe6,0xabe7, + 0xabe8,0xabe9,0xabea,0xabeb,0xabec,0xabed,0xabee,0xabef, + 0xabf0,0xabf1,0xabf2,0xabf3,0xabf4,0xabf5,0xabf6,0xabf7, + 0xabf8,0xabf9,0xabfa,0xabfb,0xabfc,0xabfd,0xabfe,0xabff, + 0xac00,0xac01,0xac02,0xac03,0xac04,0xac05,0xac06,0xac07, + 0xac08,0xac09,0xac0a,0xac0b,0xac0c,0xac0d,0xac0e,0xac0f, + 0xac10,0xac11,0xac12,0xac13,0xac14,0xac15,0xac16,0xac17, + 0xac18,0xac19,0xac1a,0xac1b,0xac1c,0xac1d,0xac1e,0xac1f, + 0xac20,0xac21,0xac22,0xac23,0xac24,0xac25,0xac26,0xac27, + 0xac28,0xac29,0xac2a,0xac2b,0xac2c,0xac2d,0xac2e,0xac2f, + 0xac30,0xac31,0xac32,0xac33,0xac34,0xac35,0xac36,0xac37, + 0xac38,0xac39,0xac3a,0xac3b,0xac3c,0xac3d,0xac3e,0xac3f, + 0xac40,0xac41,0xac42,0xac43,0xac44,0xac45,0xac46,0xac47, + 0xac48,0xac49,0xac4a,0xac4b,0xac4c,0xac4d,0xac4e,0xac4f, + 0xac50,0xac51,0xac52,0xac53,0xac54,0xac55,0xac56,0xac57, + 0xac58,0xac59,0xac5a,0xac5b,0xac5c,0xac5d,0xac5e,0xac5f, + 0xac60,0xac61,0xac62,0xac63,0xac64,0xac65,0xac66,0xac67, + 0xac68,0xac69,0xac6a,0xac6b,0xac6c,0xac6d,0xac6e,0xac6f, + 0xac70,0xac71,0xac72,0xac73,0xac74,0xac75,0xac76,0xac77, + 0xac78,0xac79,0xac7a,0xac7b,0xac7c,0xac7d,0xac7e,0xac7f, + 0xac80,0xac81,0xac82,0xac83,0xac84,0xac85,0xac86,0xac87, + 0xac88,0xac89,0xac8a,0xac8b,0xac8c,0xac8d,0xac8e,0xac8f, + 0xac90,0xac91,0xac92,0xac93,0xac94,0xac95,0xac96,0xac97, + 0xac98,0xac99,0xac9a,0xac9b,0xac9c,0xac9d,0xac9e,0xac9f, + 0xaca0,0xaca1,0xaca2,0xaca3,0xaca4,0xaca5,0xaca6,0xaca7, + 0xaca8,0xaca9,0xacaa,0xacab,0xacac,0xacad,0xacae,0xacaf, + 0xacb0,0xacb1,0xacb2,0xacb3,0xacb4,0xacb5,0xacb6,0xacb7, + 0xacb8,0xacb9,0xacba,0xacbb,0xacbc,0xacbd,0xacbe,0xacbf, + 0xacc0,0xacc1,0xacc2,0xacc3,0xacc4,0xacc5,0xacc6,0xacc7, + 0xacc8,0xacc9,0xacca,0xaccb,0xaccc,0xaccd,0xacce,0xaccf, + 0xacd0,0xacd1,0xacd2,0xacd3,0xacd4,0xacd5,0xacd6,0xacd7, + 0xacd8,0xacd9,0xacda,0xacdb,0xacdc,0xacdd,0xacde,0xacdf, + 0xace0,0xace1,0xace2,0xace3,0xace4,0xace5,0xace6,0xace7, + 0xace8,0xace9,0xacea,0xaceb,0xacec,0xaced,0xacee,0xacef, + 0xacf0,0xacf1,0xacf2,0xacf3,0xacf4,0xacf5,0xacf6,0xacf7, + 0xacf8,0xacf9,0xacfa,0xacfb,0xacfc,0xacfd,0xacfe,0xacff, + 0xad00,0xad01,0xad02,0xad03,0xad04,0xad05,0xad06,0xad07, + 0xad08,0xad09,0xad0a,0xad0b,0xad0c,0xad0d,0xad0e,0xad0f, + 0xad10,0xad11,0xad12,0xad13,0xad14,0xad15,0xad16,0xad17, + 0xad18,0xad19,0xad1a,0xad1b,0xad1c,0xad1d,0xad1e,0xad1f, + 0xad20,0xad21,0xad22,0xad23,0xad24,0xad25,0xad26,0xad27, + 0xad28,0xad29,0xad2a,0xad2b,0xad2c,0xad2d,0xad2e,0xad2f, + 0xad30,0xad31,0xad32,0xad33,0xad34,0xad35,0xad36,0xad37, + 0xad38,0xad39,0xad3a,0xad3b,0xad3c,0xad3d,0xad3e,0xad3f, + 0xad40,0xad41,0xad42,0xad43,0xad44,0xad45,0xad46,0xad47, + 0xad48,0xad49,0xad4a,0xad4b,0xad4c,0xad4d,0xad4e,0xad4f, + 0xad50,0xad51,0xad52,0xad53,0xad54,0xad55,0xad56,0xad57, + 0xad58,0xad59,0xad5a,0xad5b,0xad5c,0xad5d,0xad5e,0xad5f, + 0xad60,0xad61,0xad62,0xad63,0xad64,0xad65,0xad66,0xad67, + 0xad68,0xad69,0xad6a,0xad6b,0xad6c,0xad6d,0xad6e,0xad6f, + 0xad70,0xad71,0xad72,0xad73,0xad74,0xad75,0xad76,0xad77, + 0xad78,0xad79,0xad7a,0xad7b,0xad7c,0xad7d,0xad7e,0xad7f, + 0xad80,0xad81,0xad82,0xad83,0xad84,0xad85,0xad86,0xad87, + 0xad88,0xad89,0xad8a,0xad8b,0xad8c,0xad8d,0xad8e,0xad8f, + 0xad90,0xad91,0xad92,0xad93,0xad94,0xad95,0xad96,0xad97, + 0xad98,0xad99,0xad9a,0xad9b,0xad9c,0xad9d,0xad9e,0xad9f, + 0xada0,0xada1,0xada2,0xada3,0xada4,0xada5,0xada6,0xada7, + 0xada8,0xada9,0xadaa,0xadab,0xadac,0xadad,0xadae,0xadaf, + 0xadb0,0xadb1,0xadb2,0xadb3,0xadb4,0xadb5,0xadb6,0xadb7, + 0xadb8,0xadb9,0xadba,0xadbb,0xadbc,0xadbd,0xadbe,0xadbf, + 0xadc0,0xadc1,0xadc2,0xadc3,0xadc4,0xadc5,0xadc6,0xadc7, + 0xadc8,0xadc9,0xadca,0xadcb,0xadcc,0xadcd,0xadce,0xadcf, + 0xadd0,0xadd1,0xadd2,0xadd3,0xadd4,0xadd5,0xadd6,0xadd7, + 0xadd8,0xadd9,0xadda,0xaddb,0xaddc,0xaddd,0xadde,0xaddf, + 0xade0,0xade1,0xade2,0xade3,0xade4,0xade5,0xade6,0xade7, + 0xade8,0xade9,0xadea,0xadeb,0xadec,0xaded,0xadee,0xadef, + 0xadf0,0xadf1,0xadf2,0xadf3,0xadf4,0xadf5,0xadf6,0xadf7, + 0xadf8,0xadf9,0xadfa,0xadfb,0xadfc,0xadfd,0xadfe,0xadff, + 0xae00,0xae01,0xae02,0xae03,0xae04,0xae05,0xae06,0xae07, + 0xae08,0xae09,0xae0a,0xae0b,0xae0c,0xae0d,0xae0e,0xae0f, + 0xae10,0xae11,0xae12,0xae13,0xae14,0xae15,0xae16,0xae17, + 0xae18,0xae19,0xae1a,0xae1b,0xae1c,0xae1d,0xae1e,0xae1f, + 0xae20,0xae21,0xae22,0xae23,0xae24,0xae25,0xae26,0xae27, + 0xae28,0xae29,0xae2a,0xae2b,0xae2c,0xae2d,0xae2e,0xae2f, + 0xae30,0xae31,0xae32,0xae33,0xae34,0xae35,0xae36,0xae37, + 0xae38,0xae39,0xae3a,0xae3b,0xae3c,0xae3d,0xae3e,0xae3f, + 0xae40,0xae41,0xae42,0xae43,0xae44,0xae45,0xae46,0xae47, + 0xae48,0xae49,0xae4a,0xae4b,0xae4c,0xae4d,0xae4e,0xae4f, + 0xae50,0xae51,0xae52,0xae53,0xae54,0xae55,0xae56,0xae57, + 0xae58,0xae59,0xae5a,0xae5b,0xae5c,0xae5d,0xae5e,0xae5f, + 0xae60,0xae61,0xae62,0xae63,0xae64,0xae65,0xae66,0xae67, + 0xae68,0xae69,0xae6a,0xae6b,0xae6c,0xae6d,0xae6e,0xae6f, + 0xae70,0xae71,0xae72,0xae73,0xae74,0xae75,0xae76,0xae77, + 0xae78,0xae79,0xae7a,0xae7b,0xae7c,0xae7d,0xae7e,0xae7f, + 0xae80,0xae81,0xae82,0xae83,0xae84,0xae85,0xae86,0xae87, + 0xae88,0xae89,0xae8a,0xae8b,0xae8c,0xae8d,0xae8e,0xae8f, + 0xae90,0xae91,0xae92,0xae93,0xae94,0xae95,0xae96,0xae97, + 0xae98,0xae99,0xae9a,0xae9b,0xae9c,0xae9d,0xae9e,0xae9f, + 0xaea0,0xaea1,0xaea2,0xaea3,0xaea4,0xaea5,0xaea6,0xaea7, + 0xaea8,0xaea9,0xaeaa,0xaeab,0xaeac,0xaead,0xaeae,0xaeaf, + 0xaeb0,0xaeb1,0xaeb2,0xaeb3,0xaeb4,0xaeb5,0xaeb6,0xaeb7, + 0xaeb8,0xaeb9,0xaeba,0xaebb,0xaebc,0xaebd,0xaebe,0xaebf, + 0xaec0,0xaec1,0xaec2,0xaec3,0xaec4,0xaec5,0xaec6,0xaec7, + 0xaec8,0xaec9,0xaeca,0xaecb,0xaecc,0xaecd,0xaece,0xaecf, + 0xaed0,0xaed1,0xaed2,0xaed3,0xaed4,0xaed5,0xaed6,0xaed7, + 0xaed8,0xaed9,0xaeda,0xaedb,0xaedc,0xaedd,0xaede,0xaedf, + 0xaee0,0xaee1,0xaee2,0xaee3,0xaee4,0xaee5,0xaee6,0xaee7, + 0xaee8,0xaee9,0xaeea,0xaeeb,0xaeec,0xaeed,0xaeee,0xaeef, + 0xaef0,0xaef1,0xaef2,0xaef3,0xaef4,0xaef5,0xaef6,0xaef7, + 0xaef8,0xaef9,0xaefa,0xaefb,0xaefc,0xaefd,0xaefe,0xaeff, + 0xaf00,0xaf01,0xaf02,0xaf03,0xaf04,0xaf05,0xaf06,0xaf07, + 0xaf08,0xaf09,0xaf0a,0xaf0b,0xaf0c,0xaf0d,0xaf0e,0xaf0f, + 0xaf10,0xaf11,0xaf12,0xaf13,0xaf14,0xaf15,0xaf16,0xaf17, + 0xaf18,0xaf19,0xaf1a,0xaf1b,0xaf1c,0xaf1d,0xaf1e,0xaf1f, + 0xaf20,0xaf21,0xaf22,0xaf23,0xaf24,0xaf25,0xaf26,0xaf27, + 0xaf28,0xaf29,0xaf2a,0xaf2b,0xaf2c,0xaf2d,0xaf2e,0xaf2f, + 0xaf30,0xaf31,0xaf32,0xaf33,0xaf34,0xaf35,0xaf36,0xaf37, + 0xaf38,0xaf39,0xaf3a,0xaf3b,0xaf3c,0xaf3d,0xaf3e,0xaf3f, + 0xaf40,0xaf41,0xaf42,0xaf43,0xaf44,0xaf45,0xaf46,0xaf47, + 0xaf48,0xaf49,0xaf4a,0xaf4b,0xaf4c,0xaf4d,0xaf4e,0xaf4f, + 0xaf50,0xaf51,0xaf52,0xaf53,0xaf54,0xaf55,0xaf56,0xaf57, + 0xaf58,0xaf59,0xaf5a,0xaf5b,0xaf5c,0xaf5d,0xaf5e,0xaf5f, + 0xaf60,0xaf61,0xaf62,0xaf63,0xaf64,0xaf65,0xaf66,0xaf67, + 0xaf68,0xaf69,0xaf6a,0xaf6b,0xaf6c,0xaf6d,0xaf6e,0xaf6f, + 0xaf70,0xaf71,0xaf72,0xaf73,0xaf74,0xaf75,0xaf76,0xaf77, + 0xaf78,0xaf79,0xaf7a,0xaf7b,0xaf7c,0xaf7d,0xaf7e,0xaf7f, + 0xaf80,0xaf81,0xaf82,0xaf83,0xaf84,0xaf85,0xaf86,0xaf87, + 0xaf88,0xaf89,0xaf8a,0xaf8b,0xaf8c,0xaf8d,0xaf8e,0xaf8f, + 0xaf90,0xaf91,0xaf92,0xaf93,0xaf94,0xaf95,0xaf96,0xaf97, + 0xaf98,0xaf99,0xaf9a,0xaf9b,0xaf9c,0xaf9d,0xaf9e,0xaf9f, + 0xafa0,0xafa1,0xafa2,0xafa3,0xafa4,0xafa5,0xafa6,0xafa7, + 0xafa8,0xafa9,0xafaa,0xafab,0xafac,0xafad,0xafae,0xafaf, + 0xafb0,0xafb1,0xafb2,0xafb3,0xafb4,0xafb5,0xafb6,0xafb7, + 0xafb8,0xafb9,0xafba,0xafbb,0xafbc,0xafbd,0xafbe,0xafbf, + 0xafc0,0xafc1,0xafc2,0xafc3,0xafc4,0xafc5,0xafc6,0xafc7, + 0xafc8,0xafc9,0xafca,0xafcb,0xafcc,0xafcd,0xafce,0xafcf, + 0xafd0,0xafd1,0xafd2,0xafd3,0xafd4,0xafd5,0xafd6,0xafd7, + 0xafd8,0xafd9,0xafda,0xafdb,0xafdc,0xafdd,0xafde,0xafdf, + 0xafe0,0xafe1,0xafe2,0xafe3,0xafe4,0xafe5,0xafe6,0xafe7, + 0xafe8,0xafe9,0xafea,0xafeb,0xafec,0xafed,0xafee,0xafef, + 0xaff0,0xaff1,0xaff2,0xaff3,0xaff4,0xaff5,0xaff6,0xaff7, + 0xaff8,0xaff9,0xaffa,0xaffb,0xaffc,0xaffd,0xaffe,0xafff, + 0xb000,0xb001,0xb002,0xb003,0xb004,0xb005,0xb006,0xb007, + 0xb008,0xb009,0xb00a,0xb00b,0xb00c,0xb00d,0xb00e,0xb00f, + 0xb010,0xb011,0xb012,0xb013,0xb014,0xb015,0xb016,0xb017, + 0xb018,0xb019,0xb01a,0xb01b,0xb01c,0xb01d,0xb01e,0xb01f, + 0xb020,0xb021,0xb022,0xb023,0xb024,0xb025,0xb026,0xb027, + 0xb028,0xb029,0xb02a,0xb02b,0xb02c,0xb02d,0xb02e,0xb02f, + 0xb030,0xb031,0xb032,0xb033,0xb034,0xb035,0xb036,0xb037, + 0xb038,0xb039,0xb03a,0xb03b,0xb03c,0xb03d,0xb03e,0xb03f, + 0xb040,0xb041,0xb042,0xb043,0xb044,0xb045,0xb046,0xb047, + 0xb048,0xb049,0xb04a,0xb04b,0xb04c,0xb04d,0xb04e,0xb04f, + 0xb050,0xb051,0xb052,0xb053,0xb054,0xb055,0xb056,0xb057, + 0xb058,0xb059,0xb05a,0xb05b,0xb05c,0xb05d,0xb05e,0xb05f, + 0xb060,0xb061,0xb062,0xb063,0xb064,0xb065,0xb066,0xb067, + 0xb068,0xb069,0xb06a,0xb06b,0xb06c,0xb06d,0xb06e,0xb06f, + 0xb070,0xb071,0xb072,0xb073,0xb074,0xb075,0xb076,0xb077, + 0xb078,0xb079,0xb07a,0xb07b,0xb07c,0xb07d,0xb07e,0xb07f, + 0xb080,0xb081,0xb082,0xb083,0xb084,0xb085,0xb086,0xb087, + 0xb088,0xb089,0xb08a,0xb08b,0xb08c,0xb08d,0xb08e,0xb08f, + 0xb090,0xb091,0xb092,0xb093,0xb094,0xb095,0xb096,0xb097, + 0xb098,0xb099,0xb09a,0xb09b,0xb09c,0xb09d,0xb09e,0xb09f, + 0xb0a0,0xb0a1,0xb0a2,0xb0a3,0xb0a4,0xb0a5,0xb0a6,0xb0a7, + 0xb0a8,0xb0a9,0xb0aa,0xb0ab,0xb0ac,0xb0ad,0xb0ae,0xb0af, + 0xb0b0,0xb0b1,0xb0b2,0xb0b3,0xb0b4,0xb0b5,0xb0b6,0xb0b7, + 0xb0b8,0xb0b9,0xb0ba,0xb0bb,0xb0bc,0xb0bd,0xb0be,0xb0bf, + 0xb0c0,0xb0c1,0xb0c2,0xb0c3,0xb0c4,0xb0c5,0xb0c6,0xb0c7, + 0xb0c8,0xb0c9,0xb0ca,0xb0cb,0xb0cc,0xb0cd,0xb0ce,0xb0cf, + 0xb0d0,0xb0d1,0xb0d2,0xb0d3,0xb0d4,0xb0d5,0xb0d6,0xb0d7, + 0xb0d8,0xb0d9,0xb0da,0xb0db,0xb0dc,0xb0dd,0xb0de,0xb0df, + 0xb0e0,0xb0e1,0xb0e2,0xb0e3,0xb0e4,0xb0e5,0xb0e6,0xb0e7, + 0xb0e8,0xb0e9,0xb0ea,0xb0eb,0xb0ec,0xb0ed,0xb0ee,0xb0ef, + 0xb0f0,0xb0f1,0xb0f2,0xb0f3,0xb0f4,0xb0f5,0xb0f6,0xb0f7, + 0xb0f8,0xb0f9,0xb0fa,0xb0fb,0xb0fc,0xb0fd,0xb0fe,0xb0ff, + 0xb100,0xb101,0xb102,0xb103,0xb104,0xb105,0xb106,0xb107, + 0xb108,0xb109,0xb10a,0xb10b,0xb10c,0xb10d,0xb10e,0xb10f, + 0xb110,0xb111,0xb112,0xb113,0xb114,0xb115,0xb116,0xb117, + 0xb118,0xb119,0xb11a,0xb11b,0xb11c,0xb11d,0xb11e,0xb11f, + 0xb120,0xb121,0xb122,0xb123,0xb124,0xb125,0xb126,0xb127, + 0xb128,0xb129,0xb12a,0xb12b,0xb12c,0xb12d,0xb12e,0xb12f, + 0xb130,0xb131,0xb132,0xb133,0xb134,0xb135,0xb136,0xb137, + 0xb138,0xb139,0xb13a,0xb13b,0xb13c,0xb13d,0xb13e,0xb13f, + 0xb140,0xb141,0xb142,0xb143,0xb144,0xb145,0xb146,0xb147, + 0xb148,0xb149,0xb14a,0xb14b,0xb14c,0xb14d,0xb14e,0xb14f, + 0xb150,0xb151,0xb152,0xb153,0xb154,0xb155,0xb156,0xb157, + 0xb158,0xb159,0xb15a,0xb15b,0xb15c,0xb15d,0xb15e,0xb15f, + 0xb160,0xb161,0xb162,0xb163,0xb164,0xb165,0xb166,0xb167, + 0xb168,0xb169,0xb16a,0xb16b,0xb16c,0xb16d,0xb16e,0xb16f, + 0xb170,0xb171,0xb172,0xb173,0xb174,0xb175,0xb176,0xb177, + 0xb178,0xb179,0xb17a,0xb17b,0xb17c,0xb17d,0xb17e,0xb17f, + 0xb180,0xb181,0xb182,0xb183,0xb184,0xb185,0xb186,0xb187, + 0xb188,0xb189,0xb18a,0xb18b,0xb18c,0xb18d,0xb18e,0xb18f, + 0xb190,0xb191,0xb192,0xb193,0xb194,0xb195,0xb196,0xb197, + 0xb198,0xb199,0xb19a,0xb19b,0xb19c,0xb19d,0xb19e,0xb19f, + 0xb1a0,0xb1a1,0xb1a2,0xb1a3,0xb1a4,0xb1a5,0xb1a6,0xb1a7, + 0xb1a8,0xb1a9,0xb1aa,0xb1ab,0xb1ac,0xb1ad,0xb1ae,0xb1af, + 0xb1b0,0xb1b1,0xb1b2,0xb1b3,0xb1b4,0xb1b5,0xb1b6,0xb1b7, + 0xb1b8,0xb1b9,0xb1ba,0xb1bb,0xb1bc,0xb1bd,0xb1be,0xb1bf, + 0xb1c0,0xb1c1,0xb1c2,0xb1c3,0xb1c4,0xb1c5,0xb1c6,0xb1c7, + 0xb1c8,0xb1c9,0xb1ca,0xb1cb,0xb1cc,0xb1cd,0xb1ce,0xb1cf, + 0xb1d0,0xb1d1,0xb1d2,0xb1d3,0xb1d4,0xb1d5,0xb1d6,0xb1d7, + 0xb1d8,0xb1d9,0xb1da,0xb1db,0xb1dc,0xb1dd,0xb1de,0xb1df, + 0xb1e0,0xb1e1,0xb1e2,0xb1e3,0xb1e4,0xb1e5,0xb1e6,0xb1e7, + 0xb1e8,0xb1e9,0xb1ea,0xb1eb,0xb1ec,0xb1ed,0xb1ee,0xb1ef, + 0xb1f0,0xb1f1,0xb1f2,0xb1f3,0xb1f4,0xb1f5,0xb1f6,0xb1f7, + 0xb1f8,0xb1f9,0xb1fa,0xb1fb,0xb1fc,0xb1fd,0xb1fe,0xb1ff, + 0xb200,0xb201,0xb202,0xb203,0xb204,0xb205,0xb206,0xb207, + 0xb208,0xb209,0xb20a,0xb20b,0xb20c,0xb20d,0xb20e,0xb20f, + 0xb210,0xb211,0xb212,0xb213,0xb214,0xb215,0xb216,0xb217, + 0xb218,0xb219,0xb21a,0xb21b,0xb21c,0xb21d,0xb21e,0xb21f, + 0xb220,0xb221,0xb222,0xb223,0xb224,0xb225,0xb226,0xb227, + 0xb228,0xb229,0xb22a,0xb22b,0xb22c,0xb22d,0xb22e,0xb22f, + 0xb230,0xb231,0xb232,0xb233,0xb234,0xb235,0xb236,0xb237, + 0xb238,0xb239,0xb23a,0xb23b,0xb23c,0xb23d,0xb23e,0xb23f, + 0xb240,0xb241,0xb242,0xb243,0xb244,0xb245,0xb246,0xb247, + 0xb248,0xb249,0xb24a,0xb24b,0xb24c,0xb24d,0xb24e,0xb24f, + 0xb250,0xb251,0xb252,0xb253,0xb254,0xb255,0xb256,0xb257, + 0xb258,0xb259,0xb25a,0xb25b,0xb25c,0xb25d,0xb25e,0xb25f, + 0xb260,0xb261,0xb262,0xb263,0xb264,0xb265,0xb266,0xb267, + 0xb268,0xb269,0xb26a,0xb26b,0xb26c,0xb26d,0xb26e,0xb26f, + 0xb270,0xb271,0xb272,0xb273,0xb274,0xb275,0xb276,0xb277, + 0xb278,0xb279,0xb27a,0xb27b,0xb27c,0xb27d,0xb27e,0xb27f, + 0xb280,0xb281,0xb282,0xb283,0xb284,0xb285,0xb286,0xb287, + 0xb288,0xb289,0xb28a,0xb28b,0xb28c,0xb28d,0xb28e,0xb28f, + 0xb290,0xb291,0xb292,0xb293,0xb294,0xb295,0xb296,0xb297, + 0xb298,0xb299,0xb29a,0xb29b,0xb29c,0xb29d,0xb29e,0xb29f, + 0xb2a0,0xb2a1,0xb2a2,0xb2a3,0xb2a4,0xb2a5,0xb2a6,0xb2a7, + 0xb2a8,0xb2a9,0xb2aa,0xb2ab,0xb2ac,0xb2ad,0xb2ae,0xb2af, + 0xb2b0,0xb2b1,0xb2b2,0xb2b3,0xb2b4,0xb2b5,0xb2b6,0xb2b7, + 0xb2b8,0xb2b9,0xb2ba,0xb2bb,0xb2bc,0xb2bd,0xb2be,0xb2bf, + 0xb2c0,0xb2c1,0xb2c2,0xb2c3,0xb2c4,0xb2c5,0xb2c6,0xb2c7, + 0xb2c8,0xb2c9,0xb2ca,0xb2cb,0xb2cc,0xb2cd,0xb2ce,0xb2cf, + 0xb2d0,0xb2d1,0xb2d2,0xb2d3,0xb2d4,0xb2d5,0xb2d6,0xb2d7, + 0xb2d8,0xb2d9,0xb2da,0xb2db,0xb2dc,0xb2dd,0xb2de,0xb2df, + 0xb2e0,0xb2e1,0xb2e2,0xb2e3,0xb2e4,0xb2e5,0xb2e6,0xb2e7, + 0xb2e8,0xb2e9,0xb2ea,0xb2eb,0xb2ec,0xb2ed,0xb2ee,0xb2ef, + 0xb2f0,0xb2f1,0xb2f2,0xb2f3,0xb2f4,0xb2f5,0xb2f6,0xb2f7, + 0xb2f8,0xb2f9,0xb2fa,0xb2fb,0xb2fc,0xb2fd,0xb2fe,0xb2ff, + 0xb300,0xb301,0xb302,0xb303,0xb304,0xb305,0xb306,0xb307, + 0xb308,0xb309,0xb30a,0xb30b,0xb30c,0xb30d,0xb30e,0xb30f, + 0xb310,0xb311,0xb312,0xb313,0xb314,0xb315,0xb316,0xb317, + 0xb318,0xb319,0xb31a,0xb31b,0xb31c,0xb31d,0xb31e,0xb31f, + 0xb320,0xb321,0xb322,0xb323,0xb324,0xb325,0xb326,0xb327, + 0xb328,0xb329,0xb32a,0xb32b,0xb32c,0xb32d,0xb32e,0xb32f, + 0xb330,0xb331,0xb332,0xb333,0xb334,0xb335,0xb336,0xb337, + 0xb338,0xb339,0xb33a,0xb33b,0xb33c,0xb33d,0xb33e,0xb33f, + 0xb340,0xb341,0xb342,0xb343,0xb344,0xb345,0xb346,0xb347, + 0xb348,0xb349,0xb34a,0xb34b,0xb34c,0xb34d,0xb34e,0xb34f, + 0xb350,0xb351,0xb352,0xb353,0xb354,0xb355,0xb356,0xb357, + 0xb358,0xb359,0xb35a,0xb35b,0xb35c,0xb35d,0xb35e,0xb35f, + 0xb360,0xb361,0xb362,0xb363,0xb364,0xb365,0xb366,0xb367, + 0xb368,0xb369,0xb36a,0xb36b,0xb36c,0xb36d,0xb36e,0xb36f, + 0xb370,0xb371,0xb372,0xb373,0xb374,0xb375,0xb376,0xb377, + 0xb378,0xb379,0xb37a,0xb37b,0xb37c,0xb37d,0xb37e,0xb37f, + 0xb380,0xb381,0xb382,0xb383,0xb384,0xb385,0xb386,0xb387, + 0xb388,0xb389,0xb38a,0xb38b,0xb38c,0xb38d,0xb38e,0xb38f, + 0xb390,0xb391,0xb392,0xb393,0xb394,0xb395,0xb396,0xb397, + 0xb398,0xb399,0xb39a,0xb39b,0xb39c,0xb39d,0xb39e,0xb39f, + 0xb3a0,0xb3a1,0xb3a2,0xb3a3,0xb3a4,0xb3a5,0xb3a6,0xb3a7, + 0xb3a8,0xb3a9,0xb3aa,0xb3ab,0xb3ac,0xb3ad,0xb3ae,0xb3af, + 0xb3b0,0xb3b1,0xb3b2,0xb3b3,0xb3b4,0xb3b5,0xb3b6,0xb3b7, + 0xb3b8,0xb3b9,0xb3ba,0xb3bb,0xb3bc,0xb3bd,0xb3be,0xb3bf, + 0xb3c0,0xb3c1,0xb3c2,0xb3c3,0xb3c4,0xb3c5,0xb3c6,0xb3c7, + 0xb3c8,0xb3c9,0xb3ca,0xb3cb,0xb3cc,0xb3cd,0xb3ce,0xb3cf, + 0xb3d0,0xb3d1,0xb3d2,0xb3d3,0xb3d4,0xb3d5,0xb3d6,0xb3d7, + 0xb3d8,0xb3d9,0xb3da,0xb3db,0xb3dc,0xb3dd,0xb3de,0xb3df, + 0xb3e0,0xb3e1,0xb3e2,0xb3e3,0xb3e4,0xb3e5,0xb3e6,0xb3e7, + 0xb3e8,0xb3e9,0xb3ea,0xb3eb,0xb3ec,0xb3ed,0xb3ee,0xb3ef, + 0xb3f0,0xb3f1,0xb3f2,0xb3f3,0xb3f4,0xb3f5,0xb3f6,0xb3f7, + 0xb3f8,0xb3f9,0xb3fa,0xb3fb,0xb3fc,0xb3fd,0xb3fe,0xb3ff, + 0xb400,0xb401,0xb402,0xb403,0xb404,0xb405,0xb406,0xb407, + 0xb408,0xb409,0xb40a,0xb40b,0xb40c,0xb40d,0xb40e,0xb40f, + 0xb410,0xb411,0xb412,0xb413,0xb414,0xb415,0xb416,0xb417, + 0xb418,0xb419,0xb41a,0xb41b,0xb41c,0xb41d,0xb41e,0xb41f, + 0xb420,0xb421,0xb422,0xb423,0xb424,0xb425,0xb426,0xb427, + 0xb428,0xb429,0xb42a,0xb42b,0xb42c,0xb42d,0xb42e,0xb42f, + 0xb430,0xb431,0xb432,0xb433,0xb434,0xb435,0xb436,0xb437, + 0xb438,0xb439,0xb43a,0xb43b,0xb43c,0xb43d,0xb43e,0xb43f, + 0xb440,0xb441,0xb442,0xb443,0xb444,0xb445,0xb446,0xb447, + 0xb448,0xb449,0xb44a,0xb44b,0xb44c,0xb44d,0xb44e,0xb44f, + 0xb450,0xb451,0xb452,0xb453,0xb454,0xb455,0xb456,0xb457, + 0xb458,0xb459,0xb45a,0xb45b,0xb45c,0xb45d,0xb45e,0xb45f, + 0xb460,0xb461,0xb462,0xb463,0xb464,0xb465,0xb466,0xb467, + 0xb468,0xb469,0xb46a,0xb46b,0xb46c,0xb46d,0xb46e,0xb46f, + 0xb470,0xb471,0xb472,0xb473,0xb474,0xb475,0xb476,0xb477, + 0xb478,0xb479,0xb47a,0xb47b,0xb47c,0xb47d,0xb47e,0xb47f, + 0xb480,0xb481,0xb482,0xb483,0xb484,0xb485,0xb486,0xb487, + 0xb488,0xb489,0xb48a,0xb48b,0xb48c,0xb48d,0xb48e,0xb48f, + 0xb490,0xb491,0xb492,0xb493,0xb494,0xb495,0xb496,0xb497, + 0xb498,0xb499,0xb49a,0xb49b,0xb49c,0xb49d,0xb49e,0xb49f, + 0xb4a0,0xb4a1,0xb4a2,0xb4a3,0xb4a4,0xb4a5,0xb4a6,0xb4a7, + 0xb4a8,0xb4a9,0xb4aa,0xb4ab,0xb4ac,0xb4ad,0xb4ae,0xb4af, + 0xb4b0,0xb4b1,0xb4b2,0xb4b3,0xb4b4,0xb4b5,0xb4b6,0xb4b7, + 0xb4b8,0xb4b9,0xb4ba,0xb4bb,0xb4bc,0xb4bd,0xb4be,0xb4bf, + 0xb4c0,0xb4c1,0xb4c2,0xb4c3,0xb4c4,0xb4c5,0xb4c6,0xb4c7, + 0xb4c8,0xb4c9,0xb4ca,0xb4cb,0xb4cc,0xb4cd,0xb4ce,0xb4cf, + 0xb4d0,0xb4d1,0xb4d2,0xb4d3,0xb4d4,0xb4d5,0xb4d6,0xb4d7, + 0xb4d8,0xb4d9,0xb4da,0xb4db,0xb4dc,0xb4dd,0xb4de,0xb4df, + 0xb4e0,0xb4e1,0xb4e2,0xb4e3,0xb4e4,0xb4e5,0xb4e6,0xb4e7, + 0xb4e8,0xb4e9,0xb4ea,0xb4eb,0xb4ec,0xb4ed,0xb4ee,0xb4ef, + 0xb4f0,0xb4f1,0xb4f2,0xb4f3,0xb4f4,0xb4f5,0xb4f6,0xb4f7, + 0xb4f8,0xb4f9,0xb4fa,0xb4fb,0xb4fc,0xb4fd,0xb4fe,0xb4ff, + 0xb500,0xb501,0xb502,0xb503,0xb504,0xb505,0xb506,0xb507, + 0xb508,0xb509,0xb50a,0xb50b,0xb50c,0xb50d,0xb50e,0xb50f, + 0xb510,0xb511,0xb512,0xb513,0xb514,0xb515,0xb516,0xb517, + 0xb518,0xb519,0xb51a,0xb51b,0xb51c,0xb51d,0xb51e,0xb51f, + 0xb520,0xb521,0xb522,0xb523,0xb524,0xb525,0xb526,0xb527, + 0xb528,0xb529,0xb52a,0xb52b,0xb52c,0xb52d,0xb52e,0xb52f, + 0xb530,0xb531,0xb532,0xb533,0xb534,0xb535,0xb536,0xb537, + 0xb538,0xb539,0xb53a,0xb53b,0xb53c,0xb53d,0xb53e,0xb53f, + 0xb540,0xb541,0xb542,0xb543,0xb544,0xb545,0xb546,0xb547, + 0xb548,0xb549,0xb54a,0xb54b,0xb54c,0xb54d,0xb54e,0xb54f, + 0xb550,0xb551,0xb552,0xb553,0xb554,0xb555,0xb556,0xb557, + 0xb558,0xb559,0xb55a,0xb55b,0xb55c,0xb55d,0xb55e,0xb55f, + 0xb560,0xb561,0xb562,0xb563,0xb564,0xb565,0xb566,0xb567, + 0xb568,0xb569,0xb56a,0xb56b,0xb56c,0xb56d,0xb56e,0xb56f, + 0xb570,0xb571,0xb572,0xb573,0xb574,0xb575,0xb576,0xb577, + 0xb578,0xb579,0xb57a,0xb57b,0xb57c,0xb57d,0xb57e,0xb57f, + 0xb580,0xb581,0xb582,0xb583,0xb584,0xb585,0xb586,0xb587, + 0xb588,0xb589,0xb58a,0xb58b,0xb58c,0xb58d,0xb58e,0xb58f, + 0xb590,0xb591,0xb592,0xb593,0xb594,0xb595,0xb596,0xb597, + 0xb598,0xb599,0xb59a,0xb59b,0xb59c,0xb59d,0xb59e,0xb59f, + 0xb5a0,0xb5a1,0xb5a2,0xb5a3,0xb5a4,0xb5a5,0xb5a6,0xb5a7, + 0xb5a8,0xb5a9,0xb5aa,0xb5ab,0xb5ac,0xb5ad,0xb5ae,0xb5af, + 0xb5b0,0xb5b1,0xb5b2,0xb5b3,0xb5b4,0xb5b5,0xb5b6,0xb5b7, + 0xb5b8,0xb5b9,0xb5ba,0xb5bb,0xb5bc,0xb5bd,0xb5be,0xb5bf, + 0xb5c0,0xb5c1,0xb5c2,0xb5c3,0xb5c4,0xb5c5,0xb5c6,0xb5c7, + 0xb5c8,0xb5c9,0xb5ca,0xb5cb,0xb5cc,0xb5cd,0xb5ce,0xb5cf, + 0xb5d0,0xb5d1,0xb5d2,0xb5d3,0xb5d4,0xb5d5,0xb5d6,0xb5d7, + 0xb5d8,0xb5d9,0xb5da,0xb5db,0xb5dc,0xb5dd,0xb5de,0xb5df, + 0xb5e0,0xb5e1,0xb5e2,0xb5e3,0xb5e4,0xb5e5,0xb5e6,0xb5e7, + 0xb5e8,0xb5e9,0xb5ea,0xb5eb,0xb5ec,0xb5ed,0xb5ee,0xb5ef, + 0xb5f0,0xb5f1,0xb5f2,0xb5f3,0xb5f4,0xb5f5,0xb5f6,0xb5f7, + 0xb5f8,0xb5f9,0xb5fa,0xb5fb,0xb5fc,0xb5fd,0xb5fe,0xb5ff, + 0xb600,0xb601,0xb602,0xb603,0xb604,0xb605,0xb606,0xb607, + 0xb608,0xb609,0xb60a,0xb60b,0xb60c,0xb60d,0xb60e,0xb60f, + 0xb610,0xb611,0xb612,0xb613,0xb614,0xb615,0xb616,0xb617, + 0xb618,0xb619,0xb61a,0xb61b,0xb61c,0xb61d,0xb61e,0xb61f, + 0xb620,0xb621,0xb622,0xb623,0xb624,0xb625,0xb626,0xb627, + 0xb628,0xb629,0xb62a,0xb62b,0xb62c,0xb62d,0xb62e,0xb62f, + 0xb630,0xb631,0xb632,0xb633,0xb634,0xb635,0xb636,0xb637, + 0xb638,0xb639,0xb63a,0xb63b,0xb63c,0xb63d,0xb63e,0xb63f, + 0xb640,0xb641,0xb642,0xb643,0xb644,0xb645,0xb646,0xb647, + 0xb648,0xb649,0xb64a,0xb64b,0xb64c,0xb64d,0xb64e,0xb64f, + 0xb650,0xb651,0xb652,0xb653,0xb654,0xb655,0xb656,0xb657, + 0xb658,0xb659,0xb65a,0xb65b,0xb65c,0xb65d,0xb65e,0xb65f, + 0xb660,0xb661,0xb662,0xb663,0xb664,0xb665,0xb666,0xb667, + 0xb668,0xb669,0xb66a,0xb66b,0xb66c,0xb66d,0xb66e,0xb66f, + 0xb670,0xb671,0xb672,0xb673,0xb674,0xb675,0xb676,0xb677, + 0xb678,0xb679,0xb67a,0xb67b,0xb67c,0xb67d,0xb67e,0xb67f, + 0xb680,0xb681,0xb682,0xb683,0xb684,0xb685,0xb686,0xb687, + 0xb688,0xb689,0xb68a,0xb68b,0xb68c,0xb68d,0xb68e,0xb68f, + 0xb690,0xb691,0xb692,0xb693,0xb694,0xb695,0xb696,0xb697, + 0xb698,0xb699,0xb69a,0xb69b,0xb69c,0xb69d,0xb69e,0xb69f, + 0xb6a0,0xb6a1,0xb6a2,0xb6a3,0xb6a4,0xb6a5,0xb6a6,0xb6a7, + 0xb6a8,0xb6a9,0xb6aa,0xb6ab,0xb6ac,0xb6ad,0xb6ae,0xb6af, + 0xb6b0,0xb6b1,0xb6b2,0xb6b3,0xb6b4,0xb6b5,0xb6b6,0xb6b7, + 0xb6b8,0xb6b9,0xb6ba,0xb6bb,0xb6bc,0xb6bd,0xb6be,0xb6bf, + 0xb6c0,0xb6c1,0xb6c2,0xb6c3,0xb6c4,0xb6c5,0xb6c6,0xb6c7, + 0xb6c8,0xb6c9,0xb6ca,0xb6cb,0xb6cc,0xb6cd,0xb6ce,0xb6cf, + 0xb6d0,0xb6d1,0xb6d2,0xb6d3,0xb6d4,0xb6d5,0xb6d6,0xb6d7, + 0xb6d8,0xb6d9,0xb6da,0xb6db,0xb6dc,0xb6dd,0xb6de,0xb6df, + 0xb6e0,0xb6e1,0xb6e2,0xb6e3,0xb6e4,0xb6e5,0xb6e6,0xb6e7, + 0xb6e8,0xb6e9,0xb6ea,0xb6eb,0xb6ec,0xb6ed,0xb6ee,0xb6ef, + 0xb6f0,0xb6f1,0xb6f2,0xb6f3,0xb6f4,0xb6f5,0xb6f6,0xb6f7, + 0xb6f8,0xb6f9,0xb6fa,0xb6fb,0xb6fc,0xb6fd,0xb6fe,0xb6ff, + 0xb700,0xb701,0xb702,0xb703,0xb704,0xb705,0xb706,0xb707, + 0xb708,0xb709,0xb70a,0xb70b,0xb70c,0xb70d,0xb70e,0xb70f, + 0xb710,0xb711,0xb712,0xb713,0xb714,0xb715,0xb716,0xb717, + 0xb718,0xb719,0xb71a,0xb71b,0xb71c,0xb71d,0xb71e,0xb71f, + 0xb720,0xb721,0xb722,0xb723,0xb724,0xb725,0xb726,0xb727, + 0xb728,0xb729,0xb72a,0xb72b,0xb72c,0xb72d,0xb72e,0xb72f, + 0xb730,0xb731,0xb732,0xb733,0xb734,0xb735,0xb736,0xb737, + 0xb738,0xb739,0xb73a,0xb73b,0xb73c,0xb73d,0xb73e,0xb73f, + 0xb740,0xb741,0xb742,0xb743,0xb744,0xb745,0xb746,0xb747, + 0xb748,0xb749,0xb74a,0xb74b,0xb74c,0xb74d,0xb74e,0xb74f, + 0xb750,0xb751,0xb752,0xb753,0xb754,0xb755,0xb756,0xb757, + 0xb758,0xb759,0xb75a,0xb75b,0xb75c,0xb75d,0xb75e,0xb75f, + 0xb760,0xb761,0xb762,0xb763,0xb764,0xb765,0xb766,0xb767, + 0xb768,0xb769,0xb76a,0xb76b,0xb76c,0xb76d,0xb76e,0xb76f, + 0xb770,0xb771,0xb772,0xb773,0xb774,0xb775,0xb776,0xb777, + 0xb778,0xb779,0xb77a,0xb77b,0xb77c,0xb77d,0xb77e,0xb77f, + 0xb780,0xb781,0xb782,0xb783,0xb784,0xb785,0xb786,0xb787, + 0xb788,0xb789,0xb78a,0xb78b,0xb78c,0xb78d,0xb78e,0xb78f, + 0xb790,0xb791,0xb792,0xb793,0xb794,0xb795,0xb796,0xb797, + 0xb798,0xb799,0xb79a,0xb79b,0xb79c,0xb79d,0xb79e,0xb79f, + 0xb7a0,0xb7a1,0xb7a2,0xb7a3,0xb7a4,0xb7a5,0xb7a6,0xb7a7, + 0xb7a8,0xb7a9,0xb7aa,0xb7ab,0xb7ac,0xb7ad,0xb7ae,0xb7af, + 0xb7b0,0xb7b1,0xb7b2,0xb7b3,0xb7b4,0xb7b5,0xb7b6,0xb7b7, + 0xb7b8,0xb7b9,0xb7ba,0xb7bb,0xb7bc,0xb7bd,0xb7be,0xb7bf, + 0xb7c0,0xb7c1,0xb7c2,0xb7c3,0xb7c4,0xb7c5,0xb7c6,0xb7c7, + 0xb7c8,0xb7c9,0xb7ca,0xb7cb,0xb7cc,0xb7cd,0xb7ce,0xb7cf, + 0xb7d0,0xb7d1,0xb7d2,0xb7d3,0xb7d4,0xb7d5,0xb7d6,0xb7d7, + 0xb7d8,0xb7d9,0xb7da,0xb7db,0xb7dc,0xb7dd,0xb7de,0xb7df, + 0xb7e0,0xb7e1,0xb7e2,0xb7e3,0xb7e4,0xb7e5,0xb7e6,0xb7e7, + 0xb7e8,0xb7e9,0xb7ea,0xb7eb,0xb7ec,0xb7ed,0xb7ee,0xb7ef, + 0xb7f0,0xb7f1,0xb7f2,0xb7f3,0xb7f4,0xb7f5,0xb7f6,0xb7f7, + 0xb7f8,0xb7f9,0xb7fa,0xb7fb,0xb7fc,0xb7fd,0xb7fe,0xb7ff, + 0xb800,0xb801,0xb802,0xb803,0xb804,0xb805,0xb806,0xb807, + 0xb808,0xb809,0xb80a,0xb80b,0xb80c,0xb80d,0xb80e,0xb80f, + 0xb810,0xb811,0xb812,0xb813,0xb814,0xb815,0xb816,0xb817, + 0xb818,0xb819,0xb81a,0xb81b,0xb81c,0xb81d,0xb81e,0xb81f, + 0xb820,0xb821,0xb822,0xb823,0xb824,0xb825,0xb826,0xb827, + 0xb828,0xb829,0xb82a,0xb82b,0xb82c,0xb82d,0xb82e,0xb82f, + 0xb830,0xb831,0xb832,0xb833,0xb834,0xb835,0xb836,0xb837, + 0xb838,0xb839,0xb83a,0xb83b,0xb83c,0xb83d,0xb83e,0xb83f, + 0xb840,0xb841,0xb842,0xb843,0xb844,0xb845,0xb846,0xb847, + 0xb848,0xb849,0xb84a,0xb84b,0xb84c,0xb84d,0xb84e,0xb84f, + 0xb850,0xb851,0xb852,0xb853,0xb854,0xb855,0xb856,0xb857, + 0xb858,0xb859,0xb85a,0xb85b,0xb85c,0xb85d,0xb85e,0xb85f, + 0xb860,0xb861,0xb862,0xb863,0xb864,0xb865,0xb866,0xb867, + 0xb868,0xb869,0xb86a,0xb86b,0xb86c,0xb86d,0xb86e,0xb86f, + 0xb870,0xb871,0xb872,0xb873,0xb874,0xb875,0xb876,0xb877, + 0xb878,0xb879,0xb87a,0xb87b,0xb87c,0xb87d,0xb87e,0xb87f, + 0xb880,0xb881,0xb882,0xb883,0xb884,0xb885,0xb886,0xb887, + 0xb888,0xb889,0xb88a,0xb88b,0xb88c,0xb88d,0xb88e,0xb88f, + 0xb890,0xb891,0xb892,0xb893,0xb894,0xb895,0xb896,0xb897, + 0xb898,0xb899,0xb89a,0xb89b,0xb89c,0xb89d,0xb89e,0xb89f, + 0xb8a0,0xb8a1,0xb8a2,0xb8a3,0xb8a4,0xb8a5,0xb8a6,0xb8a7, + 0xb8a8,0xb8a9,0xb8aa,0xb8ab,0xb8ac,0xb8ad,0xb8ae,0xb8af, + 0xb8b0,0xb8b1,0xb8b2,0xb8b3,0xb8b4,0xb8b5,0xb8b6,0xb8b7, + 0xb8b8,0xb8b9,0xb8ba,0xb8bb,0xb8bc,0xb8bd,0xb8be,0xb8bf, + 0xb8c0,0xb8c1,0xb8c2,0xb8c3,0xb8c4,0xb8c5,0xb8c6,0xb8c7, + 0xb8c8,0xb8c9,0xb8ca,0xb8cb,0xb8cc,0xb8cd,0xb8ce,0xb8cf, + 0xb8d0,0xb8d1,0xb8d2,0xb8d3,0xb8d4,0xb8d5,0xb8d6,0xb8d7, + 0xb8d8,0xb8d9,0xb8da,0xb8db,0xb8dc,0xb8dd,0xb8de,0xb8df, + 0xb8e0,0xb8e1,0xb8e2,0xb8e3,0xb8e4,0xb8e5,0xb8e6,0xb8e7, + 0xb8e8,0xb8e9,0xb8ea,0xb8eb,0xb8ec,0xb8ed,0xb8ee,0xb8ef, + 0xb8f0,0xb8f1,0xb8f2,0xb8f3,0xb8f4,0xb8f5,0xb8f6,0xb8f7, + 0xb8f8,0xb8f9,0xb8fa,0xb8fb,0xb8fc,0xb8fd,0xb8fe,0xb8ff, + 0xb900,0xb901,0xb902,0xb903,0xb904,0xb905,0xb906,0xb907, + 0xb908,0xb909,0xb90a,0xb90b,0xb90c,0xb90d,0xb90e,0xb90f, + 0xb910,0xb911,0xb912,0xb913,0xb914,0xb915,0xb916,0xb917, + 0xb918,0xb919,0xb91a,0xb91b,0xb91c,0xb91d,0xb91e,0xb91f, + 0xb920,0xb921,0xb922,0xb923,0xb924,0xb925,0xb926,0xb927, + 0xb928,0xb929,0xb92a,0xb92b,0xb92c,0xb92d,0xb92e,0xb92f, + 0xb930,0xb931,0xb932,0xb933,0xb934,0xb935,0xb936,0xb937, + 0xb938,0xb939,0xb93a,0xb93b,0xb93c,0xb93d,0xb93e,0xb93f, + 0xb940,0xb941,0xb942,0xb943,0xb944,0xb945,0xb946,0xb947, + 0xb948,0xb949,0xb94a,0xb94b,0xb94c,0xb94d,0xb94e,0xb94f, + 0xb950,0xb951,0xb952,0xb953,0xb954,0xb955,0xb956,0xb957, + 0xb958,0xb959,0xb95a,0xb95b,0xb95c,0xb95d,0xb95e,0xb95f, + 0xb960,0xb961,0xb962,0xb963,0xb964,0xb965,0xb966,0xb967, + 0xb968,0xb969,0xb96a,0xb96b,0xb96c,0xb96d,0xb96e,0xb96f, + 0xb970,0xb971,0xb972,0xb973,0xb974,0xb975,0xb976,0xb977, + 0xb978,0xb979,0xb97a,0xb97b,0xb97c,0xb97d,0xb97e,0xb97f, + 0xb980,0xb981,0xb982,0xb983,0xb984,0xb985,0xb986,0xb987, + 0xb988,0xb989,0xb98a,0xb98b,0xb98c,0xb98d,0xb98e,0xb98f, + 0xb990,0xb991,0xb992,0xb993,0xb994,0xb995,0xb996,0xb997, + 0xb998,0xb999,0xb99a,0xb99b,0xb99c,0xb99d,0xb99e,0xb99f, + 0xb9a0,0xb9a1,0xb9a2,0xb9a3,0xb9a4,0xb9a5,0xb9a6,0xb9a7, + 0xb9a8,0xb9a9,0xb9aa,0xb9ab,0xb9ac,0xb9ad,0xb9ae,0xb9af, + 0xb9b0,0xb9b1,0xb9b2,0xb9b3,0xb9b4,0xb9b5,0xb9b6,0xb9b7, + 0xb9b8,0xb9b9,0xb9ba,0xb9bb,0xb9bc,0xb9bd,0xb9be,0xb9bf, + 0xb9c0,0xb9c1,0xb9c2,0xb9c3,0xb9c4,0xb9c5,0xb9c6,0xb9c7, + 0xb9c8,0xb9c9,0xb9ca,0xb9cb,0xb9cc,0xb9cd,0xb9ce,0xb9cf, + 0xb9d0,0xb9d1,0xb9d2,0xb9d3,0xb9d4,0xb9d5,0xb9d6,0xb9d7, + 0xb9d8,0xb9d9,0xb9da,0xb9db,0xb9dc,0xb9dd,0xb9de,0xb9df, + 0xb9e0,0xb9e1,0xb9e2,0xb9e3,0xb9e4,0xb9e5,0xb9e6,0xb9e7, + 0xb9e8,0xb9e9,0xb9ea,0xb9eb,0xb9ec,0xb9ed,0xb9ee,0xb9ef, + 0xb9f0,0xb9f1,0xb9f2,0xb9f3,0xb9f4,0xb9f5,0xb9f6,0xb9f7, + 0xb9f8,0xb9f9,0xb9fa,0xb9fb,0xb9fc,0xb9fd,0xb9fe,0xb9ff, + 0xba00,0xba01,0xba02,0xba03,0xba04,0xba05,0xba06,0xba07, + 0xba08,0xba09,0xba0a,0xba0b,0xba0c,0xba0d,0xba0e,0xba0f, + 0xba10,0xba11,0xba12,0xba13,0xba14,0xba15,0xba16,0xba17, + 0xba18,0xba19,0xba1a,0xba1b,0xba1c,0xba1d,0xba1e,0xba1f, + 0xba20,0xba21,0xba22,0xba23,0xba24,0xba25,0xba26,0xba27, + 0xba28,0xba29,0xba2a,0xba2b,0xba2c,0xba2d,0xba2e,0xba2f, + 0xba30,0xba31,0xba32,0xba33,0xba34,0xba35,0xba36,0xba37, + 0xba38,0xba39,0xba3a,0xba3b,0xba3c,0xba3d,0xba3e,0xba3f, + 0xba40,0xba41,0xba42,0xba43,0xba44,0xba45,0xba46,0xba47, + 0xba48,0xba49,0xba4a,0xba4b,0xba4c,0xba4d,0xba4e,0xba4f, + 0xba50,0xba51,0xba52,0xba53,0xba54,0xba55,0xba56,0xba57, + 0xba58,0xba59,0xba5a,0xba5b,0xba5c,0xba5d,0xba5e,0xba5f, + 0xba60,0xba61,0xba62,0xba63,0xba64,0xba65,0xba66,0xba67, + 0xba68,0xba69,0xba6a,0xba6b,0xba6c,0xba6d,0xba6e,0xba6f, + 0xba70,0xba71,0xba72,0xba73,0xba74,0xba75,0xba76,0xba77, + 0xba78,0xba79,0xba7a,0xba7b,0xba7c,0xba7d,0xba7e,0xba7f, + 0xba80,0xba81,0xba82,0xba83,0xba84,0xba85,0xba86,0xba87, + 0xba88,0xba89,0xba8a,0xba8b,0xba8c,0xba8d,0xba8e,0xba8f, + 0xba90,0xba91,0xba92,0xba93,0xba94,0xba95,0xba96,0xba97, + 0xba98,0xba99,0xba9a,0xba9b,0xba9c,0xba9d,0xba9e,0xba9f, + 0xbaa0,0xbaa1,0xbaa2,0xbaa3,0xbaa4,0xbaa5,0xbaa6,0xbaa7, + 0xbaa8,0xbaa9,0xbaaa,0xbaab,0xbaac,0xbaad,0xbaae,0xbaaf, + 0xbab0,0xbab1,0xbab2,0xbab3,0xbab4,0xbab5,0xbab6,0xbab7, + 0xbab8,0xbab9,0xbaba,0xbabb,0xbabc,0xbabd,0xbabe,0xbabf, + 0xbac0,0xbac1,0xbac2,0xbac3,0xbac4,0xbac5,0xbac6,0xbac7, + 0xbac8,0xbac9,0xbaca,0xbacb,0xbacc,0xbacd,0xbace,0xbacf, + 0xbad0,0xbad1,0xbad2,0xbad3,0xbad4,0xbad5,0xbad6,0xbad7, + 0xbad8,0xbad9,0xbada,0xbadb,0xbadc,0xbadd,0xbade,0xbadf, + 0xbae0,0xbae1,0xbae2,0xbae3,0xbae4,0xbae5,0xbae6,0xbae7, + 0xbae8,0xbae9,0xbaea,0xbaeb,0xbaec,0xbaed,0xbaee,0xbaef, + 0xbaf0,0xbaf1,0xbaf2,0xbaf3,0xbaf4,0xbaf5,0xbaf6,0xbaf7, + 0xbaf8,0xbaf9,0xbafa,0xbafb,0xbafc,0xbafd,0xbafe,0xbaff, + 0xbb00,0xbb01,0xbb02,0xbb03,0xbb04,0xbb05,0xbb06,0xbb07, + 0xbb08,0xbb09,0xbb0a,0xbb0b,0xbb0c,0xbb0d,0xbb0e,0xbb0f, + 0xbb10,0xbb11,0xbb12,0xbb13,0xbb14,0xbb15,0xbb16,0xbb17, + 0xbb18,0xbb19,0xbb1a,0xbb1b,0xbb1c,0xbb1d,0xbb1e,0xbb1f, + 0xbb20,0xbb21,0xbb22,0xbb23,0xbb24,0xbb25,0xbb26,0xbb27, + 0xbb28,0xbb29,0xbb2a,0xbb2b,0xbb2c,0xbb2d,0xbb2e,0xbb2f, + 0xbb30,0xbb31,0xbb32,0xbb33,0xbb34,0xbb35,0xbb36,0xbb37, + 0xbb38,0xbb39,0xbb3a,0xbb3b,0xbb3c,0xbb3d,0xbb3e,0xbb3f, + 0xbb40,0xbb41,0xbb42,0xbb43,0xbb44,0xbb45,0xbb46,0xbb47, + 0xbb48,0xbb49,0xbb4a,0xbb4b,0xbb4c,0xbb4d,0xbb4e,0xbb4f, + 0xbb50,0xbb51,0xbb52,0xbb53,0xbb54,0xbb55,0xbb56,0xbb57, + 0xbb58,0xbb59,0xbb5a,0xbb5b,0xbb5c,0xbb5d,0xbb5e,0xbb5f, + 0xbb60,0xbb61,0xbb62,0xbb63,0xbb64,0xbb65,0xbb66,0xbb67, + 0xbb68,0xbb69,0xbb6a,0xbb6b,0xbb6c,0xbb6d,0xbb6e,0xbb6f, + 0xbb70,0xbb71,0xbb72,0xbb73,0xbb74,0xbb75,0xbb76,0xbb77, + 0xbb78,0xbb79,0xbb7a,0xbb7b,0xbb7c,0xbb7d,0xbb7e,0xbb7f, + 0xbb80,0xbb81,0xbb82,0xbb83,0xbb84,0xbb85,0xbb86,0xbb87, + 0xbb88,0xbb89,0xbb8a,0xbb8b,0xbb8c,0xbb8d,0xbb8e,0xbb8f, + 0xbb90,0xbb91,0xbb92,0xbb93,0xbb94,0xbb95,0xbb96,0xbb97, + 0xbb98,0xbb99,0xbb9a,0xbb9b,0xbb9c,0xbb9d,0xbb9e,0xbb9f, + 0xbba0,0xbba1,0xbba2,0xbba3,0xbba4,0xbba5,0xbba6,0xbba7, + 0xbba8,0xbba9,0xbbaa,0xbbab,0xbbac,0xbbad,0xbbae,0xbbaf, + 0xbbb0,0xbbb1,0xbbb2,0xbbb3,0xbbb4,0xbbb5,0xbbb6,0xbbb7, + 0xbbb8,0xbbb9,0xbbba,0xbbbb,0xbbbc,0xbbbd,0xbbbe,0xbbbf, + 0xbbc0,0xbbc1,0xbbc2,0xbbc3,0xbbc4,0xbbc5,0xbbc6,0xbbc7, + 0xbbc8,0xbbc9,0xbbca,0xbbcb,0xbbcc,0xbbcd,0xbbce,0xbbcf, + 0xbbd0,0xbbd1,0xbbd2,0xbbd3,0xbbd4,0xbbd5,0xbbd6,0xbbd7, + 0xbbd8,0xbbd9,0xbbda,0xbbdb,0xbbdc,0xbbdd,0xbbde,0xbbdf, + 0xbbe0,0xbbe1,0xbbe2,0xbbe3,0xbbe4,0xbbe5,0xbbe6,0xbbe7, + 0xbbe8,0xbbe9,0xbbea,0xbbeb,0xbbec,0xbbed,0xbbee,0xbbef, + 0xbbf0,0xbbf1,0xbbf2,0xbbf3,0xbbf4,0xbbf5,0xbbf6,0xbbf7, + 0xbbf8,0xbbf9,0xbbfa,0xbbfb,0xbbfc,0xbbfd,0xbbfe,0xbbff, + 0xbc00,0xbc01,0xbc02,0xbc03,0xbc04,0xbc05,0xbc06,0xbc07, + 0xbc08,0xbc09,0xbc0a,0xbc0b,0xbc0c,0xbc0d,0xbc0e,0xbc0f, + 0xbc10,0xbc11,0xbc12,0xbc13,0xbc14,0xbc15,0xbc16,0xbc17, + 0xbc18,0xbc19,0xbc1a,0xbc1b,0xbc1c,0xbc1d,0xbc1e,0xbc1f, + 0xbc20,0xbc21,0xbc22,0xbc23,0xbc24,0xbc25,0xbc26,0xbc27, + 0xbc28,0xbc29,0xbc2a,0xbc2b,0xbc2c,0xbc2d,0xbc2e,0xbc2f, + 0xbc30,0xbc31,0xbc32,0xbc33,0xbc34,0xbc35,0xbc36,0xbc37, + 0xbc38,0xbc39,0xbc3a,0xbc3b,0xbc3c,0xbc3d,0xbc3e,0xbc3f, + 0xbc40,0xbc41,0xbc42,0xbc43,0xbc44,0xbc45,0xbc46,0xbc47, + 0xbc48,0xbc49,0xbc4a,0xbc4b,0xbc4c,0xbc4d,0xbc4e,0xbc4f, + 0xbc50,0xbc51,0xbc52,0xbc53,0xbc54,0xbc55,0xbc56,0xbc57, + 0xbc58,0xbc59,0xbc5a,0xbc5b,0xbc5c,0xbc5d,0xbc5e,0xbc5f, + 0xbc60,0xbc61,0xbc62,0xbc63,0xbc64,0xbc65,0xbc66,0xbc67, + 0xbc68,0xbc69,0xbc6a,0xbc6b,0xbc6c,0xbc6d,0xbc6e,0xbc6f, + 0xbc70,0xbc71,0xbc72,0xbc73,0xbc74,0xbc75,0xbc76,0xbc77, + 0xbc78,0xbc79,0xbc7a,0xbc7b,0xbc7c,0xbc7d,0xbc7e,0xbc7f, + 0xbc80,0xbc81,0xbc82,0xbc83,0xbc84,0xbc85,0xbc86,0xbc87, + 0xbc88,0xbc89,0xbc8a,0xbc8b,0xbc8c,0xbc8d,0xbc8e,0xbc8f, + 0xbc90,0xbc91,0xbc92,0xbc93,0xbc94,0xbc95,0xbc96,0xbc97, + 0xbc98,0xbc99,0xbc9a,0xbc9b,0xbc9c,0xbc9d,0xbc9e,0xbc9f, + 0xbca0,0xbca1,0xbca2,0xbca3,0xbca4,0xbca5,0xbca6,0xbca7, + 0xbca8,0xbca9,0xbcaa,0xbcab,0xbcac,0xbcad,0xbcae,0xbcaf, + 0xbcb0,0xbcb1,0xbcb2,0xbcb3,0xbcb4,0xbcb5,0xbcb6,0xbcb7, + 0xbcb8,0xbcb9,0xbcba,0xbcbb,0xbcbc,0xbcbd,0xbcbe,0xbcbf, + 0xbcc0,0xbcc1,0xbcc2,0xbcc3,0xbcc4,0xbcc5,0xbcc6,0xbcc7, + 0xbcc8,0xbcc9,0xbcca,0xbccb,0xbccc,0xbccd,0xbcce,0xbccf, + 0xbcd0,0xbcd1,0xbcd2,0xbcd3,0xbcd4,0xbcd5,0xbcd6,0xbcd7, + 0xbcd8,0xbcd9,0xbcda,0xbcdb,0xbcdc,0xbcdd,0xbcde,0xbcdf, + 0xbce0,0xbce1,0xbce2,0xbce3,0xbce4,0xbce5,0xbce6,0xbce7, + 0xbce8,0xbce9,0xbcea,0xbceb,0xbcec,0xbced,0xbcee,0xbcef, + 0xbcf0,0xbcf1,0xbcf2,0xbcf3,0xbcf4,0xbcf5,0xbcf6,0xbcf7, + 0xbcf8,0xbcf9,0xbcfa,0xbcfb,0xbcfc,0xbcfd,0xbcfe,0xbcff, + 0xbd00,0xbd01,0xbd02,0xbd03,0xbd04,0xbd05,0xbd06,0xbd07, + 0xbd08,0xbd09,0xbd0a,0xbd0b,0xbd0c,0xbd0d,0xbd0e,0xbd0f, + 0xbd10,0xbd11,0xbd12,0xbd13,0xbd14,0xbd15,0xbd16,0xbd17, + 0xbd18,0xbd19,0xbd1a,0xbd1b,0xbd1c,0xbd1d,0xbd1e,0xbd1f, + 0xbd20,0xbd21,0xbd22,0xbd23,0xbd24,0xbd25,0xbd26,0xbd27, + 0xbd28,0xbd29,0xbd2a,0xbd2b,0xbd2c,0xbd2d,0xbd2e,0xbd2f, + 0xbd30,0xbd31,0xbd32,0xbd33,0xbd34,0xbd35,0xbd36,0xbd37, + 0xbd38,0xbd39,0xbd3a,0xbd3b,0xbd3c,0xbd3d,0xbd3e,0xbd3f, + 0xbd40,0xbd41,0xbd42,0xbd43,0xbd44,0xbd45,0xbd46,0xbd47, + 0xbd48,0xbd49,0xbd4a,0xbd4b,0xbd4c,0xbd4d,0xbd4e,0xbd4f, + 0xbd50,0xbd51,0xbd52,0xbd53,0xbd54,0xbd55,0xbd56,0xbd57, + 0xbd58,0xbd59,0xbd5a,0xbd5b,0xbd5c,0xbd5d,0xbd5e,0xbd5f, + 0xbd60,0xbd61,0xbd62,0xbd63,0xbd64,0xbd65,0xbd66,0xbd67, + 0xbd68,0xbd69,0xbd6a,0xbd6b,0xbd6c,0xbd6d,0xbd6e,0xbd6f, + 0xbd70,0xbd71,0xbd72,0xbd73,0xbd74,0xbd75,0xbd76,0xbd77, + 0xbd78,0xbd79,0xbd7a,0xbd7b,0xbd7c,0xbd7d,0xbd7e,0xbd7f, + 0xbd80,0xbd81,0xbd82,0xbd83,0xbd84,0xbd85,0xbd86,0xbd87, + 0xbd88,0xbd89,0xbd8a,0xbd8b,0xbd8c,0xbd8d,0xbd8e,0xbd8f, + 0xbd90,0xbd91,0xbd92,0xbd93,0xbd94,0xbd95,0xbd96,0xbd97, + 0xbd98,0xbd99,0xbd9a,0xbd9b,0xbd9c,0xbd9d,0xbd9e,0xbd9f, + 0xbda0,0xbda1,0xbda2,0xbda3,0xbda4,0xbda5,0xbda6,0xbda7, + 0xbda8,0xbda9,0xbdaa,0xbdab,0xbdac,0xbdad,0xbdae,0xbdaf, + 0xbdb0,0xbdb1,0xbdb2,0xbdb3,0xbdb4,0xbdb5,0xbdb6,0xbdb7, + 0xbdb8,0xbdb9,0xbdba,0xbdbb,0xbdbc,0xbdbd,0xbdbe,0xbdbf, + 0xbdc0,0xbdc1,0xbdc2,0xbdc3,0xbdc4,0xbdc5,0xbdc6,0xbdc7, + 0xbdc8,0xbdc9,0xbdca,0xbdcb,0xbdcc,0xbdcd,0xbdce,0xbdcf, + 0xbdd0,0xbdd1,0xbdd2,0xbdd3,0xbdd4,0xbdd5,0xbdd6,0xbdd7, + 0xbdd8,0xbdd9,0xbdda,0xbddb,0xbddc,0xbddd,0xbdde,0xbddf, + 0xbde0,0xbde1,0xbde2,0xbde3,0xbde4,0xbde5,0xbde6,0xbde7, + 0xbde8,0xbde9,0xbdea,0xbdeb,0xbdec,0xbded,0xbdee,0xbdef, + 0xbdf0,0xbdf1,0xbdf2,0xbdf3,0xbdf4,0xbdf5,0xbdf6,0xbdf7, + 0xbdf8,0xbdf9,0xbdfa,0xbdfb,0xbdfc,0xbdfd,0xbdfe,0xbdff, + 0xbe00,0xbe01,0xbe02,0xbe03,0xbe04,0xbe05,0xbe06,0xbe07, + 0xbe08,0xbe09,0xbe0a,0xbe0b,0xbe0c,0xbe0d,0xbe0e,0xbe0f, + 0xbe10,0xbe11,0xbe12,0xbe13,0xbe14,0xbe15,0xbe16,0xbe17, + 0xbe18,0xbe19,0xbe1a,0xbe1b,0xbe1c,0xbe1d,0xbe1e,0xbe1f, + 0xbe20,0xbe21,0xbe22,0xbe23,0xbe24,0xbe25,0xbe26,0xbe27, + 0xbe28,0xbe29,0xbe2a,0xbe2b,0xbe2c,0xbe2d,0xbe2e,0xbe2f, + 0xbe30,0xbe31,0xbe32,0xbe33,0xbe34,0xbe35,0xbe36,0xbe37, + 0xbe38,0xbe39,0xbe3a,0xbe3b,0xbe3c,0xbe3d,0xbe3e,0xbe3f, + 0xbe40,0xbe41,0xbe42,0xbe43,0xbe44,0xbe45,0xbe46,0xbe47, + 0xbe48,0xbe49,0xbe4a,0xbe4b,0xbe4c,0xbe4d,0xbe4e,0xbe4f, + 0xbe50,0xbe51,0xbe52,0xbe53,0xbe54,0xbe55,0xbe56,0xbe57, + 0xbe58,0xbe59,0xbe5a,0xbe5b,0xbe5c,0xbe5d,0xbe5e,0xbe5f, + 0xbe60,0xbe61,0xbe62,0xbe63,0xbe64,0xbe65,0xbe66,0xbe67, + 0xbe68,0xbe69,0xbe6a,0xbe6b,0xbe6c,0xbe6d,0xbe6e,0xbe6f, + 0xbe70,0xbe71,0xbe72,0xbe73,0xbe74,0xbe75,0xbe76,0xbe77, + 0xbe78,0xbe79,0xbe7a,0xbe7b,0xbe7c,0xbe7d,0xbe7e,0xbe7f, + 0xbe80,0xbe81,0xbe82,0xbe83,0xbe84,0xbe85,0xbe86,0xbe87, + 0xbe88,0xbe89,0xbe8a,0xbe8b,0xbe8c,0xbe8d,0xbe8e,0xbe8f, + 0xbe90,0xbe91,0xbe92,0xbe93,0xbe94,0xbe95,0xbe96,0xbe97, + 0xbe98,0xbe99,0xbe9a,0xbe9b,0xbe9c,0xbe9d,0xbe9e,0xbe9f, + 0xbea0,0xbea1,0xbea2,0xbea3,0xbea4,0xbea5,0xbea6,0xbea7, + 0xbea8,0xbea9,0xbeaa,0xbeab,0xbeac,0xbead,0xbeae,0xbeaf, + 0xbeb0,0xbeb1,0xbeb2,0xbeb3,0xbeb4,0xbeb5,0xbeb6,0xbeb7, + 0xbeb8,0xbeb9,0xbeba,0xbebb,0xbebc,0xbebd,0xbebe,0xbebf, + 0xbec0,0xbec1,0xbec2,0xbec3,0xbec4,0xbec5,0xbec6,0xbec7, + 0xbec8,0xbec9,0xbeca,0xbecb,0xbecc,0xbecd,0xbece,0xbecf, + 0xbed0,0xbed1,0xbed2,0xbed3,0xbed4,0xbed5,0xbed6,0xbed7, + 0xbed8,0xbed9,0xbeda,0xbedb,0xbedc,0xbedd,0xbede,0xbedf, + 0xbee0,0xbee1,0xbee2,0xbee3,0xbee4,0xbee5,0xbee6,0xbee7, + 0xbee8,0xbee9,0xbeea,0xbeeb,0xbeec,0xbeed,0xbeee,0xbeef, + 0xbef0,0xbef1,0xbef2,0xbef3,0xbef4,0xbef5,0xbef6,0xbef7, + 0xbef8,0xbef9,0xbefa,0xbefb,0xbefc,0xbefd,0xbefe,0xbeff, + 0xbf00,0xbf01,0xbf02,0xbf03,0xbf04,0xbf05,0xbf06,0xbf07, + 0xbf08,0xbf09,0xbf0a,0xbf0b,0xbf0c,0xbf0d,0xbf0e,0xbf0f, + 0xbf10,0xbf11,0xbf12,0xbf13,0xbf14,0xbf15,0xbf16,0xbf17, + 0xbf18,0xbf19,0xbf1a,0xbf1b,0xbf1c,0xbf1d,0xbf1e,0xbf1f, + 0xbf20,0xbf21,0xbf22,0xbf23,0xbf24,0xbf25,0xbf26,0xbf27, + 0xbf28,0xbf29,0xbf2a,0xbf2b,0xbf2c,0xbf2d,0xbf2e,0xbf2f, + 0xbf30,0xbf31,0xbf32,0xbf33,0xbf34,0xbf35,0xbf36,0xbf37, + 0xbf38,0xbf39,0xbf3a,0xbf3b,0xbf3c,0xbf3d,0xbf3e,0xbf3f, + 0xbf40,0xbf41,0xbf42,0xbf43,0xbf44,0xbf45,0xbf46,0xbf47, + 0xbf48,0xbf49,0xbf4a,0xbf4b,0xbf4c,0xbf4d,0xbf4e,0xbf4f, + 0xbf50,0xbf51,0xbf52,0xbf53,0xbf54,0xbf55,0xbf56,0xbf57, + 0xbf58,0xbf59,0xbf5a,0xbf5b,0xbf5c,0xbf5d,0xbf5e,0xbf5f, + 0xbf60,0xbf61,0xbf62,0xbf63,0xbf64,0xbf65,0xbf66,0xbf67, + 0xbf68,0xbf69,0xbf6a,0xbf6b,0xbf6c,0xbf6d,0xbf6e,0xbf6f, + 0xbf70,0xbf71,0xbf72,0xbf73,0xbf74,0xbf75,0xbf76,0xbf77, + 0xbf78,0xbf79,0xbf7a,0xbf7b,0xbf7c,0xbf7d,0xbf7e,0xbf7f, + 0xbf80,0xbf81,0xbf82,0xbf83,0xbf84,0xbf85,0xbf86,0xbf87, + 0xbf88,0xbf89,0xbf8a,0xbf8b,0xbf8c,0xbf8d,0xbf8e,0xbf8f, + 0xbf90,0xbf91,0xbf92,0xbf93,0xbf94,0xbf95,0xbf96,0xbf97, + 0xbf98,0xbf99,0xbf9a,0xbf9b,0xbf9c,0xbf9d,0xbf9e,0xbf9f, + 0xbfa0,0xbfa1,0xbfa2,0xbfa3,0xbfa4,0xbfa5,0xbfa6,0xbfa7, + 0xbfa8,0xbfa9,0xbfaa,0xbfab,0xbfac,0xbfad,0xbfae,0xbfaf, + 0xbfb0,0xbfb1,0xbfb2,0xbfb3,0xbfb4,0xbfb5,0xbfb6,0xbfb7, + 0xbfb8,0xbfb9,0xbfba,0xbfbb,0xbfbc,0xbfbd,0xbfbe,0xbfbf, + 0xbfc0,0xbfc1,0xbfc2,0xbfc3,0xbfc4,0xbfc5,0xbfc6,0xbfc7, + 0xbfc8,0xbfc9,0xbfca,0xbfcb,0xbfcc,0xbfcd,0xbfce,0xbfcf, + 0xbfd0,0xbfd1,0xbfd2,0xbfd3,0xbfd4,0xbfd5,0xbfd6,0xbfd7, + 0xbfd8,0xbfd9,0xbfda,0xbfdb,0xbfdc,0xbfdd,0xbfde,0xbfdf, + 0xbfe0,0xbfe1,0xbfe2,0xbfe3,0xbfe4,0xbfe5,0xbfe6,0xbfe7, + 0xbfe8,0xbfe9,0xbfea,0xbfeb,0xbfec,0xbfed,0xbfee,0xbfef, + 0xbff0,0xbff1,0xbff2,0xbff3,0xbff4,0xbff5,0xbff6,0xbff7, + 0xbff8,0xbff9,0xbffa,0xbffb,0xbffc,0xbffd,0xbffe,0xbfff, + 0xc000,0xc001,0xc002,0xc003,0xc004,0xc005,0xc006,0xc007, + 0xc008,0xc009,0xc00a,0xc00b,0xc00c,0xc00d,0xc00e,0xc00f, + 0xc010,0xc011,0xc012,0xc013,0xc014,0xc015,0xc016,0xc017, + 0xc018,0xc019,0xc01a,0xc01b,0xc01c,0xc01d,0xc01e,0xc01f, + 0xc020,0xc021,0xc022,0xc023,0xc024,0xc025,0xc026,0xc027, + 0xc028,0xc029,0xc02a,0xc02b,0xc02c,0xc02d,0xc02e,0xc02f, + 0xc030,0xc031,0xc032,0xc033,0xc034,0xc035,0xc036,0xc037, + 0xc038,0xc039,0xc03a,0xc03b,0xc03c,0xc03d,0xc03e,0xc03f, + 0xc040,0xc041,0xc042,0xc043,0xc044,0xc045,0xc046,0xc047, + 0xc048,0xc049,0xc04a,0xc04b,0xc04c,0xc04d,0xc04e,0xc04f, + 0xc050,0xc051,0xc052,0xc053,0xc054,0xc055,0xc056,0xc057, + 0xc058,0xc059,0xc05a,0xc05b,0xc05c,0xc05d,0xc05e,0xc05f, + 0xc060,0xc061,0xc062,0xc063,0xc064,0xc065,0xc066,0xc067, + 0xc068,0xc069,0xc06a,0xc06b,0xc06c,0xc06d,0xc06e,0xc06f, + 0xc070,0xc071,0xc072,0xc073,0xc074,0xc075,0xc076,0xc077, + 0xc078,0xc079,0xc07a,0xc07b,0xc07c,0xc07d,0xc07e,0xc07f, + 0xc080,0xc081,0xc082,0xc083,0xc084,0xc085,0xc086,0xc087, + 0xc088,0xc089,0xc08a,0xc08b,0xc08c,0xc08d,0xc08e,0xc08f, + 0xc090,0xc091,0xc092,0xc093,0xc094,0xc095,0xc096,0xc097, + 0xc098,0xc099,0xc09a,0xc09b,0xc09c,0xc09d,0xc09e,0xc09f, + 0xc0a0,0xc0a1,0xc0a2,0xc0a3,0xc0a4,0xc0a5,0xc0a6,0xc0a7, + 0xc0a8,0xc0a9,0xc0aa,0xc0ab,0xc0ac,0xc0ad,0xc0ae,0xc0af, + 0xc0b0,0xc0b1,0xc0b2,0xc0b3,0xc0b4,0xc0b5,0xc0b6,0xc0b7, + 0xc0b8,0xc0b9,0xc0ba,0xc0bb,0xc0bc,0xc0bd,0xc0be,0xc0bf, + 0xc0c0,0xc0c1,0xc0c2,0xc0c3,0xc0c4,0xc0c5,0xc0c6,0xc0c7, + 0xc0c8,0xc0c9,0xc0ca,0xc0cb,0xc0cc,0xc0cd,0xc0ce,0xc0cf, + 0xc0d0,0xc0d1,0xc0d2,0xc0d3,0xc0d4,0xc0d5,0xc0d6,0xc0d7, + 0xc0d8,0xc0d9,0xc0da,0xc0db,0xc0dc,0xc0dd,0xc0de,0xc0df, + 0xc0e0,0xc0e1,0xc0e2,0xc0e3,0xc0e4,0xc0e5,0xc0e6,0xc0e7, + 0xc0e8,0xc0e9,0xc0ea,0xc0eb,0xc0ec,0xc0ed,0xc0ee,0xc0ef, + 0xc0f0,0xc0f1,0xc0f2,0xc0f3,0xc0f4,0xc0f5,0xc0f6,0xc0f7, + 0xc0f8,0xc0f9,0xc0fa,0xc0fb,0xc0fc,0xc0fd,0xc0fe,0xc0ff, + 0xc100,0xc101,0xc102,0xc103,0xc104,0xc105,0xc106,0xc107, + 0xc108,0xc109,0xc10a,0xc10b,0xc10c,0xc10d,0xc10e,0xc10f, + 0xc110,0xc111,0xc112,0xc113,0xc114,0xc115,0xc116,0xc117, + 0xc118,0xc119,0xc11a,0xc11b,0xc11c,0xc11d,0xc11e,0xc11f, + 0xc120,0xc121,0xc122,0xc123,0xc124,0xc125,0xc126,0xc127, + 0xc128,0xc129,0xc12a,0xc12b,0xc12c,0xc12d,0xc12e,0xc12f, + 0xc130,0xc131,0xc132,0xc133,0xc134,0xc135,0xc136,0xc137, + 0xc138,0xc139,0xc13a,0xc13b,0xc13c,0xc13d,0xc13e,0xc13f, + 0xc140,0xc141,0xc142,0xc143,0xc144,0xc145,0xc146,0xc147, + 0xc148,0xc149,0xc14a,0xc14b,0xc14c,0xc14d,0xc14e,0xc14f, + 0xc150,0xc151,0xc152,0xc153,0xc154,0xc155,0xc156,0xc157, + 0xc158,0xc159,0xc15a,0xc15b,0xc15c,0xc15d,0xc15e,0xc15f, + 0xc160,0xc161,0xc162,0xc163,0xc164,0xc165,0xc166,0xc167, + 0xc168,0xc169,0xc16a,0xc16b,0xc16c,0xc16d,0xc16e,0xc16f, + 0xc170,0xc171,0xc172,0xc173,0xc174,0xc175,0xc176,0xc177, + 0xc178,0xc179,0xc17a,0xc17b,0xc17c,0xc17d,0xc17e,0xc17f, + 0xc180,0xc181,0xc182,0xc183,0xc184,0xc185,0xc186,0xc187, + 0xc188,0xc189,0xc18a,0xc18b,0xc18c,0xc18d,0xc18e,0xc18f, + 0xc190,0xc191,0xc192,0xc193,0xc194,0xc195,0xc196,0xc197, + 0xc198,0xc199,0xc19a,0xc19b,0xc19c,0xc19d,0xc19e,0xc19f, + 0xc1a0,0xc1a1,0xc1a2,0xc1a3,0xc1a4,0xc1a5,0xc1a6,0xc1a7, + 0xc1a8,0xc1a9,0xc1aa,0xc1ab,0xc1ac,0xc1ad,0xc1ae,0xc1af, + 0xc1b0,0xc1b1,0xc1b2,0xc1b3,0xc1b4,0xc1b5,0xc1b6,0xc1b7, + 0xc1b8,0xc1b9,0xc1ba,0xc1bb,0xc1bc,0xc1bd,0xc1be,0xc1bf, + 0xc1c0,0xc1c1,0xc1c2,0xc1c3,0xc1c4,0xc1c5,0xc1c6,0xc1c7, + 0xc1c8,0xc1c9,0xc1ca,0xc1cb,0xc1cc,0xc1cd,0xc1ce,0xc1cf, + 0xc1d0,0xc1d1,0xc1d2,0xc1d3,0xc1d4,0xc1d5,0xc1d6,0xc1d7, + 0xc1d8,0xc1d9,0xc1da,0xc1db,0xc1dc,0xc1dd,0xc1de,0xc1df, + 0xc1e0,0xc1e1,0xc1e2,0xc1e3,0xc1e4,0xc1e5,0xc1e6,0xc1e7, + 0xc1e8,0xc1e9,0xc1ea,0xc1eb,0xc1ec,0xc1ed,0xc1ee,0xc1ef, + 0xc1f0,0xc1f1,0xc1f2,0xc1f3,0xc1f4,0xc1f5,0xc1f6,0xc1f7, + 0xc1f8,0xc1f9,0xc1fa,0xc1fb,0xc1fc,0xc1fd,0xc1fe,0xc1ff, + 0xc200,0xc201,0xc202,0xc203,0xc204,0xc205,0xc206,0xc207, + 0xc208,0xc209,0xc20a,0xc20b,0xc20c,0xc20d,0xc20e,0xc20f, + 0xc210,0xc211,0xc212,0xc213,0xc214,0xc215,0xc216,0xc217, + 0xc218,0xc219,0xc21a,0xc21b,0xc21c,0xc21d,0xc21e,0xc21f, + 0xc220,0xc221,0xc222,0xc223,0xc224,0xc225,0xc226,0xc227, + 0xc228,0xc229,0xc22a,0xc22b,0xc22c,0xc22d,0xc22e,0xc22f, + 0xc230,0xc231,0xc232,0xc233,0xc234,0xc235,0xc236,0xc237, + 0xc238,0xc239,0xc23a,0xc23b,0xc23c,0xc23d,0xc23e,0xc23f, + 0xc240,0xc241,0xc242,0xc243,0xc244,0xc245,0xc246,0xc247, + 0xc248,0xc249,0xc24a,0xc24b,0xc24c,0xc24d,0xc24e,0xc24f, + 0xc250,0xc251,0xc252,0xc253,0xc254,0xc255,0xc256,0xc257, + 0xc258,0xc259,0xc25a,0xc25b,0xc25c,0xc25d,0xc25e,0xc25f, + 0xc260,0xc261,0xc262,0xc263,0xc264,0xc265,0xc266,0xc267, + 0xc268,0xc269,0xc26a,0xc26b,0xc26c,0xc26d,0xc26e,0xc26f, + 0xc270,0xc271,0xc272,0xc273,0xc274,0xc275,0xc276,0xc277, + 0xc278,0xc279,0xc27a,0xc27b,0xc27c,0xc27d,0xc27e,0xc27f, + 0xc280,0xc281,0xc282,0xc283,0xc284,0xc285,0xc286,0xc287, + 0xc288,0xc289,0xc28a,0xc28b,0xc28c,0xc28d,0xc28e,0xc28f, + 0xc290,0xc291,0xc292,0xc293,0xc294,0xc295,0xc296,0xc297, + 0xc298,0xc299,0xc29a,0xc29b,0xc29c,0xc29d,0xc29e,0xc29f, + 0xc2a0,0xc2a1,0xc2a2,0xc2a3,0xc2a4,0xc2a5,0xc2a6,0xc2a7, + 0xc2a8,0xc2a9,0xc2aa,0xc2ab,0xc2ac,0xc2ad,0xc2ae,0xc2af, + 0xc2b0,0xc2b1,0xc2b2,0xc2b3,0xc2b4,0xc2b5,0xc2b6,0xc2b7, + 0xc2b8,0xc2b9,0xc2ba,0xc2bb,0xc2bc,0xc2bd,0xc2be,0xc2bf, + 0xc2c0,0xc2c1,0xc2c2,0xc2c3,0xc2c4,0xc2c5,0xc2c6,0xc2c7, + 0xc2c8,0xc2c9,0xc2ca,0xc2cb,0xc2cc,0xc2cd,0xc2ce,0xc2cf, + 0xc2d0,0xc2d1,0xc2d2,0xc2d3,0xc2d4,0xc2d5,0xc2d6,0xc2d7, + 0xc2d8,0xc2d9,0xc2da,0xc2db,0xc2dc,0xc2dd,0xc2de,0xc2df, + 0xc2e0,0xc2e1,0xc2e2,0xc2e3,0xc2e4,0xc2e5,0xc2e6,0xc2e7, + 0xc2e8,0xc2e9,0xc2ea,0xc2eb,0xc2ec,0xc2ed,0xc2ee,0xc2ef, + 0xc2f0,0xc2f1,0xc2f2,0xc2f3,0xc2f4,0xc2f5,0xc2f6,0xc2f7, + 0xc2f8,0xc2f9,0xc2fa,0xc2fb,0xc2fc,0xc2fd,0xc2fe,0xc2ff, + 0xc300,0xc301,0xc302,0xc303,0xc304,0xc305,0xc306,0xc307, + 0xc308,0xc309,0xc30a,0xc30b,0xc30c,0xc30d,0xc30e,0xc30f, + 0xc310,0xc311,0xc312,0xc313,0xc314,0xc315,0xc316,0xc317, + 0xc318,0xc319,0xc31a,0xc31b,0xc31c,0xc31d,0xc31e,0xc31f, + 0xc320,0xc321,0xc322,0xc323,0xc324,0xc325,0xc326,0xc327, + 0xc328,0xc329,0xc32a,0xc32b,0xc32c,0xc32d,0xc32e,0xc32f, + 0xc330,0xc331,0xc332,0xc333,0xc334,0xc335,0xc336,0xc337, + 0xc338,0xc339,0xc33a,0xc33b,0xc33c,0xc33d,0xc33e,0xc33f, + 0xc340,0xc341,0xc342,0xc343,0xc344,0xc345,0xc346,0xc347, + 0xc348,0xc349,0xc34a,0xc34b,0xc34c,0xc34d,0xc34e,0xc34f, + 0xc350,0xc351,0xc352,0xc353,0xc354,0xc355,0xc356,0xc357, + 0xc358,0xc359,0xc35a,0xc35b,0xc35c,0xc35d,0xc35e,0xc35f, + 0xc360,0xc361,0xc362,0xc363,0xc364,0xc365,0xc366,0xc367, + 0xc368,0xc369,0xc36a,0xc36b,0xc36c,0xc36d,0xc36e,0xc36f, + 0xc370,0xc371,0xc372,0xc373,0xc374,0xc375,0xc376,0xc377, + 0xc378,0xc379,0xc37a,0xc37b,0xc37c,0xc37d,0xc37e,0xc37f, + 0xc380,0xc381,0xc382,0xc383,0xc384,0xc385,0xc386,0xc387, + 0xc388,0xc389,0xc38a,0xc38b,0xc38c,0xc38d,0xc38e,0xc38f, + 0xc390,0xc391,0xc392,0xc393,0xc394,0xc395,0xc396,0xc397, + 0xc398,0xc399,0xc39a,0xc39b,0xc39c,0xc39d,0xc39e,0xc39f, + 0xc3a0,0xc3a1,0xc3a2,0xc3a3,0xc3a4,0xc3a5,0xc3a6,0xc3a7, + 0xc3a8,0xc3a9,0xc3aa,0xc3ab,0xc3ac,0xc3ad,0xc3ae,0xc3af, + 0xc3b0,0xc3b1,0xc3b2,0xc3b3,0xc3b4,0xc3b5,0xc3b6,0xc3b7, + 0xc3b8,0xc3b9,0xc3ba,0xc3bb,0xc3bc,0xc3bd,0xc3be,0xc3bf, + 0xc3c0,0xc3c1,0xc3c2,0xc3c3,0xc3c4,0xc3c5,0xc3c6,0xc3c7, + 0xc3c8,0xc3c9,0xc3ca,0xc3cb,0xc3cc,0xc3cd,0xc3ce,0xc3cf, + 0xc3d0,0xc3d1,0xc3d2,0xc3d3,0xc3d4,0xc3d5,0xc3d6,0xc3d7, + 0xc3d8,0xc3d9,0xc3da,0xc3db,0xc3dc,0xc3dd,0xc3de,0xc3df, + 0xc3e0,0xc3e1,0xc3e2,0xc3e3,0xc3e4,0xc3e5,0xc3e6,0xc3e7, + 0xc3e8,0xc3e9,0xc3ea,0xc3eb,0xc3ec,0xc3ed,0xc3ee,0xc3ef, + 0xc3f0,0xc3f1,0xc3f2,0xc3f3,0xc3f4,0xc3f5,0xc3f6,0xc3f7, + 0xc3f8,0xc3f9,0xc3fa,0xc3fb,0xc3fc,0xc3fd,0xc3fe,0xc3ff, + 0xc400,0xc401,0xc402,0xc403,0xc404,0xc405,0xc406,0xc407, + 0xc408,0xc409,0xc40a,0xc40b,0xc40c,0xc40d,0xc40e,0xc40f, + 0xc410,0xc411,0xc412,0xc413,0xc414,0xc415,0xc416,0xc417, + 0xc418,0xc419,0xc41a,0xc41b,0xc41c,0xc41d,0xc41e,0xc41f, + 0xc420,0xc421,0xc422,0xc423,0xc424,0xc425,0xc426,0xc427, + 0xc428,0xc429,0xc42a,0xc42b,0xc42c,0xc42d,0xc42e,0xc42f, + 0xc430,0xc431,0xc432,0xc433,0xc434,0xc435,0xc436,0xc437, + 0xc438,0xc439,0xc43a,0xc43b,0xc43c,0xc43d,0xc43e,0xc43f, + 0xc440,0xc441,0xc442,0xc443,0xc444,0xc445,0xc446,0xc447, + 0xc448,0xc449,0xc44a,0xc44b,0xc44c,0xc44d,0xc44e,0xc44f, + 0xc450,0xc451,0xc452,0xc453,0xc454,0xc455,0xc456,0xc457, + 0xc458,0xc459,0xc45a,0xc45b,0xc45c,0xc45d,0xc45e,0xc45f, + 0xc460,0xc461,0xc462,0xc463,0xc464,0xc465,0xc466,0xc467, + 0xc468,0xc469,0xc46a,0xc46b,0xc46c,0xc46d,0xc46e,0xc46f, + 0xc470,0xc471,0xc472,0xc473,0xc474,0xc475,0xc476,0xc477, + 0xc478,0xc479,0xc47a,0xc47b,0xc47c,0xc47d,0xc47e,0xc47f, + 0xc480,0xc481,0xc482,0xc483,0xc484,0xc485,0xc486,0xc487, + 0xc488,0xc489,0xc48a,0xc48b,0xc48c,0xc48d,0xc48e,0xc48f, + 0xc490,0xc491,0xc492,0xc493,0xc494,0xc495,0xc496,0xc497, + 0xc498,0xc499,0xc49a,0xc49b,0xc49c,0xc49d,0xc49e,0xc49f, + 0xc4a0,0xc4a1,0xc4a2,0xc4a3,0xc4a4,0xc4a5,0xc4a6,0xc4a7, + 0xc4a8,0xc4a9,0xc4aa,0xc4ab,0xc4ac,0xc4ad,0xc4ae,0xc4af, + 0xc4b0,0xc4b1,0xc4b2,0xc4b3,0xc4b4,0xc4b5,0xc4b6,0xc4b7, + 0xc4b8,0xc4b9,0xc4ba,0xc4bb,0xc4bc,0xc4bd,0xc4be,0xc4bf, + 0xc4c0,0xc4c1,0xc4c2,0xc4c3,0xc4c4,0xc4c5,0xc4c6,0xc4c7, + 0xc4c8,0xc4c9,0xc4ca,0xc4cb,0xc4cc,0xc4cd,0xc4ce,0xc4cf, + 0xc4d0,0xc4d1,0xc4d2,0xc4d3,0xc4d4,0xc4d5,0xc4d6,0xc4d7, + 0xc4d8,0xc4d9,0xc4da,0xc4db,0xc4dc,0xc4dd,0xc4de,0xc4df, + 0xc4e0,0xc4e1,0xc4e2,0xc4e3,0xc4e4,0xc4e5,0xc4e6,0xc4e7, + 0xc4e8,0xc4e9,0xc4ea,0xc4eb,0xc4ec,0xc4ed,0xc4ee,0xc4ef, + 0xc4f0,0xc4f1,0xc4f2,0xc4f3,0xc4f4,0xc4f5,0xc4f6,0xc4f7, + 0xc4f8,0xc4f9,0xc4fa,0xc4fb,0xc4fc,0xc4fd,0xc4fe,0xc4ff, + 0xc500,0xc501,0xc502,0xc503,0xc504,0xc505,0xc506,0xc507, + 0xc508,0xc509,0xc50a,0xc50b,0xc50c,0xc50d,0xc50e,0xc50f, + 0xc510,0xc511,0xc512,0xc513,0xc514,0xc515,0xc516,0xc517, + 0xc518,0xc519,0xc51a,0xc51b,0xc51c,0xc51d,0xc51e,0xc51f, + 0xc520,0xc521,0xc522,0xc523,0xc524,0xc525,0xc526,0xc527, + 0xc528,0xc529,0xc52a,0xc52b,0xc52c,0xc52d,0xc52e,0xc52f, + 0xc530,0xc531,0xc532,0xc533,0xc534,0xc535,0xc536,0xc537, + 0xc538,0xc539,0xc53a,0xc53b,0xc53c,0xc53d,0xc53e,0xc53f, + 0xc540,0xc541,0xc542,0xc543,0xc544,0xc545,0xc546,0xc547, + 0xc548,0xc549,0xc54a,0xc54b,0xc54c,0xc54d,0xc54e,0xc54f, + 0xc550,0xc551,0xc552,0xc553,0xc554,0xc555,0xc556,0xc557, + 0xc558,0xc559,0xc55a,0xc55b,0xc55c,0xc55d,0xc55e,0xc55f, + 0xc560,0xc561,0xc562,0xc563,0xc564,0xc565,0xc566,0xc567, + 0xc568,0xc569,0xc56a,0xc56b,0xc56c,0xc56d,0xc56e,0xc56f, + 0xc570,0xc571,0xc572,0xc573,0xc574,0xc575,0xc576,0xc577, + 0xc578,0xc579,0xc57a,0xc57b,0xc57c,0xc57d,0xc57e,0xc57f, + 0xc580,0xc581,0xc582,0xc583,0xc584,0xc585,0xc586,0xc587, + 0xc588,0xc589,0xc58a,0xc58b,0xc58c,0xc58d,0xc58e,0xc58f, + 0xc590,0xc591,0xc592,0xc593,0xc594,0xc595,0xc596,0xc597, + 0xc598,0xc599,0xc59a,0xc59b,0xc59c,0xc59d,0xc59e,0xc59f, + 0xc5a0,0xc5a1,0xc5a2,0xc5a3,0xc5a4,0xc5a5,0xc5a6,0xc5a7, + 0xc5a8,0xc5a9,0xc5aa,0xc5ab,0xc5ac,0xc5ad,0xc5ae,0xc5af, + 0xc5b0,0xc5b1,0xc5b2,0xc5b3,0xc5b4,0xc5b5,0xc5b6,0xc5b7, + 0xc5b8,0xc5b9,0xc5ba,0xc5bb,0xc5bc,0xc5bd,0xc5be,0xc5bf, + 0xc5c0,0xc5c1,0xc5c2,0xc5c3,0xc5c4,0xc5c5,0xc5c6,0xc5c7, + 0xc5c8,0xc5c9,0xc5ca,0xc5cb,0xc5cc,0xc5cd,0xc5ce,0xc5cf, + 0xc5d0,0xc5d1,0xc5d2,0xc5d3,0xc5d4,0xc5d5,0xc5d6,0xc5d7, + 0xc5d8,0xc5d9,0xc5da,0xc5db,0xc5dc,0xc5dd,0xc5de,0xc5df, + 0xc5e0,0xc5e1,0xc5e2,0xc5e3,0xc5e4,0xc5e5,0xc5e6,0xc5e7, + 0xc5e8,0xc5e9,0xc5ea,0xc5eb,0xc5ec,0xc5ed,0xc5ee,0xc5ef, + 0xc5f0,0xc5f1,0xc5f2,0xc5f3,0xc5f4,0xc5f5,0xc5f6,0xc5f7, + 0xc5f8,0xc5f9,0xc5fa,0xc5fb,0xc5fc,0xc5fd,0xc5fe,0xc5ff, + 0xc600,0xc601,0xc602,0xc603,0xc604,0xc605,0xc606,0xc607, + 0xc608,0xc609,0xc60a,0xc60b,0xc60c,0xc60d,0xc60e,0xc60f, + 0xc610,0xc611,0xc612,0xc613,0xc614,0xc615,0xc616,0xc617, + 0xc618,0xc619,0xc61a,0xc61b,0xc61c,0xc61d,0xc61e,0xc61f, + 0xc620,0xc621,0xc622,0xc623,0xc624,0xc625,0xc626,0xc627, + 0xc628,0xc629,0xc62a,0xc62b,0xc62c,0xc62d,0xc62e,0xc62f, + 0xc630,0xc631,0xc632,0xc633,0xc634,0xc635,0xc636,0xc637, + 0xc638,0xc639,0xc63a,0xc63b,0xc63c,0xc63d,0xc63e,0xc63f, + 0xc640,0xc641,0xc642,0xc643,0xc644,0xc645,0xc646,0xc647, + 0xc648,0xc649,0xc64a,0xc64b,0xc64c,0xc64d,0xc64e,0xc64f, + 0xc650,0xc651,0xc652,0xc653,0xc654,0xc655,0xc656,0xc657, + 0xc658,0xc659,0xc65a,0xc65b,0xc65c,0xc65d,0xc65e,0xc65f, + 0xc660,0xc661,0xc662,0xc663,0xc664,0xc665,0xc666,0xc667, + 0xc668,0xc669,0xc66a,0xc66b,0xc66c,0xc66d,0xc66e,0xc66f, + 0xc670,0xc671,0xc672,0xc673,0xc674,0xc675,0xc676,0xc677, + 0xc678,0xc679,0xc67a,0xc67b,0xc67c,0xc67d,0xc67e,0xc67f, + 0xc680,0xc681,0xc682,0xc683,0xc684,0xc685,0xc686,0xc687, + 0xc688,0xc689,0xc68a,0xc68b,0xc68c,0xc68d,0xc68e,0xc68f, + 0xc690,0xc691,0xc692,0xc693,0xc694,0xc695,0xc696,0xc697, + 0xc698,0xc699,0xc69a,0xc69b,0xc69c,0xc69d,0xc69e,0xc69f, + 0xc6a0,0xc6a1,0xc6a2,0xc6a3,0xc6a4,0xc6a5,0xc6a6,0xc6a7, + 0xc6a8,0xc6a9,0xc6aa,0xc6ab,0xc6ac,0xc6ad,0xc6ae,0xc6af, + 0xc6b0,0xc6b1,0xc6b2,0xc6b3,0xc6b4,0xc6b5,0xc6b6,0xc6b7, + 0xc6b8,0xc6b9,0xc6ba,0xc6bb,0xc6bc,0xc6bd,0xc6be,0xc6bf, + 0xc6c0,0xc6c1,0xc6c2,0xc6c3,0xc6c4,0xc6c5,0xc6c6,0xc6c7, + 0xc6c8,0xc6c9,0xc6ca,0xc6cb,0xc6cc,0xc6cd,0xc6ce,0xc6cf, + 0xc6d0,0xc6d1,0xc6d2,0xc6d3,0xc6d4,0xc6d5,0xc6d6,0xc6d7, + 0xc6d8,0xc6d9,0xc6da,0xc6db,0xc6dc,0xc6dd,0xc6de,0xc6df, + 0xc6e0,0xc6e1,0xc6e2,0xc6e3,0xc6e4,0xc6e5,0xc6e6,0xc6e7, + 0xc6e8,0xc6e9,0xc6ea,0xc6eb,0xc6ec,0xc6ed,0xc6ee,0xc6ef, + 0xc6f0,0xc6f1,0xc6f2,0xc6f3,0xc6f4,0xc6f5,0xc6f6,0xc6f7, + 0xc6f8,0xc6f9,0xc6fa,0xc6fb,0xc6fc,0xc6fd,0xc6fe,0xc6ff, + 0xc700,0xc701,0xc702,0xc703,0xc704,0xc705,0xc706,0xc707, + 0xc708,0xc709,0xc70a,0xc70b,0xc70c,0xc70d,0xc70e,0xc70f, + 0xc710,0xc711,0xc712,0xc713,0xc714,0xc715,0xc716,0xc717, + 0xc718,0xc719,0xc71a,0xc71b,0xc71c,0xc71d,0xc71e,0xc71f, + 0xc720,0xc721,0xc722,0xc723,0xc724,0xc725,0xc726,0xc727, + 0xc728,0xc729,0xc72a,0xc72b,0xc72c,0xc72d,0xc72e,0xc72f, + 0xc730,0xc731,0xc732,0xc733,0xc734,0xc735,0xc736,0xc737, + 0xc738,0xc739,0xc73a,0xc73b,0xc73c,0xc73d,0xc73e,0xc73f, + 0xc740,0xc741,0xc742,0xc743,0xc744,0xc745,0xc746,0xc747, + 0xc748,0xc749,0xc74a,0xc74b,0xc74c,0xc74d,0xc74e,0xc74f, + 0xc750,0xc751,0xc752,0xc753,0xc754,0xc755,0xc756,0xc757, + 0xc758,0xc759,0xc75a,0xc75b,0xc75c,0xc75d,0xc75e,0xc75f, + 0xc760,0xc761,0xc762,0xc763,0xc764,0xc765,0xc766,0xc767, + 0xc768,0xc769,0xc76a,0xc76b,0xc76c,0xc76d,0xc76e,0xc76f, + 0xc770,0xc771,0xc772,0xc773,0xc774,0xc775,0xc776,0xc777, + 0xc778,0xc779,0xc77a,0xc77b,0xc77c,0xc77d,0xc77e,0xc77f, + 0xc780,0xc781,0xc782,0xc783,0xc784,0xc785,0xc786,0xc787, + 0xc788,0xc789,0xc78a,0xc78b,0xc78c,0xc78d,0xc78e,0xc78f, + 0xc790,0xc791,0xc792,0xc793,0xc794,0xc795,0xc796,0xc797, + 0xc798,0xc799,0xc79a,0xc79b,0xc79c,0xc79d,0xc79e,0xc79f, + 0xc7a0,0xc7a1,0xc7a2,0xc7a3,0xc7a4,0xc7a5,0xc7a6,0xc7a7, + 0xc7a8,0xc7a9,0xc7aa,0xc7ab,0xc7ac,0xc7ad,0xc7ae,0xc7af, + 0xc7b0,0xc7b1,0xc7b2,0xc7b3,0xc7b4,0xc7b5,0xc7b6,0xc7b7, + 0xc7b8,0xc7b9,0xc7ba,0xc7bb,0xc7bc,0xc7bd,0xc7be,0xc7bf, + 0xc7c0,0xc7c1,0xc7c2,0xc7c3,0xc7c4,0xc7c5,0xc7c6,0xc7c7, + 0xc7c8,0xc7c9,0xc7ca,0xc7cb,0xc7cc,0xc7cd,0xc7ce,0xc7cf, + 0xc7d0,0xc7d1,0xc7d2,0xc7d3,0xc7d4,0xc7d5,0xc7d6,0xc7d7, + 0xc7d8,0xc7d9,0xc7da,0xc7db,0xc7dc,0xc7dd,0xc7de,0xc7df, + 0xc7e0,0xc7e1,0xc7e2,0xc7e3,0xc7e4,0xc7e5,0xc7e6,0xc7e7, + 0xc7e8,0xc7e9,0xc7ea,0xc7eb,0xc7ec,0xc7ed,0xc7ee,0xc7ef, + 0xc7f0,0xc7f1,0xc7f2,0xc7f3,0xc7f4,0xc7f5,0xc7f6,0xc7f7, + 0xc7f8,0xc7f9,0xc7fa,0xc7fb,0xc7fc,0xc7fd,0xc7fe,0xc7ff, + 0xc800,0xc801,0xc802,0xc803,0xc804,0xc805,0xc806,0xc807, + 0xc808,0xc809,0xc80a,0xc80b,0xc80c,0xc80d,0xc80e,0xc80f, + 0xc810,0xc811,0xc812,0xc813,0xc814,0xc815,0xc816,0xc817, + 0xc818,0xc819,0xc81a,0xc81b,0xc81c,0xc81d,0xc81e,0xc81f, + 0xc820,0xc821,0xc822,0xc823,0xc824,0xc825,0xc826,0xc827, + 0xc828,0xc829,0xc82a,0xc82b,0xc82c,0xc82d,0xc82e,0xc82f, + 0xc830,0xc831,0xc832,0xc833,0xc834,0xc835,0xc836,0xc837, + 0xc838,0xc839,0xc83a,0xc83b,0xc83c,0xc83d,0xc83e,0xc83f, + 0xc840,0xc841,0xc842,0xc843,0xc844,0xc845,0xc846,0xc847, + 0xc848,0xc849,0xc84a,0xc84b,0xc84c,0xc84d,0xc84e,0xc84f, + 0xc850,0xc851,0xc852,0xc853,0xc854,0xc855,0xc856,0xc857, + 0xc858,0xc859,0xc85a,0xc85b,0xc85c,0xc85d,0xc85e,0xc85f, + 0xc860,0xc861,0xc862,0xc863,0xc864,0xc865,0xc866,0xc867, + 0xc868,0xc869,0xc86a,0xc86b,0xc86c,0xc86d,0xc86e,0xc86f, + 0xc870,0xc871,0xc872,0xc873,0xc874,0xc875,0xc876,0xc877, + 0xc878,0xc879,0xc87a,0xc87b,0xc87c,0xc87d,0xc87e,0xc87f, + 0xc880,0xc881,0xc882,0xc883,0xc884,0xc885,0xc886,0xc887, + 0xc888,0xc889,0xc88a,0xc88b,0xc88c,0xc88d,0xc88e,0xc88f, + 0xc890,0xc891,0xc892,0xc893,0xc894,0xc895,0xc896,0xc897, + 0xc898,0xc899,0xc89a,0xc89b,0xc89c,0xc89d,0xc89e,0xc89f, + 0xc8a0,0xc8a1,0xc8a2,0xc8a3,0xc8a4,0xc8a5,0xc8a6,0xc8a7, + 0xc8a8,0xc8a9,0xc8aa,0xc8ab,0xc8ac,0xc8ad,0xc8ae,0xc8af, + 0xc8b0,0xc8b1,0xc8b2,0xc8b3,0xc8b4,0xc8b5,0xc8b6,0xc8b7, + 0xc8b8,0xc8b9,0xc8ba,0xc8bb,0xc8bc,0xc8bd,0xc8be,0xc8bf, + 0xc8c0,0xc8c1,0xc8c2,0xc8c3,0xc8c4,0xc8c5,0xc8c6,0xc8c7, + 0xc8c8,0xc8c9,0xc8ca,0xc8cb,0xc8cc,0xc8cd,0xc8ce,0xc8cf, + 0xc8d0,0xc8d1,0xc8d2,0xc8d3,0xc8d4,0xc8d5,0xc8d6,0xc8d7, + 0xc8d8,0xc8d9,0xc8da,0xc8db,0xc8dc,0xc8dd,0xc8de,0xc8df, + 0xc8e0,0xc8e1,0xc8e2,0xc8e3,0xc8e4,0xc8e5,0xc8e6,0xc8e7, + 0xc8e8,0xc8e9,0xc8ea,0xc8eb,0xc8ec,0xc8ed,0xc8ee,0xc8ef, + 0xc8f0,0xc8f1,0xc8f2,0xc8f3,0xc8f4,0xc8f5,0xc8f6,0xc8f7, + 0xc8f8,0xc8f9,0xc8fa,0xc8fb,0xc8fc,0xc8fd,0xc8fe,0xc8ff, + 0xc900,0xc901,0xc902,0xc903,0xc904,0xc905,0xc906,0xc907, + 0xc908,0xc909,0xc90a,0xc90b,0xc90c,0xc90d,0xc90e,0xc90f, + 0xc910,0xc911,0xc912,0xc913,0xc914,0xc915,0xc916,0xc917, + 0xc918,0xc919,0xc91a,0xc91b,0xc91c,0xc91d,0xc91e,0xc91f, + 0xc920,0xc921,0xc922,0xc923,0xc924,0xc925,0xc926,0xc927, + 0xc928,0xc929,0xc92a,0xc92b,0xc92c,0xc92d,0xc92e,0xc92f, + 0xc930,0xc931,0xc932,0xc933,0xc934,0xc935,0xc936,0xc937, + 0xc938,0xc939,0xc93a,0xc93b,0xc93c,0xc93d,0xc93e,0xc93f, + 0xc940,0xc941,0xc942,0xc943,0xc944,0xc945,0xc946,0xc947, + 0xc948,0xc949,0xc94a,0xc94b,0xc94c,0xc94d,0xc94e,0xc94f, + 0xc950,0xc951,0xc952,0xc953,0xc954,0xc955,0xc956,0xc957, + 0xc958,0xc959,0xc95a,0xc95b,0xc95c,0xc95d,0xc95e,0xc95f, + 0xc960,0xc961,0xc962,0xc963,0xc964,0xc965,0xc966,0xc967, + 0xc968,0xc969,0xc96a,0xc96b,0xc96c,0xc96d,0xc96e,0xc96f, + 0xc970,0xc971,0xc972,0xc973,0xc974,0xc975,0xc976,0xc977, + 0xc978,0xc979,0xc97a,0xc97b,0xc97c,0xc97d,0xc97e,0xc97f, + 0xc980,0xc981,0xc982,0xc983,0xc984,0xc985,0xc986,0xc987, + 0xc988,0xc989,0xc98a,0xc98b,0xc98c,0xc98d,0xc98e,0xc98f, + 0xc990,0xc991,0xc992,0xc993,0xc994,0xc995,0xc996,0xc997, + 0xc998,0xc999,0xc99a,0xc99b,0xc99c,0xc99d,0xc99e,0xc99f, + 0xc9a0,0xc9a1,0xc9a2,0xc9a3,0xc9a4,0xc9a5,0xc9a6,0xc9a7, + 0xc9a8,0xc9a9,0xc9aa,0xc9ab,0xc9ac,0xc9ad,0xc9ae,0xc9af, + 0xc9b0,0xc9b1,0xc9b2,0xc9b3,0xc9b4,0xc9b5,0xc9b6,0xc9b7, + 0xc9b8,0xc9b9,0xc9ba,0xc9bb,0xc9bc,0xc9bd,0xc9be,0xc9bf, + 0xc9c0,0xc9c1,0xc9c2,0xc9c3,0xc9c4,0xc9c5,0xc9c6,0xc9c7, + 0xc9c8,0xc9c9,0xc9ca,0xc9cb,0xc9cc,0xc9cd,0xc9ce,0xc9cf, + 0xc9d0,0xc9d1,0xc9d2,0xc9d3,0xc9d4,0xc9d5,0xc9d6,0xc9d7, + 0xc9d8,0xc9d9,0xc9da,0xc9db,0xc9dc,0xc9dd,0xc9de,0xc9df, + 0xc9e0,0xc9e1,0xc9e2,0xc9e3,0xc9e4,0xc9e5,0xc9e6,0xc9e7, + 0xc9e8,0xc9e9,0xc9ea,0xc9eb,0xc9ec,0xc9ed,0xc9ee,0xc9ef, + 0xc9f0,0xc9f1,0xc9f2,0xc9f3,0xc9f4,0xc9f5,0xc9f6,0xc9f7, + 0xc9f8,0xc9f9,0xc9fa,0xc9fb,0xc9fc,0xc9fd,0xc9fe,0xc9ff, + 0xca00,0xca01,0xca02,0xca03,0xca04,0xca05,0xca06,0xca07, + 0xca08,0xca09,0xca0a,0xca0b,0xca0c,0xca0d,0xca0e,0xca0f, + 0xca10,0xca11,0xca12,0xca13,0xca14,0xca15,0xca16,0xca17, + 0xca18,0xca19,0xca1a,0xca1b,0xca1c,0xca1d,0xca1e,0xca1f, + 0xca20,0xca21,0xca22,0xca23,0xca24,0xca25,0xca26,0xca27, + 0xca28,0xca29,0xca2a,0xca2b,0xca2c,0xca2d,0xca2e,0xca2f, + 0xca30,0xca31,0xca32,0xca33,0xca34,0xca35,0xca36,0xca37, + 0xca38,0xca39,0xca3a,0xca3b,0xca3c,0xca3d,0xca3e,0xca3f, + 0xca40,0xca41,0xca42,0xca43,0xca44,0xca45,0xca46,0xca47, + 0xca48,0xca49,0xca4a,0xca4b,0xca4c,0xca4d,0xca4e,0xca4f, + 0xca50,0xca51,0xca52,0xca53,0xca54,0xca55,0xca56,0xca57, + 0xca58,0xca59,0xca5a,0xca5b,0xca5c,0xca5d,0xca5e,0xca5f, + 0xca60,0xca61,0xca62,0xca63,0xca64,0xca65,0xca66,0xca67, + 0xca68,0xca69,0xca6a,0xca6b,0xca6c,0xca6d,0xca6e,0xca6f, + 0xca70,0xca71,0xca72,0xca73,0xca74,0xca75,0xca76,0xca77, + 0xca78,0xca79,0xca7a,0xca7b,0xca7c,0xca7d,0xca7e,0xca7f, + 0xca80,0xca81,0xca82,0xca83,0xca84,0xca85,0xca86,0xca87, + 0xca88,0xca89,0xca8a,0xca8b,0xca8c,0xca8d,0xca8e,0xca8f, + 0xca90,0xca91,0xca92,0xca93,0xca94,0xca95,0xca96,0xca97, + 0xca98,0xca99,0xca9a,0xca9b,0xca9c,0xca9d,0xca9e,0xca9f, + 0xcaa0,0xcaa1,0xcaa2,0xcaa3,0xcaa4,0xcaa5,0xcaa6,0xcaa7, + 0xcaa8,0xcaa9,0xcaaa,0xcaab,0xcaac,0xcaad,0xcaae,0xcaaf, + 0xcab0,0xcab1,0xcab2,0xcab3,0xcab4,0xcab5,0xcab6,0xcab7, + 0xcab8,0xcab9,0xcaba,0xcabb,0xcabc,0xcabd,0xcabe,0xcabf, + 0xcac0,0xcac1,0xcac2,0xcac3,0xcac4,0xcac5,0xcac6,0xcac7, + 0xcac8,0xcac9,0xcaca,0xcacb,0xcacc,0xcacd,0xcace,0xcacf, + 0xcad0,0xcad1,0xcad2,0xcad3,0xcad4,0xcad5,0xcad6,0xcad7, + 0xcad8,0xcad9,0xcada,0xcadb,0xcadc,0xcadd,0xcade,0xcadf, + 0xcae0,0xcae1,0xcae2,0xcae3,0xcae4,0xcae5,0xcae6,0xcae7, + 0xcae8,0xcae9,0xcaea,0xcaeb,0xcaec,0xcaed,0xcaee,0xcaef, + 0xcaf0,0xcaf1,0xcaf2,0xcaf3,0xcaf4,0xcaf5,0xcaf6,0xcaf7, + 0xcaf8,0xcaf9,0xcafa,0xcafb,0xcafc,0xcafd,0xcafe,0xcaff, + 0xcb00,0xcb01,0xcb02,0xcb03,0xcb04,0xcb05,0xcb06,0xcb07, + 0xcb08,0xcb09,0xcb0a,0xcb0b,0xcb0c,0xcb0d,0xcb0e,0xcb0f, + 0xcb10,0xcb11,0xcb12,0xcb13,0xcb14,0xcb15,0xcb16,0xcb17, + 0xcb18,0xcb19,0xcb1a,0xcb1b,0xcb1c,0xcb1d,0xcb1e,0xcb1f, + 0xcb20,0xcb21,0xcb22,0xcb23,0xcb24,0xcb25,0xcb26,0xcb27, + 0xcb28,0xcb29,0xcb2a,0xcb2b,0xcb2c,0xcb2d,0xcb2e,0xcb2f, + 0xcb30,0xcb31,0xcb32,0xcb33,0xcb34,0xcb35,0xcb36,0xcb37, + 0xcb38,0xcb39,0xcb3a,0xcb3b,0xcb3c,0xcb3d,0xcb3e,0xcb3f, + 0xcb40,0xcb41,0xcb42,0xcb43,0xcb44,0xcb45,0xcb46,0xcb47, + 0xcb48,0xcb49,0xcb4a,0xcb4b,0xcb4c,0xcb4d,0xcb4e,0xcb4f, + 0xcb50,0xcb51,0xcb52,0xcb53,0xcb54,0xcb55,0xcb56,0xcb57, + 0xcb58,0xcb59,0xcb5a,0xcb5b,0xcb5c,0xcb5d,0xcb5e,0xcb5f, + 0xcb60,0xcb61,0xcb62,0xcb63,0xcb64,0xcb65,0xcb66,0xcb67, + 0xcb68,0xcb69,0xcb6a,0xcb6b,0xcb6c,0xcb6d,0xcb6e,0xcb6f, + 0xcb70,0xcb71,0xcb72,0xcb73,0xcb74,0xcb75,0xcb76,0xcb77, + 0xcb78,0xcb79,0xcb7a,0xcb7b,0xcb7c,0xcb7d,0xcb7e,0xcb7f, + 0xcb80,0xcb81,0xcb82,0xcb83,0xcb84,0xcb85,0xcb86,0xcb87, + 0xcb88,0xcb89,0xcb8a,0xcb8b,0xcb8c,0xcb8d,0xcb8e,0xcb8f, + 0xcb90,0xcb91,0xcb92,0xcb93,0xcb94,0xcb95,0xcb96,0xcb97, + 0xcb98,0xcb99,0xcb9a,0xcb9b,0xcb9c,0xcb9d,0xcb9e,0xcb9f, + 0xcba0,0xcba1,0xcba2,0xcba3,0xcba4,0xcba5,0xcba6,0xcba7, + 0xcba8,0xcba9,0xcbaa,0xcbab,0xcbac,0xcbad,0xcbae,0xcbaf, + 0xcbb0,0xcbb1,0xcbb2,0xcbb3,0xcbb4,0xcbb5,0xcbb6,0xcbb7, + 0xcbb8,0xcbb9,0xcbba,0xcbbb,0xcbbc,0xcbbd,0xcbbe,0xcbbf, + 0xcbc0,0xcbc1,0xcbc2,0xcbc3,0xcbc4,0xcbc5,0xcbc6,0xcbc7, + 0xcbc8,0xcbc9,0xcbca,0xcbcb,0xcbcc,0xcbcd,0xcbce,0xcbcf, + 0xcbd0,0xcbd1,0xcbd2,0xcbd3,0xcbd4,0xcbd5,0xcbd6,0xcbd7, + 0xcbd8,0xcbd9,0xcbda,0xcbdb,0xcbdc,0xcbdd,0xcbde,0xcbdf, + 0xcbe0,0xcbe1,0xcbe2,0xcbe3,0xcbe4,0xcbe5,0xcbe6,0xcbe7, + 0xcbe8,0xcbe9,0xcbea,0xcbeb,0xcbec,0xcbed,0xcbee,0xcbef, + 0xcbf0,0xcbf1,0xcbf2,0xcbf3,0xcbf4,0xcbf5,0xcbf6,0xcbf7, + 0xcbf8,0xcbf9,0xcbfa,0xcbfb,0xcbfc,0xcbfd,0xcbfe,0xcbff, + 0xcc00,0xcc01,0xcc02,0xcc03,0xcc04,0xcc05,0xcc06,0xcc07, + 0xcc08,0xcc09,0xcc0a,0xcc0b,0xcc0c,0xcc0d,0xcc0e,0xcc0f, + 0xcc10,0xcc11,0xcc12,0xcc13,0xcc14,0xcc15,0xcc16,0xcc17, + 0xcc18,0xcc19,0xcc1a,0xcc1b,0xcc1c,0xcc1d,0xcc1e,0xcc1f, + 0xcc20,0xcc21,0xcc22,0xcc23,0xcc24,0xcc25,0xcc26,0xcc27, + 0xcc28,0xcc29,0xcc2a,0xcc2b,0xcc2c,0xcc2d,0xcc2e,0xcc2f, + 0xcc30,0xcc31,0xcc32,0xcc33,0xcc34,0xcc35,0xcc36,0xcc37, + 0xcc38,0xcc39,0xcc3a,0xcc3b,0xcc3c,0xcc3d,0xcc3e,0xcc3f, + 0xcc40,0xcc41,0xcc42,0xcc43,0xcc44,0xcc45,0xcc46,0xcc47, + 0xcc48,0xcc49,0xcc4a,0xcc4b,0xcc4c,0xcc4d,0xcc4e,0xcc4f, + 0xcc50,0xcc51,0xcc52,0xcc53,0xcc54,0xcc55,0xcc56,0xcc57, + 0xcc58,0xcc59,0xcc5a,0xcc5b,0xcc5c,0xcc5d,0xcc5e,0xcc5f, + 0xcc60,0xcc61,0xcc62,0xcc63,0xcc64,0xcc65,0xcc66,0xcc67, + 0xcc68,0xcc69,0xcc6a,0xcc6b,0xcc6c,0xcc6d,0xcc6e,0xcc6f, + 0xcc70,0xcc71,0xcc72,0xcc73,0xcc74,0xcc75,0xcc76,0xcc77, + 0xcc78,0xcc79,0xcc7a,0xcc7b,0xcc7c,0xcc7d,0xcc7e,0xcc7f, + 0xcc80,0xcc81,0xcc82,0xcc83,0xcc84,0xcc85,0xcc86,0xcc87, + 0xcc88,0xcc89,0xcc8a,0xcc8b,0xcc8c,0xcc8d,0xcc8e,0xcc8f, + 0xcc90,0xcc91,0xcc92,0xcc93,0xcc94,0xcc95,0xcc96,0xcc97, + 0xcc98,0xcc99,0xcc9a,0xcc9b,0xcc9c,0xcc9d,0xcc9e,0xcc9f, + 0xcca0,0xcca1,0xcca2,0xcca3,0xcca4,0xcca5,0xcca6,0xcca7, + 0xcca8,0xcca9,0xccaa,0xccab,0xccac,0xccad,0xccae,0xccaf, + 0xccb0,0xccb1,0xccb2,0xccb3,0xccb4,0xccb5,0xccb6,0xccb7, + 0xccb8,0xccb9,0xccba,0xccbb,0xccbc,0xccbd,0xccbe,0xccbf, + 0xccc0,0xccc1,0xccc2,0xccc3,0xccc4,0xccc5,0xccc6,0xccc7, + 0xccc8,0xccc9,0xccca,0xcccb,0xcccc,0xcccd,0xccce,0xcccf, + 0xccd0,0xccd1,0xccd2,0xccd3,0xccd4,0xccd5,0xccd6,0xccd7, + 0xccd8,0xccd9,0xccda,0xccdb,0xccdc,0xccdd,0xccde,0xccdf, + 0xcce0,0xcce1,0xcce2,0xcce3,0xcce4,0xcce5,0xcce6,0xcce7, + 0xcce8,0xcce9,0xccea,0xcceb,0xccec,0xcced,0xccee,0xccef, + 0xccf0,0xccf1,0xccf2,0xccf3,0xccf4,0xccf5,0xccf6,0xccf7, + 0xccf8,0xccf9,0xccfa,0xccfb,0xccfc,0xccfd,0xccfe,0xccff, + 0xcd00,0xcd01,0xcd02,0xcd03,0xcd04,0xcd05,0xcd06,0xcd07, + 0xcd08,0xcd09,0xcd0a,0xcd0b,0xcd0c,0xcd0d,0xcd0e,0xcd0f, + 0xcd10,0xcd11,0xcd12,0xcd13,0xcd14,0xcd15,0xcd16,0xcd17, + 0xcd18,0xcd19,0xcd1a,0xcd1b,0xcd1c,0xcd1d,0xcd1e,0xcd1f, + 0xcd20,0xcd21,0xcd22,0xcd23,0xcd24,0xcd25,0xcd26,0xcd27, + 0xcd28,0xcd29,0xcd2a,0xcd2b,0xcd2c,0xcd2d,0xcd2e,0xcd2f, + 0xcd30,0xcd31,0xcd32,0xcd33,0xcd34,0xcd35,0xcd36,0xcd37, + 0xcd38,0xcd39,0xcd3a,0xcd3b,0xcd3c,0xcd3d,0xcd3e,0xcd3f, + 0xcd40,0xcd41,0xcd42,0xcd43,0xcd44,0xcd45,0xcd46,0xcd47, + 0xcd48,0xcd49,0xcd4a,0xcd4b,0xcd4c,0xcd4d,0xcd4e,0xcd4f, + 0xcd50,0xcd51,0xcd52,0xcd53,0xcd54,0xcd55,0xcd56,0xcd57, + 0xcd58,0xcd59,0xcd5a,0xcd5b,0xcd5c,0xcd5d,0xcd5e,0xcd5f, + 0xcd60,0xcd61,0xcd62,0xcd63,0xcd64,0xcd65,0xcd66,0xcd67, + 0xcd68,0xcd69,0xcd6a,0xcd6b,0xcd6c,0xcd6d,0xcd6e,0xcd6f, + 0xcd70,0xcd71,0xcd72,0xcd73,0xcd74,0xcd75,0xcd76,0xcd77, + 0xcd78,0xcd79,0xcd7a,0xcd7b,0xcd7c,0xcd7d,0xcd7e,0xcd7f, + 0xcd80,0xcd81,0xcd82,0xcd83,0xcd84,0xcd85,0xcd86,0xcd87, + 0xcd88,0xcd89,0xcd8a,0xcd8b,0xcd8c,0xcd8d,0xcd8e,0xcd8f, + 0xcd90,0xcd91,0xcd92,0xcd93,0xcd94,0xcd95,0xcd96,0xcd97, + 0xcd98,0xcd99,0xcd9a,0xcd9b,0xcd9c,0xcd9d,0xcd9e,0xcd9f, + 0xcda0,0xcda1,0xcda2,0xcda3,0xcda4,0xcda5,0xcda6,0xcda7, + 0xcda8,0xcda9,0xcdaa,0xcdab,0xcdac,0xcdad,0xcdae,0xcdaf, + 0xcdb0,0xcdb1,0xcdb2,0xcdb3,0xcdb4,0xcdb5,0xcdb6,0xcdb7, + 0xcdb8,0xcdb9,0xcdba,0xcdbb,0xcdbc,0xcdbd,0xcdbe,0xcdbf, + 0xcdc0,0xcdc1,0xcdc2,0xcdc3,0xcdc4,0xcdc5,0xcdc6,0xcdc7, + 0xcdc8,0xcdc9,0xcdca,0xcdcb,0xcdcc,0xcdcd,0xcdce,0xcdcf, + 0xcdd0,0xcdd1,0xcdd2,0xcdd3,0xcdd4,0xcdd5,0xcdd6,0xcdd7, + 0xcdd8,0xcdd9,0xcdda,0xcddb,0xcddc,0xcddd,0xcdde,0xcddf, + 0xcde0,0xcde1,0xcde2,0xcde3,0xcde4,0xcde5,0xcde6,0xcde7, + 0xcde8,0xcde9,0xcdea,0xcdeb,0xcdec,0xcded,0xcdee,0xcdef, + 0xcdf0,0xcdf1,0xcdf2,0xcdf3,0xcdf4,0xcdf5,0xcdf6,0xcdf7, + 0xcdf8,0xcdf9,0xcdfa,0xcdfb,0xcdfc,0xcdfd,0xcdfe,0xcdff, + 0xce00,0xce01,0xce02,0xce03,0xce04,0xce05,0xce06,0xce07, + 0xce08,0xce09,0xce0a,0xce0b,0xce0c,0xce0d,0xce0e,0xce0f, + 0xce10,0xce11,0xce12,0xce13,0xce14,0xce15,0xce16,0xce17, + 0xce18,0xce19,0xce1a,0xce1b,0xce1c,0xce1d,0xce1e,0xce1f, + 0xce20,0xce21,0xce22,0xce23,0xce24,0xce25,0xce26,0xce27, + 0xce28,0xce29,0xce2a,0xce2b,0xce2c,0xce2d,0xce2e,0xce2f, + 0xce30,0xce31,0xce32,0xce33,0xce34,0xce35,0xce36,0xce37, + 0xce38,0xce39,0xce3a,0xce3b,0xce3c,0xce3d,0xce3e,0xce3f, + 0xce40,0xce41,0xce42,0xce43,0xce44,0xce45,0xce46,0xce47, + 0xce48,0xce49,0xce4a,0xce4b,0xce4c,0xce4d,0xce4e,0xce4f, + 0xce50,0xce51,0xce52,0xce53,0xce54,0xce55,0xce56,0xce57, + 0xce58,0xce59,0xce5a,0xce5b,0xce5c,0xce5d,0xce5e,0xce5f, + 0xce60,0xce61,0xce62,0xce63,0xce64,0xce65,0xce66,0xce67, + 0xce68,0xce69,0xce6a,0xce6b,0xce6c,0xce6d,0xce6e,0xce6f, + 0xce70,0xce71,0xce72,0xce73,0xce74,0xce75,0xce76,0xce77, + 0xce78,0xce79,0xce7a,0xce7b,0xce7c,0xce7d,0xce7e,0xce7f, + 0xce80,0xce81,0xce82,0xce83,0xce84,0xce85,0xce86,0xce87, + 0xce88,0xce89,0xce8a,0xce8b,0xce8c,0xce8d,0xce8e,0xce8f, + 0xce90,0xce91,0xce92,0xce93,0xce94,0xce95,0xce96,0xce97, + 0xce98,0xce99,0xce9a,0xce9b,0xce9c,0xce9d,0xce9e,0xce9f, + 0xcea0,0xcea1,0xcea2,0xcea3,0xcea4,0xcea5,0xcea6,0xcea7, + 0xcea8,0xcea9,0xceaa,0xceab,0xceac,0xcead,0xceae,0xceaf, + 0xceb0,0xceb1,0xceb2,0xceb3,0xceb4,0xceb5,0xceb6,0xceb7, + 0xceb8,0xceb9,0xceba,0xcebb,0xcebc,0xcebd,0xcebe,0xcebf, + 0xcec0,0xcec1,0xcec2,0xcec3,0xcec4,0xcec5,0xcec6,0xcec7, + 0xcec8,0xcec9,0xceca,0xcecb,0xcecc,0xcecd,0xcece,0xcecf, + 0xced0,0xced1,0xced2,0xced3,0xced4,0xced5,0xced6,0xced7, + 0xced8,0xced9,0xceda,0xcedb,0xcedc,0xcedd,0xcede,0xcedf, + 0xcee0,0xcee1,0xcee2,0xcee3,0xcee4,0xcee5,0xcee6,0xcee7, + 0xcee8,0xcee9,0xceea,0xceeb,0xceec,0xceed,0xceee,0xceef, + 0xcef0,0xcef1,0xcef2,0xcef3,0xcef4,0xcef5,0xcef6,0xcef7, + 0xcef8,0xcef9,0xcefa,0xcefb,0xcefc,0xcefd,0xcefe,0xceff, + 0xcf00,0xcf01,0xcf02,0xcf03,0xcf04,0xcf05,0xcf06,0xcf07, + 0xcf08,0xcf09,0xcf0a,0xcf0b,0xcf0c,0xcf0d,0xcf0e,0xcf0f, + 0xcf10,0xcf11,0xcf12,0xcf13,0xcf14,0xcf15,0xcf16,0xcf17, + 0xcf18,0xcf19,0xcf1a,0xcf1b,0xcf1c,0xcf1d,0xcf1e,0xcf1f, + 0xcf20,0xcf21,0xcf22,0xcf23,0xcf24,0xcf25,0xcf26,0xcf27, + 0xcf28,0xcf29,0xcf2a,0xcf2b,0xcf2c,0xcf2d,0xcf2e,0xcf2f, + 0xcf30,0xcf31,0xcf32,0xcf33,0xcf34,0xcf35,0xcf36,0xcf37, + 0xcf38,0xcf39,0xcf3a,0xcf3b,0xcf3c,0xcf3d,0xcf3e,0xcf3f, + 0xcf40,0xcf41,0xcf42,0xcf43,0xcf44,0xcf45,0xcf46,0xcf47, + 0xcf48,0xcf49,0xcf4a,0xcf4b,0xcf4c,0xcf4d,0xcf4e,0xcf4f, + 0xcf50,0xcf51,0xcf52,0xcf53,0xcf54,0xcf55,0xcf56,0xcf57, + 0xcf58,0xcf59,0xcf5a,0xcf5b,0xcf5c,0xcf5d,0xcf5e,0xcf5f, + 0xcf60,0xcf61,0xcf62,0xcf63,0xcf64,0xcf65,0xcf66,0xcf67, + 0xcf68,0xcf69,0xcf6a,0xcf6b,0xcf6c,0xcf6d,0xcf6e,0xcf6f, + 0xcf70,0xcf71,0xcf72,0xcf73,0xcf74,0xcf75,0xcf76,0xcf77, + 0xcf78,0xcf79,0xcf7a,0xcf7b,0xcf7c,0xcf7d,0xcf7e,0xcf7f, + 0xcf80,0xcf81,0xcf82,0xcf83,0xcf84,0xcf85,0xcf86,0xcf87, + 0xcf88,0xcf89,0xcf8a,0xcf8b,0xcf8c,0xcf8d,0xcf8e,0xcf8f, + 0xcf90,0xcf91,0xcf92,0xcf93,0xcf94,0xcf95,0xcf96,0xcf97, + 0xcf98,0xcf99,0xcf9a,0xcf9b,0xcf9c,0xcf9d,0xcf9e,0xcf9f, + 0xcfa0,0xcfa1,0xcfa2,0xcfa3,0xcfa4,0xcfa5,0xcfa6,0xcfa7, + 0xcfa8,0xcfa9,0xcfaa,0xcfab,0xcfac,0xcfad,0xcfae,0xcfaf, + 0xcfb0,0xcfb1,0xcfb2,0xcfb3,0xcfb4,0xcfb5,0xcfb6,0xcfb7, + 0xcfb8,0xcfb9,0xcfba,0xcfbb,0xcfbc,0xcfbd,0xcfbe,0xcfbf, + 0xcfc0,0xcfc1,0xcfc2,0xcfc3,0xcfc4,0xcfc5,0xcfc6,0xcfc7, + 0xcfc8,0xcfc9,0xcfca,0xcfcb,0xcfcc,0xcfcd,0xcfce,0xcfcf, + 0xcfd0,0xcfd1,0xcfd2,0xcfd3,0xcfd4,0xcfd5,0xcfd6,0xcfd7, + 0xcfd8,0xcfd9,0xcfda,0xcfdb,0xcfdc,0xcfdd,0xcfde,0xcfdf, + 0xcfe0,0xcfe1,0xcfe2,0xcfe3,0xcfe4,0xcfe5,0xcfe6,0xcfe7, + 0xcfe8,0xcfe9,0xcfea,0xcfeb,0xcfec,0xcfed,0xcfee,0xcfef, + 0xcff0,0xcff1,0xcff2,0xcff3,0xcff4,0xcff5,0xcff6,0xcff7, + 0xcff8,0xcff9,0xcffa,0xcffb,0xcffc,0xcffd,0xcffe,0xcfff, + 0xd000,0xd001,0xd002,0xd003,0xd004,0xd005,0xd006,0xd007, + 0xd008,0xd009,0xd00a,0xd00b,0xd00c,0xd00d,0xd00e,0xd00f, + 0xd010,0xd011,0xd012,0xd013,0xd014,0xd015,0xd016,0xd017, + 0xd018,0xd019,0xd01a,0xd01b,0xd01c,0xd01d,0xd01e,0xd01f, + 0xd020,0xd021,0xd022,0xd023,0xd024,0xd025,0xd026,0xd027, + 0xd028,0xd029,0xd02a,0xd02b,0xd02c,0xd02d,0xd02e,0xd02f, + 0xd030,0xd031,0xd032,0xd033,0xd034,0xd035,0xd036,0xd037, + 0xd038,0xd039,0xd03a,0xd03b,0xd03c,0xd03d,0xd03e,0xd03f, + 0xd040,0xd041,0xd042,0xd043,0xd044,0xd045,0xd046,0xd047, + 0xd048,0xd049,0xd04a,0xd04b,0xd04c,0xd04d,0xd04e,0xd04f, + 0xd050,0xd051,0xd052,0xd053,0xd054,0xd055,0xd056,0xd057, + 0xd058,0xd059,0xd05a,0xd05b,0xd05c,0xd05d,0xd05e,0xd05f, + 0xd060,0xd061,0xd062,0xd063,0xd064,0xd065,0xd066,0xd067, + 0xd068,0xd069,0xd06a,0xd06b,0xd06c,0xd06d,0xd06e,0xd06f, + 0xd070,0xd071,0xd072,0xd073,0xd074,0xd075,0xd076,0xd077, + 0xd078,0xd079,0xd07a,0xd07b,0xd07c,0xd07d,0xd07e,0xd07f, + 0xd080,0xd081,0xd082,0xd083,0xd084,0xd085,0xd086,0xd087, + 0xd088,0xd089,0xd08a,0xd08b,0xd08c,0xd08d,0xd08e,0xd08f, + 0xd090,0xd091,0xd092,0xd093,0xd094,0xd095,0xd096,0xd097, + 0xd098,0xd099,0xd09a,0xd09b,0xd09c,0xd09d,0xd09e,0xd09f, + 0xd0a0,0xd0a1,0xd0a2,0xd0a3,0xd0a4,0xd0a5,0xd0a6,0xd0a7, + 0xd0a8,0xd0a9,0xd0aa,0xd0ab,0xd0ac,0xd0ad,0xd0ae,0xd0af, + 0xd0b0,0xd0b1,0xd0b2,0xd0b3,0xd0b4,0xd0b5,0xd0b6,0xd0b7, + 0xd0b8,0xd0b9,0xd0ba,0xd0bb,0xd0bc,0xd0bd,0xd0be,0xd0bf, + 0xd0c0,0xd0c1,0xd0c2,0xd0c3,0xd0c4,0xd0c5,0xd0c6,0xd0c7, + 0xd0c8,0xd0c9,0xd0ca,0xd0cb,0xd0cc,0xd0cd,0xd0ce,0xd0cf, + 0xd0d0,0xd0d1,0xd0d2,0xd0d3,0xd0d4,0xd0d5,0xd0d6,0xd0d7, + 0xd0d8,0xd0d9,0xd0da,0xd0db,0xd0dc,0xd0dd,0xd0de,0xd0df, + 0xd0e0,0xd0e1,0xd0e2,0xd0e3,0xd0e4,0xd0e5,0xd0e6,0xd0e7, + 0xd0e8,0xd0e9,0xd0ea,0xd0eb,0xd0ec,0xd0ed,0xd0ee,0xd0ef, + 0xd0f0,0xd0f1,0xd0f2,0xd0f3,0xd0f4,0xd0f5,0xd0f6,0xd0f7, + 0xd0f8,0xd0f9,0xd0fa,0xd0fb,0xd0fc,0xd0fd,0xd0fe,0xd0ff, + 0xd100,0xd101,0xd102,0xd103,0xd104,0xd105,0xd106,0xd107, + 0xd108,0xd109,0xd10a,0xd10b,0xd10c,0xd10d,0xd10e,0xd10f, + 0xd110,0xd111,0xd112,0xd113,0xd114,0xd115,0xd116,0xd117, + 0xd118,0xd119,0xd11a,0xd11b,0xd11c,0xd11d,0xd11e,0xd11f, + 0xd120,0xd121,0xd122,0xd123,0xd124,0xd125,0xd126,0xd127, + 0xd128,0xd129,0xd12a,0xd12b,0xd12c,0xd12d,0xd12e,0xd12f, + 0xd130,0xd131,0xd132,0xd133,0xd134,0xd135,0xd136,0xd137, + 0xd138,0xd139,0xd13a,0xd13b,0xd13c,0xd13d,0xd13e,0xd13f, + 0xd140,0xd141,0xd142,0xd143,0xd144,0xd145,0xd146,0xd147, + 0xd148,0xd149,0xd14a,0xd14b,0xd14c,0xd14d,0xd14e,0xd14f, + 0xd150,0xd151,0xd152,0xd153,0xd154,0xd155,0xd156,0xd157, + 0xd158,0xd159,0xd15a,0xd15b,0xd15c,0xd15d,0xd15e,0xd15f, + 0xd160,0xd161,0xd162,0xd163,0xd164,0xd165,0xd166,0xd167, + 0xd168,0xd169,0xd16a,0xd16b,0xd16c,0xd16d,0xd16e,0xd16f, + 0xd170,0xd171,0xd172,0xd173,0xd174,0xd175,0xd176,0xd177, + 0xd178,0xd179,0xd17a,0xd17b,0xd17c,0xd17d,0xd17e,0xd17f, + 0xd180,0xd181,0xd182,0xd183,0xd184,0xd185,0xd186,0xd187, + 0xd188,0xd189,0xd18a,0xd18b,0xd18c,0xd18d,0xd18e,0xd18f, + 0xd190,0xd191,0xd192,0xd193,0xd194,0xd195,0xd196,0xd197, + 0xd198,0xd199,0xd19a,0xd19b,0xd19c,0xd19d,0xd19e,0xd19f, + 0xd1a0,0xd1a1,0xd1a2,0xd1a3,0xd1a4,0xd1a5,0xd1a6,0xd1a7, + 0xd1a8,0xd1a9,0xd1aa,0xd1ab,0xd1ac,0xd1ad,0xd1ae,0xd1af, + 0xd1b0,0xd1b1,0xd1b2,0xd1b3,0xd1b4,0xd1b5,0xd1b6,0xd1b7, + 0xd1b8,0xd1b9,0xd1ba,0xd1bb,0xd1bc,0xd1bd,0xd1be,0xd1bf, + 0xd1c0,0xd1c1,0xd1c2,0xd1c3,0xd1c4,0xd1c5,0xd1c6,0xd1c7, + 0xd1c8,0xd1c9,0xd1ca,0xd1cb,0xd1cc,0xd1cd,0xd1ce,0xd1cf, + 0xd1d0,0xd1d1,0xd1d2,0xd1d3,0xd1d4,0xd1d5,0xd1d6,0xd1d7, + 0xd1d8,0xd1d9,0xd1da,0xd1db,0xd1dc,0xd1dd,0xd1de,0xd1df, + 0xd1e0,0xd1e1,0xd1e2,0xd1e3,0xd1e4,0xd1e5,0xd1e6,0xd1e7, + 0xd1e8,0xd1e9,0xd1ea,0xd1eb,0xd1ec,0xd1ed,0xd1ee,0xd1ef, + 0xd1f0,0xd1f1,0xd1f2,0xd1f3,0xd1f4,0xd1f5,0xd1f6,0xd1f7, + 0xd1f8,0xd1f9,0xd1fa,0xd1fb,0xd1fc,0xd1fd,0xd1fe,0xd1ff, + 0xd200,0xd201,0xd202,0xd203,0xd204,0xd205,0xd206,0xd207, + 0xd208,0xd209,0xd20a,0xd20b,0xd20c,0xd20d,0xd20e,0xd20f, + 0xd210,0xd211,0xd212,0xd213,0xd214,0xd215,0xd216,0xd217, + 0xd218,0xd219,0xd21a,0xd21b,0xd21c,0xd21d,0xd21e,0xd21f, + 0xd220,0xd221,0xd222,0xd223,0xd224,0xd225,0xd226,0xd227, + 0xd228,0xd229,0xd22a,0xd22b,0xd22c,0xd22d,0xd22e,0xd22f, + 0xd230,0xd231,0xd232,0xd233,0xd234,0xd235,0xd236,0xd237, + 0xd238,0xd239,0xd23a,0xd23b,0xd23c,0xd23d,0xd23e,0xd23f, + 0xd240,0xd241,0xd242,0xd243,0xd244,0xd245,0xd246,0xd247, + 0xd248,0xd249,0xd24a,0xd24b,0xd24c,0xd24d,0xd24e,0xd24f, + 0xd250,0xd251,0xd252,0xd253,0xd254,0xd255,0xd256,0xd257, + 0xd258,0xd259,0xd25a,0xd25b,0xd25c,0xd25d,0xd25e,0xd25f, + 0xd260,0xd261,0xd262,0xd263,0xd264,0xd265,0xd266,0xd267, + 0xd268,0xd269,0xd26a,0xd26b,0xd26c,0xd26d,0xd26e,0xd26f, + 0xd270,0xd271,0xd272,0xd273,0xd274,0xd275,0xd276,0xd277, + 0xd278,0xd279,0xd27a,0xd27b,0xd27c,0xd27d,0xd27e,0xd27f, + 0xd280,0xd281,0xd282,0xd283,0xd284,0xd285,0xd286,0xd287, + 0xd288,0xd289,0xd28a,0xd28b,0xd28c,0xd28d,0xd28e,0xd28f, + 0xd290,0xd291,0xd292,0xd293,0xd294,0xd295,0xd296,0xd297, + 0xd298,0xd299,0xd29a,0xd29b,0xd29c,0xd29d,0xd29e,0xd29f, + 0xd2a0,0xd2a1,0xd2a2,0xd2a3,0xd2a4,0xd2a5,0xd2a6,0xd2a7, + 0xd2a8,0xd2a9,0xd2aa,0xd2ab,0xd2ac,0xd2ad,0xd2ae,0xd2af, + 0xd2b0,0xd2b1,0xd2b2,0xd2b3,0xd2b4,0xd2b5,0xd2b6,0xd2b7, + 0xd2b8,0xd2b9,0xd2ba,0xd2bb,0xd2bc,0xd2bd,0xd2be,0xd2bf, + 0xd2c0,0xd2c1,0xd2c2,0xd2c3,0xd2c4,0xd2c5,0xd2c6,0xd2c7, + 0xd2c8,0xd2c9,0xd2ca,0xd2cb,0xd2cc,0xd2cd,0xd2ce,0xd2cf, + 0xd2d0,0xd2d1,0xd2d2,0xd2d3,0xd2d4,0xd2d5,0xd2d6,0xd2d7, + 0xd2d8,0xd2d9,0xd2da,0xd2db,0xd2dc,0xd2dd,0xd2de,0xd2df, + 0xd2e0,0xd2e1,0xd2e2,0xd2e3,0xd2e4,0xd2e5,0xd2e6,0xd2e7, + 0xd2e8,0xd2e9,0xd2ea,0xd2eb,0xd2ec,0xd2ed,0xd2ee,0xd2ef, + 0xd2f0,0xd2f1,0xd2f2,0xd2f3,0xd2f4,0xd2f5,0xd2f6,0xd2f7, + 0xd2f8,0xd2f9,0xd2fa,0xd2fb,0xd2fc,0xd2fd,0xd2fe,0xd2ff, + 0xd300,0xd301,0xd302,0xd303,0xd304,0xd305,0xd306,0xd307, + 0xd308,0xd309,0xd30a,0xd30b,0xd30c,0xd30d,0xd30e,0xd30f, + 0xd310,0xd311,0xd312,0xd313,0xd314,0xd315,0xd316,0xd317, + 0xd318,0xd319,0xd31a,0xd31b,0xd31c,0xd31d,0xd31e,0xd31f, + 0xd320,0xd321,0xd322,0xd323,0xd324,0xd325,0xd326,0xd327, + 0xd328,0xd329,0xd32a,0xd32b,0xd32c,0xd32d,0xd32e,0xd32f, + 0xd330,0xd331,0xd332,0xd333,0xd334,0xd335,0xd336,0xd337, + 0xd338,0xd339,0xd33a,0xd33b,0xd33c,0xd33d,0xd33e,0xd33f, + 0xd340,0xd341,0xd342,0xd343,0xd344,0xd345,0xd346,0xd347, + 0xd348,0xd349,0xd34a,0xd34b,0xd34c,0xd34d,0xd34e,0xd34f, + 0xd350,0xd351,0xd352,0xd353,0xd354,0xd355,0xd356,0xd357, + 0xd358,0xd359,0xd35a,0xd35b,0xd35c,0xd35d,0xd35e,0xd35f, + 0xd360,0xd361,0xd362,0xd363,0xd364,0xd365,0xd366,0xd367, + 0xd368,0xd369,0xd36a,0xd36b,0xd36c,0xd36d,0xd36e,0xd36f, + 0xd370,0xd371,0xd372,0xd373,0xd374,0xd375,0xd376,0xd377, + 0xd378,0xd379,0xd37a,0xd37b,0xd37c,0xd37d,0xd37e,0xd37f, + 0xd380,0xd381,0xd382,0xd383,0xd384,0xd385,0xd386,0xd387, + 0xd388,0xd389,0xd38a,0xd38b,0xd38c,0xd38d,0xd38e,0xd38f, + 0xd390,0xd391,0xd392,0xd393,0xd394,0xd395,0xd396,0xd397, + 0xd398,0xd399,0xd39a,0xd39b,0xd39c,0xd39d,0xd39e,0xd39f, + 0xd3a0,0xd3a1,0xd3a2,0xd3a3,0xd3a4,0xd3a5,0xd3a6,0xd3a7, + 0xd3a8,0xd3a9,0xd3aa,0xd3ab,0xd3ac,0xd3ad,0xd3ae,0xd3af, + 0xd3b0,0xd3b1,0xd3b2,0xd3b3,0xd3b4,0xd3b5,0xd3b6,0xd3b7, + 0xd3b8,0xd3b9,0xd3ba,0xd3bb,0xd3bc,0xd3bd,0xd3be,0xd3bf, + 0xd3c0,0xd3c1,0xd3c2,0xd3c3,0xd3c4,0xd3c5,0xd3c6,0xd3c7, + 0xd3c8,0xd3c9,0xd3ca,0xd3cb,0xd3cc,0xd3cd,0xd3ce,0xd3cf, + 0xd3d0,0xd3d1,0xd3d2,0xd3d3,0xd3d4,0xd3d5,0xd3d6,0xd3d7, + 0xd3d8,0xd3d9,0xd3da,0xd3db,0xd3dc,0xd3dd,0xd3de,0xd3df, + 0xd3e0,0xd3e1,0xd3e2,0xd3e3,0xd3e4,0xd3e5,0xd3e6,0xd3e7, + 0xd3e8,0xd3e9,0xd3ea,0xd3eb,0xd3ec,0xd3ed,0xd3ee,0xd3ef, + 0xd3f0,0xd3f1,0xd3f2,0xd3f3,0xd3f4,0xd3f5,0xd3f6,0xd3f7, + 0xd3f8,0xd3f9,0xd3fa,0xd3fb,0xd3fc,0xd3fd,0xd3fe,0xd3ff, + 0xd400,0xd401,0xd402,0xd403,0xd404,0xd405,0xd406,0xd407, + 0xd408,0xd409,0xd40a,0xd40b,0xd40c,0xd40d,0xd40e,0xd40f, + 0xd410,0xd411,0xd412,0xd413,0xd414,0xd415,0xd416,0xd417, + 0xd418,0xd419,0xd41a,0xd41b,0xd41c,0xd41d,0xd41e,0xd41f, + 0xd420,0xd421,0xd422,0xd423,0xd424,0xd425,0xd426,0xd427, + 0xd428,0xd429,0xd42a,0xd42b,0xd42c,0xd42d,0xd42e,0xd42f, + 0xd430,0xd431,0xd432,0xd433,0xd434,0xd435,0xd436,0xd437, + 0xd438,0xd439,0xd43a,0xd43b,0xd43c,0xd43d,0xd43e,0xd43f, + 0xd440,0xd441,0xd442,0xd443,0xd444,0xd445,0xd446,0xd447, + 0xd448,0xd449,0xd44a,0xd44b,0xd44c,0xd44d,0xd44e,0xd44f, + 0xd450,0xd451,0xd452,0xd453,0xd454,0xd455,0xd456,0xd457, + 0xd458,0xd459,0xd45a,0xd45b,0xd45c,0xd45d,0xd45e,0xd45f, + 0xd460,0xd461,0xd462,0xd463,0xd464,0xd465,0xd466,0xd467, + 0xd468,0xd469,0xd46a,0xd46b,0xd46c,0xd46d,0xd46e,0xd46f, + 0xd470,0xd471,0xd472,0xd473,0xd474,0xd475,0xd476,0xd477, + 0xd478,0xd479,0xd47a,0xd47b,0xd47c,0xd47d,0xd47e,0xd47f, + 0xd480,0xd481,0xd482,0xd483,0xd484,0xd485,0xd486,0xd487, + 0xd488,0xd489,0xd48a,0xd48b,0xd48c,0xd48d,0xd48e,0xd48f, + 0xd490,0xd491,0xd492,0xd493,0xd494,0xd495,0xd496,0xd497, + 0xd498,0xd499,0xd49a,0xd49b,0xd49c,0xd49d,0xd49e,0xd49f, + 0xd4a0,0xd4a1,0xd4a2,0xd4a3,0xd4a4,0xd4a5,0xd4a6,0xd4a7, + 0xd4a8,0xd4a9,0xd4aa,0xd4ab,0xd4ac,0xd4ad,0xd4ae,0xd4af, + 0xd4b0,0xd4b1,0xd4b2,0xd4b3,0xd4b4,0xd4b5,0xd4b6,0xd4b7, + 0xd4b8,0xd4b9,0xd4ba,0xd4bb,0xd4bc,0xd4bd,0xd4be,0xd4bf, + 0xd4c0,0xd4c1,0xd4c2,0xd4c3,0xd4c4,0xd4c5,0xd4c6,0xd4c7, + 0xd4c8,0xd4c9,0xd4ca,0xd4cb,0xd4cc,0xd4cd,0xd4ce,0xd4cf, + 0xd4d0,0xd4d1,0xd4d2,0xd4d3,0xd4d4,0xd4d5,0xd4d6,0xd4d7, + 0xd4d8,0xd4d9,0xd4da,0xd4db,0xd4dc,0xd4dd,0xd4de,0xd4df, + 0xd4e0,0xd4e1,0xd4e2,0xd4e3,0xd4e4,0xd4e5,0xd4e6,0xd4e7, + 0xd4e8,0xd4e9,0xd4ea,0xd4eb,0xd4ec,0xd4ed,0xd4ee,0xd4ef, + 0xd4f0,0xd4f1,0xd4f2,0xd4f3,0xd4f4,0xd4f5,0xd4f6,0xd4f7, + 0xd4f8,0xd4f9,0xd4fa,0xd4fb,0xd4fc,0xd4fd,0xd4fe,0xd4ff, + 0xd500,0xd501,0xd502,0xd503,0xd504,0xd505,0xd506,0xd507, + 0xd508,0xd509,0xd50a,0xd50b,0xd50c,0xd50d,0xd50e,0xd50f, + 0xd510,0xd511,0xd512,0xd513,0xd514,0xd515,0xd516,0xd517, + 0xd518,0xd519,0xd51a,0xd51b,0xd51c,0xd51d,0xd51e,0xd51f, + 0xd520,0xd521,0xd522,0xd523,0xd524,0xd525,0xd526,0xd527, + 0xd528,0xd529,0xd52a,0xd52b,0xd52c,0xd52d,0xd52e,0xd52f, + 0xd530,0xd531,0xd532,0xd533,0xd534,0xd535,0xd536,0xd537, + 0xd538,0xd539,0xd53a,0xd53b,0xd53c,0xd53d,0xd53e,0xd53f, + 0xd540,0xd541,0xd542,0xd543,0xd544,0xd545,0xd546,0xd547, + 0xd548,0xd549,0xd54a,0xd54b,0xd54c,0xd54d,0xd54e,0xd54f, + 0xd550,0xd551,0xd552,0xd553,0xd554,0xd555,0xd556,0xd557, + 0xd558,0xd559,0xd55a,0xd55b,0xd55c,0xd55d,0xd55e,0xd55f, + 0xd560,0xd561,0xd562,0xd563,0xd564,0xd565,0xd566,0xd567, + 0xd568,0xd569,0xd56a,0xd56b,0xd56c,0xd56d,0xd56e,0xd56f, + 0xd570,0xd571,0xd572,0xd573,0xd574,0xd575,0xd576,0xd577, + 0xd578,0xd579,0xd57a,0xd57b,0xd57c,0xd57d,0xd57e,0xd57f, + 0xd580,0xd581,0xd582,0xd583,0xd584,0xd585,0xd586,0xd587, + 0xd588,0xd589,0xd58a,0xd58b,0xd58c,0xd58d,0xd58e,0xd58f, + 0xd590,0xd591,0xd592,0xd593,0xd594,0xd595,0xd596,0xd597, + 0xd598,0xd599,0xd59a,0xd59b,0xd59c,0xd59d,0xd59e,0xd59f, + 0xd5a0,0xd5a1,0xd5a2,0xd5a3,0xd5a4,0xd5a5,0xd5a6,0xd5a7, + 0xd5a8,0xd5a9,0xd5aa,0xd5ab,0xd5ac,0xd5ad,0xd5ae,0xd5af, + 0xd5b0,0xd5b1,0xd5b2,0xd5b3,0xd5b4,0xd5b5,0xd5b6,0xd5b7, + 0xd5b8,0xd5b9,0xd5ba,0xd5bb,0xd5bc,0xd5bd,0xd5be,0xd5bf, + 0xd5c0,0xd5c1,0xd5c2,0xd5c3,0xd5c4,0xd5c5,0xd5c6,0xd5c7, + 0xd5c8,0xd5c9,0xd5ca,0xd5cb,0xd5cc,0xd5cd,0xd5ce,0xd5cf, + 0xd5d0,0xd5d1,0xd5d2,0xd5d3,0xd5d4,0xd5d5,0xd5d6,0xd5d7, + 0xd5d8,0xd5d9,0xd5da,0xd5db,0xd5dc,0xd5dd,0xd5de,0xd5df, + 0xd5e0,0xd5e1,0xd5e2,0xd5e3,0xd5e4,0xd5e5,0xd5e6,0xd5e7, + 0xd5e8,0xd5e9,0xd5ea,0xd5eb,0xd5ec,0xd5ed,0xd5ee,0xd5ef, + 0xd5f0,0xd5f1,0xd5f2,0xd5f3,0xd5f4,0xd5f5,0xd5f6,0xd5f7, + 0xd5f8,0xd5f9,0xd5fa,0xd5fb,0xd5fc,0xd5fd,0xd5fe,0xd5ff, + 0xd600,0xd601,0xd602,0xd603,0xd604,0xd605,0xd606,0xd607, + 0xd608,0xd609,0xd60a,0xd60b,0xd60c,0xd60d,0xd60e,0xd60f, + 0xd610,0xd611,0xd612,0xd613,0xd614,0xd615,0xd616,0xd617, + 0xd618,0xd619,0xd61a,0xd61b,0xd61c,0xd61d,0xd61e,0xd61f, + 0xd620,0xd621,0xd622,0xd623,0xd624,0xd625,0xd626,0xd627, + 0xd628,0xd629,0xd62a,0xd62b,0xd62c,0xd62d,0xd62e,0xd62f, + 0xd630,0xd631,0xd632,0xd633,0xd634,0xd635,0xd636,0xd637, + 0xd638,0xd639,0xd63a,0xd63b,0xd63c,0xd63d,0xd63e,0xd63f, + 0xd640,0xd641,0xd642,0xd643,0xd644,0xd645,0xd646,0xd647, + 0xd648,0xd649,0xd64a,0xd64b,0xd64c,0xd64d,0xd64e,0xd64f, + 0xd650,0xd651,0xd652,0xd653,0xd654,0xd655,0xd656,0xd657, + 0xd658,0xd659,0xd65a,0xd65b,0xd65c,0xd65d,0xd65e,0xd65f, + 0xd660,0xd661,0xd662,0xd663,0xd664,0xd665,0xd666,0xd667, + 0xd668,0xd669,0xd66a,0xd66b,0xd66c,0xd66d,0xd66e,0xd66f, + 0xd670,0xd671,0xd672,0xd673,0xd674,0xd675,0xd676,0xd677, + 0xd678,0xd679,0xd67a,0xd67b,0xd67c,0xd67d,0xd67e,0xd67f, + 0xd680,0xd681,0xd682,0xd683,0xd684,0xd685,0xd686,0xd687, + 0xd688,0xd689,0xd68a,0xd68b,0xd68c,0xd68d,0xd68e,0xd68f, + 0xd690,0xd691,0xd692,0xd693,0xd694,0xd695,0xd696,0xd697, + 0xd698,0xd699,0xd69a,0xd69b,0xd69c,0xd69d,0xd69e,0xd69f, + 0xd6a0,0xd6a1,0xd6a2,0xd6a3,0xd6a4,0xd6a5,0xd6a6,0xd6a7, + 0xd6a8,0xd6a9,0xd6aa,0xd6ab,0xd6ac,0xd6ad,0xd6ae,0xd6af, + 0xd6b0,0xd6b1,0xd6b2,0xd6b3,0xd6b4,0xd6b5,0xd6b6,0xd6b7, + 0xd6b8,0xd6b9,0xd6ba,0xd6bb,0xd6bc,0xd6bd,0xd6be,0xd6bf, + 0xd6c0,0xd6c1,0xd6c2,0xd6c3,0xd6c4,0xd6c5,0xd6c6,0xd6c7, + 0xd6c8,0xd6c9,0xd6ca,0xd6cb,0xd6cc,0xd6cd,0xd6ce,0xd6cf, + 0xd6d0,0xd6d1,0xd6d2,0xd6d3,0xd6d4,0xd6d5,0xd6d6,0xd6d7, + 0xd6d8,0xd6d9,0xd6da,0xd6db,0xd6dc,0xd6dd,0xd6de,0xd6df, + 0xd6e0,0xd6e1,0xd6e2,0xd6e3,0xd6e4,0xd6e5,0xd6e6,0xd6e7, + 0xd6e8,0xd6e9,0xd6ea,0xd6eb,0xd6ec,0xd6ed,0xd6ee,0xd6ef, + 0xd6f0,0xd6f1,0xd6f2,0xd6f3,0xd6f4,0xd6f5,0xd6f6,0xd6f7, + 0xd6f8,0xd6f9,0xd6fa,0xd6fb,0xd6fc,0xd6fd,0xd6fe,0xd6ff, + 0xd700,0xd701,0xd702,0xd703,0xd704,0xd705,0xd706,0xd707, + 0xd708,0xd709,0xd70a,0xd70b,0xd70c,0xd70d,0xd70e,0xd70f, + 0xd710,0xd711,0xd712,0xd713,0xd714,0xd715,0xd716,0xd717, + 0xd718,0xd719,0xd71a,0xd71b,0xd71c,0xd71d,0xd71e,0xd71f, + 0xd720,0xd721,0xd722,0xd723,0xd724,0xd725,0xd726,0xd727, + 0xd728,0xd729,0xd72a,0xd72b,0xd72c,0xd72d,0xd72e,0xd72f, + 0xd730,0xd731,0xd732,0xd733,0xd734,0xd735,0xd736,0xd737, + 0xd738,0xd739,0xd73a,0xd73b,0xd73c,0xd73d,0xd73e,0xd73f, + 0xd740,0xd741,0xd742,0xd743,0xd744,0xd745,0xd746,0xd747, + 0xd748,0xd749,0xd74a,0xd74b,0xd74c,0xd74d,0xd74e,0xd74f, + 0xd750,0xd751,0xd752,0xd753,0xd754,0xd755,0xd756,0xd757, + 0xd758,0xd759,0xd75a,0xd75b,0xd75c,0xd75d,0xd75e,0xd75f, + 0xd760,0xd761,0xd762,0xd763,0xd764,0xd765,0xd766,0xd767, + 0xd768,0xd769,0xd76a,0xd76b,0xd76c,0xd76d,0xd76e,0xd76f, + 0xd770,0xd771,0xd772,0xd773,0xd774,0xd775,0xd776,0xd777, + 0xd778,0xd779,0xd77a,0xd77b,0xd77c,0xd77d,0xd77e,0xd77f, + 0xd780,0xd781,0xd782,0xd783,0xd784,0xd785,0xd786,0xd787, + 0xd788,0xd789,0xd78a,0xd78b,0xd78c,0xd78d,0xd78e,0xd78f, + 0xd790,0xd791,0xd792,0xd793,0xd794,0xd795,0xd796,0xd797, + 0xd798,0xd799,0xd79a,0xd79b,0xd79c,0xd79d,0xd79e,0xd79f, + 0xd7a0,0xd7a1,0xd7a2,0xd7a3,0xd7a4,0xd7a5,0xd7a6,0xd7a7, + 0xd7a8,0xd7a9,0xd7aa,0xd7ab,0xd7ac,0xd7ad,0xd7ae,0xd7af, + 0xd7b0,0xd7b1,0xd7b2,0xd7b3,0xd7b4,0xd7b5,0xd7b6,0xd7b7, + 0xd7b8,0xd7b9,0xd7ba,0xd7bb,0xd7bc,0xd7bd,0xd7be,0xd7bf, + 0xd7c0,0xd7c1,0xd7c2,0xd7c3,0xd7c4,0xd7c5,0xd7c6,0xd7c7, + 0xd7c8,0xd7c9,0xd7ca,0xd7cb,0xd7cc,0xd7cd,0xd7ce,0xd7cf, + 0xd7d0,0xd7d1,0xd7d2,0xd7d3,0xd7d4,0xd7d5,0xd7d6,0xd7d7, + 0xd7d8,0xd7d9,0xd7da,0xd7db,0xd7dc,0xd7dd,0xd7de,0xd7df, + 0xd7e0,0xd7e1,0xd7e2,0xd7e3,0xd7e4,0xd7e5,0xd7e6,0xd7e7, + 0xd7e8,0xd7e9,0xd7ea,0xd7eb,0xd7ec,0xd7ed,0xd7ee,0xd7ef, + 0xd7f0,0xd7f1,0xd7f2,0xd7f3,0xd7f4,0xd7f5,0xd7f6,0xd7f7, + 0xd7f8,0xd7f9,0xd7fa,0xd7fb,0xd7fc,0xd7fd,0xd7fe,0xd7ff, + 0xd800,0xd801,0xd802,0xd803,0xd804,0xd805,0xd806,0xd807, + 0xd808,0xd809,0xd80a,0xd80b,0xd80c,0xd80d,0xd80e,0xd80f, + 0xd810,0xd811,0xd812,0xd813,0xd814,0xd815,0xd816,0xd817, + 0xd818,0xd819,0xd81a,0xd81b,0xd81c,0xd81d,0xd81e,0xd81f, + 0xd820,0xd821,0xd822,0xd823,0xd824,0xd825,0xd826,0xd827, + 0xd828,0xd829,0xd82a,0xd82b,0xd82c,0xd82d,0xd82e,0xd82f, + 0xd830,0xd831,0xd832,0xd833,0xd834,0xd835,0xd836,0xd837, + 0xd838,0xd839,0xd83a,0xd83b,0xd83c,0xd83d,0xd83e,0xd83f, + 0xd840,0xd841,0xd842,0xd843,0xd844,0xd845,0xd846,0xd847, + 0xd848,0xd849,0xd84a,0xd84b,0xd84c,0xd84d,0xd84e,0xd84f, + 0xd850,0xd851,0xd852,0xd853,0xd854,0xd855,0xd856,0xd857, + 0xd858,0xd859,0xd85a,0xd85b,0xd85c,0xd85d,0xd85e,0xd85f, + 0xd860,0xd861,0xd862,0xd863,0xd864,0xd865,0xd866,0xd867, + 0xd868,0xd869,0xd86a,0xd86b,0xd86c,0xd86d,0xd86e,0xd86f, + 0xd870,0xd871,0xd872,0xd873,0xd874,0xd875,0xd876,0xd877, + 0xd878,0xd879,0xd87a,0xd87b,0xd87c,0xd87d,0xd87e,0xd87f, + 0xd880,0xd881,0xd882,0xd883,0xd884,0xd885,0xd886,0xd887, + 0xd888,0xd889,0xd88a,0xd88b,0xd88c,0xd88d,0xd88e,0xd88f, + 0xd890,0xd891,0xd892,0xd893,0xd894,0xd895,0xd896,0xd897, + 0xd898,0xd899,0xd89a,0xd89b,0xd89c,0xd89d,0xd89e,0xd89f, + 0xd8a0,0xd8a1,0xd8a2,0xd8a3,0xd8a4,0xd8a5,0xd8a6,0xd8a7, + 0xd8a8,0xd8a9,0xd8aa,0xd8ab,0xd8ac,0xd8ad,0xd8ae,0xd8af, + 0xd8b0,0xd8b1,0xd8b2,0xd8b3,0xd8b4,0xd8b5,0xd8b6,0xd8b7, + 0xd8b8,0xd8b9,0xd8ba,0xd8bb,0xd8bc,0xd8bd,0xd8be,0xd8bf, + 0xd8c0,0xd8c1,0xd8c2,0xd8c3,0xd8c4,0xd8c5,0xd8c6,0xd8c7, + 0xd8c8,0xd8c9,0xd8ca,0xd8cb,0xd8cc,0xd8cd,0xd8ce,0xd8cf, + 0xd8d0,0xd8d1,0xd8d2,0xd8d3,0xd8d4,0xd8d5,0xd8d6,0xd8d7, + 0xd8d8,0xd8d9,0xd8da,0xd8db,0xd8dc,0xd8dd,0xd8de,0xd8df, + 0xd8e0,0xd8e1,0xd8e2,0xd8e3,0xd8e4,0xd8e5,0xd8e6,0xd8e7, + 0xd8e8,0xd8e9,0xd8ea,0xd8eb,0xd8ec,0xd8ed,0xd8ee,0xd8ef, + 0xd8f0,0xd8f1,0xd8f2,0xd8f3,0xd8f4,0xd8f5,0xd8f6,0xd8f7, + 0xd8f8,0xd8f9,0xd8fa,0xd8fb,0xd8fc,0xd8fd,0xd8fe,0xd8ff, + 0xd900,0xd901,0xd902,0xd903,0xd904,0xd905,0xd906,0xd907, + 0xd908,0xd909,0xd90a,0xd90b,0xd90c,0xd90d,0xd90e,0xd90f, + 0xd910,0xd911,0xd912,0xd913,0xd914,0xd915,0xd916,0xd917, + 0xd918,0xd919,0xd91a,0xd91b,0xd91c,0xd91d,0xd91e,0xd91f, + 0xd920,0xd921,0xd922,0xd923,0xd924,0xd925,0xd926,0xd927, + 0xd928,0xd929,0xd92a,0xd92b,0xd92c,0xd92d,0xd92e,0xd92f, + 0xd930,0xd931,0xd932,0xd933,0xd934,0xd935,0xd936,0xd937, + 0xd938,0xd939,0xd93a,0xd93b,0xd93c,0xd93d,0xd93e,0xd93f, + 0xd940,0xd941,0xd942,0xd943,0xd944,0xd945,0xd946,0xd947, + 0xd948,0xd949,0xd94a,0xd94b,0xd94c,0xd94d,0xd94e,0xd94f, + 0xd950,0xd951,0xd952,0xd953,0xd954,0xd955,0xd956,0xd957, + 0xd958,0xd959,0xd95a,0xd95b,0xd95c,0xd95d,0xd95e,0xd95f, + 0xd960,0xd961,0xd962,0xd963,0xd964,0xd965,0xd966,0xd967, + 0xd968,0xd969,0xd96a,0xd96b,0xd96c,0xd96d,0xd96e,0xd96f, + 0xd970,0xd971,0xd972,0xd973,0xd974,0xd975,0xd976,0xd977, + 0xd978,0xd979,0xd97a,0xd97b,0xd97c,0xd97d,0xd97e,0xd97f, + 0xd980,0xd981,0xd982,0xd983,0xd984,0xd985,0xd986,0xd987, + 0xd988,0xd989,0xd98a,0xd98b,0xd98c,0xd98d,0xd98e,0xd98f, + 0xd990,0xd991,0xd992,0xd993,0xd994,0xd995,0xd996,0xd997, + 0xd998,0xd999,0xd99a,0xd99b,0xd99c,0xd99d,0xd99e,0xd99f, + 0xd9a0,0xd9a1,0xd9a2,0xd9a3,0xd9a4,0xd9a5,0xd9a6,0xd9a7, + 0xd9a8,0xd9a9,0xd9aa,0xd9ab,0xd9ac,0xd9ad,0xd9ae,0xd9af, + 0xd9b0,0xd9b1,0xd9b2,0xd9b3,0xd9b4,0xd9b5,0xd9b6,0xd9b7, + 0xd9b8,0xd9b9,0xd9ba,0xd9bb,0xd9bc,0xd9bd,0xd9be,0xd9bf, + 0xd9c0,0xd9c1,0xd9c2,0xd9c3,0xd9c4,0xd9c5,0xd9c6,0xd9c7, + 0xd9c8,0xd9c9,0xd9ca,0xd9cb,0xd9cc,0xd9cd,0xd9ce,0xd9cf, + 0xd9d0,0xd9d1,0xd9d2,0xd9d3,0xd9d4,0xd9d5,0xd9d6,0xd9d7, + 0xd9d8,0xd9d9,0xd9da,0xd9db,0xd9dc,0xd9dd,0xd9de,0xd9df, + 0xd9e0,0xd9e1,0xd9e2,0xd9e3,0xd9e4,0xd9e5,0xd9e6,0xd9e7, + 0xd9e8,0xd9e9,0xd9ea,0xd9eb,0xd9ec,0xd9ed,0xd9ee,0xd9ef, + 0xd9f0,0xd9f1,0xd9f2,0xd9f3,0xd9f4,0xd9f5,0xd9f6,0xd9f7, + 0xd9f8,0xd9f9,0xd9fa,0xd9fb,0xd9fc,0xd9fd,0xd9fe,0xd9ff, + 0xda00,0xda01,0xda02,0xda03,0xda04,0xda05,0xda06,0xda07, + 0xda08,0xda09,0xda0a,0xda0b,0xda0c,0xda0d,0xda0e,0xda0f, + 0xda10,0xda11,0xda12,0xda13,0xda14,0xda15,0xda16,0xda17, + 0xda18,0xda19,0xda1a,0xda1b,0xda1c,0xda1d,0xda1e,0xda1f, + 0xda20,0xda21,0xda22,0xda23,0xda24,0xda25,0xda26,0xda27, + 0xda28,0xda29,0xda2a,0xda2b,0xda2c,0xda2d,0xda2e,0xda2f, + 0xda30,0xda31,0xda32,0xda33,0xda34,0xda35,0xda36,0xda37, + 0xda38,0xda39,0xda3a,0xda3b,0xda3c,0xda3d,0xda3e,0xda3f, + 0xda40,0xda41,0xda42,0xda43,0xda44,0xda45,0xda46,0xda47, + 0xda48,0xda49,0xda4a,0xda4b,0xda4c,0xda4d,0xda4e,0xda4f, + 0xda50,0xda51,0xda52,0xda53,0xda54,0xda55,0xda56,0xda57, + 0xda58,0xda59,0xda5a,0xda5b,0xda5c,0xda5d,0xda5e,0xda5f, + 0xda60,0xda61,0xda62,0xda63,0xda64,0xda65,0xda66,0xda67, + 0xda68,0xda69,0xda6a,0xda6b,0xda6c,0xda6d,0xda6e,0xda6f, + 0xda70,0xda71,0xda72,0xda73,0xda74,0xda75,0xda76,0xda77, + 0xda78,0xda79,0xda7a,0xda7b,0xda7c,0xda7d,0xda7e,0xda7f, + 0xda80,0xda81,0xda82,0xda83,0xda84,0xda85,0xda86,0xda87, + 0xda88,0xda89,0xda8a,0xda8b,0xda8c,0xda8d,0xda8e,0xda8f, + 0xda90,0xda91,0xda92,0xda93,0xda94,0xda95,0xda96,0xda97, + 0xda98,0xda99,0xda9a,0xda9b,0xda9c,0xda9d,0xda9e,0xda9f, + 0xdaa0,0xdaa1,0xdaa2,0xdaa3,0xdaa4,0xdaa5,0xdaa6,0xdaa7, + 0xdaa8,0xdaa9,0xdaaa,0xdaab,0xdaac,0xdaad,0xdaae,0xdaaf, + 0xdab0,0xdab1,0xdab2,0xdab3,0xdab4,0xdab5,0xdab6,0xdab7, + 0xdab8,0xdab9,0xdaba,0xdabb,0xdabc,0xdabd,0xdabe,0xdabf, + 0xdac0,0xdac1,0xdac2,0xdac3,0xdac4,0xdac5,0xdac6,0xdac7, + 0xdac8,0xdac9,0xdaca,0xdacb,0xdacc,0xdacd,0xdace,0xdacf, + 0xdad0,0xdad1,0xdad2,0xdad3,0xdad4,0xdad5,0xdad6,0xdad7, + 0xdad8,0xdad9,0xdada,0xdadb,0xdadc,0xdadd,0xdade,0xdadf, + 0xdae0,0xdae1,0xdae2,0xdae3,0xdae4,0xdae5,0xdae6,0xdae7, + 0xdae8,0xdae9,0xdaea,0xdaeb,0xdaec,0xdaed,0xdaee,0xdaef, + 0xdaf0,0xdaf1,0xdaf2,0xdaf3,0xdaf4,0xdaf5,0xdaf6,0xdaf7, + 0xdaf8,0xdaf9,0xdafa,0xdafb,0xdafc,0xdafd,0xdafe,0xdaff, + 0xdb00,0xdb01,0xdb02,0xdb03,0xdb04,0xdb05,0xdb06,0xdb07, + 0xdb08,0xdb09,0xdb0a,0xdb0b,0xdb0c,0xdb0d,0xdb0e,0xdb0f, + 0xdb10,0xdb11,0xdb12,0xdb13,0xdb14,0xdb15,0xdb16,0xdb17, + 0xdb18,0xdb19,0xdb1a,0xdb1b,0xdb1c,0xdb1d,0xdb1e,0xdb1f, + 0xdb20,0xdb21,0xdb22,0xdb23,0xdb24,0xdb25,0xdb26,0xdb27, + 0xdb28,0xdb29,0xdb2a,0xdb2b,0xdb2c,0xdb2d,0xdb2e,0xdb2f, + 0xdb30,0xdb31,0xdb32,0xdb33,0xdb34,0xdb35,0xdb36,0xdb37, + 0xdb38,0xdb39,0xdb3a,0xdb3b,0xdb3c,0xdb3d,0xdb3e,0xdb3f, + 0xdb40,0xdb41,0xdb42,0xdb43,0xdb44,0xdb45,0xdb46,0xdb47, + 0xdb48,0xdb49,0xdb4a,0xdb4b,0xdb4c,0xdb4d,0xdb4e,0xdb4f, + 0xdb50,0xdb51,0xdb52,0xdb53,0xdb54,0xdb55,0xdb56,0xdb57, + 0xdb58,0xdb59,0xdb5a,0xdb5b,0xdb5c,0xdb5d,0xdb5e,0xdb5f, + 0xdb60,0xdb61,0xdb62,0xdb63,0xdb64,0xdb65,0xdb66,0xdb67, + 0xdb68,0xdb69,0xdb6a,0xdb6b,0xdb6c,0xdb6d,0xdb6e,0xdb6f, + 0xdb70,0xdb71,0xdb72,0xdb73,0xdb74,0xdb75,0xdb76,0xdb77, + 0xdb78,0xdb79,0xdb7a,0xdb7b,0xdb7c,0xdb7d,0xdb7e,0xdb7f, + 0xdb80,0xdb81,0xdb82,0xdb83,0xdb84,0xdb85,0xdb86,0xdb87, + 0xdb88,0xdb89,0xdb8a,0xdb8b,0xdb8c,0xdb8d,0xdb8e,0xdb8f, + 0xdb90,0xdb91,0xdb92,0xdb93,0xdb94,0xdb95,0xdb96,0xdb97, + 0xdb98,0xdb99,0xdb9a,0xdb9b,0xdb9c,0xdb9d,0xdb9e,0xdb9f, + 0xdba0,0xdba1,0xdba2,0xdba3,0xdba4,0xdba5,0xdba6,0xdba7, + 0xdba8,0xdba9,0xdbaa,0xdbab,0xdbac,0xdbad,0xdbae,0xdbaf, + 0xdbb0,0xdbb1,0xdbb2,0xdbb3,0xdbb4,0xdbb5,0xdbb6,0xdbb7, + 0xdbb8,0xdbb9,0xdbba,0xdbbb,0xdbbc,0xdbbd,0xdbbe,0xdbbf, + 0xdbc0,0xdbc1,0xdbc2,0xdbc3,0xdbc4,0xdbc5,0xdbc6,0xdbc7, + 0xdbc8,0xdbc9,0xdbca,0xdbcb,0xdbcc,0xdbcd,0xdbce,0xdbcf, + 0xdbd0,0xdbd1,0xdbd2,0xdbd3,0xdbd4,0xdbd5,0xdbd6,0xdbd7, + 0xdbd8,0xdbd9,0xdbda,0xdbdb,0xdbdc,0xdbdd,0xdbde,0xdbdf, + 0xdbe0,0xdbe1,0xdbe2,0xdbe3,0xdbe4,0xdbe5,0xdbe6,0xdbe7, + 0xdbe8,0xdbe9,0xdbea,0xdbeb,0xdbec,0xdbed,0xdbee,0xdbef, + 0xdbf0,0xdbf1,0xdbf2,0xdbf3,0xdbf4,0xdbf5,0xdbf6,0xdbf7, + 0xdbf8,0xdbf9,0xdbfa,0xdbfb,0xdbfc,0xdbfd,0xdbfe,0xdbff, + 0xdc00,0xdc01,0xdc02,0xdc03,0xdc04,0xdc05,0xdc06,0xdc07, + 0xdc08,0xdc09,0xdc0a,0xdc0b,0xdc0c,0xdc0d,0xdc0e,0xdc0f, + 0xdc10,0xdc11,0xdc12,0xdc13,0xdc14,0xdc15,0xdc16,0xdc17, + 0xdc18,0xdc19,0xdc1a,0xdc1b,0xdc1c,0xdc1d,0xdc1e,0xdc1f, + 0xdc20,0xdc21,0xdc22,0xdc23,0xdc24,0xdc25,0xdc26,0xdc27, + 0xdc28,0xdc29,0xdc2a,0xdc2b,0xdc2c,0xdc2d,0xdc2e,0xdc2f, + 0xdc30,0xdc31,0xdc32,0xdc33,0xdc34,0xdc35,0xdc36,0xdc37, + 0xdc38,0xdc39,0xdc3a,0xdc3b,0xdc3c,0xdc3d,0xdc3e,0xdc3f, + 0xdc40,0xdc41,0xdc42,0xdc43,0xdc44,0xdc45,0xdc46,0xdc47, + 0xdc48,0xdc49,0xdc4a,0xdc4b,0xdc4c,0xdc4d,0xdc4e,0xdc4f, + 0xdc50,0xdc51,0xdc52,0xdc53,0xdc54,0xdc55,0xdc56,0xdc57, + 0xdc58,0xdc59,0xdc5a,0xdc5b,0xdc5c,0xdc5d,0xdc5e,0xdc5f, + 0xdc60,0xdc61,0xdc62,0xdc63,0xdc64,0xdc65,0xdc66,0xdc67, + 0xdc68,0xdc69,0xdc6a,0xdc6b,0xdc6c,0xdc6d,0xdc6e,0xdc6f, + 0xdc70,0xdc71,0xdc72,0xdc73,0xdc74,0xdc75,0xdc76,0xdc77, + 0xdc78,0xdc79,0xdc7a,0xdc7b,0xdc7c,0xdc7d,0xdc7e,0xdc7f, + 0xdc80,0xdc81,0xdc82,0xdc83,0xdc84,0xdc85,0xdc86,0xdc87, + 0xdc88,0xdc89,0xdc8a,0xdc8b,0xdc8c,0xdc8d,0xdc8e,0xdc8f, + 0xdc90,0xdc91,0xdc92,0xdc93,0xdc94,0xdc95,0xdc96,0xdc97, + 0xdc98,0xdc99,0xdc9a,0xdc9b,0xdc9c,0xdc9d,0xdc9e,0xdc9f, + 0xdca0,0xdca1,0xdca2,0xdca3,0xdca4,0xdca5,0xdca6,0xdca7, + 0xdca8,0xdca9,0xdcaa,0xdcab,0xdcac,0xdcad,0xdcae,0xdcaf, + 0xdcb0,0xdcb1,0xdcb2,0xdcb3,0xdcb4,0xdcb5,0xdcb6,0xdcb7, + 0xdcb8,0xdcb9,0xdcba,0xdcbb,0xdcbc,0xdcbd,0xdcbe,0xdcbf, + 0xdcc0,0xdcc1,0xdcc2,0xdcc3,0xdcc4,0xdcc5,0xdcc6,0xdcc7, + 0xdcc8,0xdcc9,0xdcca,0xdccb,0xdccc,0xdccd,0xdcce,0xdccf, + 0xdcd0,0xdcd1,0xdcd2,0xdcd3,0xdcd4,0xdcd5,0xdcd6,0xdcd7, + 0xdcd8,0xdcd9,0xdcda,0xdcdb,0xdcdc,0xdcdd,0xdcde,0xdcdf, + 0xdce0,0xdce1,0xdce2,0xdce3,0xdce4,0xdce5,0xdce6,0xdce7, + 0xdce8,0xdce9,0xdcea,0xdceb,0xdcec,0xdced,0xdcee,0xdcef, + 0xdcf0,0xdcf1,0xdcf2,0xdcf3,0xdcf4,0xdcf5,0xdcf6,0xdcf7, + 0xdcf8,0xdcf9,0xdcfa,0xdcfb,0xdcfc,0xdcfd,0xdcfe,0xdcff, + 0xdd00,0xdd01,0xdd02,0xdd03,0xdd04,0xdd05,0xdd06,0xdd07, + 0xdd08,0xdd09,0xdd0a,0xdd0b,0xdd0c,0xdd0d,0xdd0e,0xdd0f, + 0xdd10,0xdd11,0xdd12,0xdd13,0xdd14,0xdd15,0xdd16,0xdd17, + 0xdd18,0xdd19,0xdd1a,0xdd1b,0xdd1c,0xdd1d,0xdd1e,0xdd1f, + 0xdd20,0xdd21,0xdd22,0xdd23,0xdd24,0xdd25,0xdd26,0xdd27, + 0xdd28,0xdd29,0xdd2a,0xdd2b,0xdd2c,0xdd2d,0xdd2e,0xdd2f, + 0xdd30,0xdd31,0xdd32,0xdd33,0xdd34,0xdd35,0xdd36,0xdd37, + 0xdd38,0xdd39,0xdd3a,0xdd3b,0xdd3c,0xdd3d,0xdd3e,0xdd3f, + 0xdd40,0xdd41,0xdd42,0xdd43,0xdd44,0xdd45,0xdd46,0xdd47, + 0xdd48,0xdd49,0xdd4a,0xdd4b,0xdd4c,0xdd4d,0xdd4e,0xdd4f, + 0xdd50,0xdd51,0xdd52,0xdd53,0xdd54,0xdd55,0xdd56,0xdd57, + 0xdd58,0xdd59,0xdd5a,0xdd5b,0xdd5c,0xdd5d,0xdd5e,0xdd5f, + 0xdd60,0xdd61,0xdd62,0xdd63,0xdd64,0xdd65,0xdd66,0xdd67, + 0xdd68,0xdd69,0xdd6a,0xdd6b,0xdd6c,0xdd6d,0xdd6e,0xdd6f, + 0xdd70,0xdd71,0xdd72,0xdd73,0xdd74,0xdd75,0xdd76,0xdd77, + 0xdd78,0xdd79,0xdd7a,0xdd7b,0xdd7c,0xdd7d,0xdd7e,0xdd7f, + 0xdd80,0xdd81,0xdd82,0xdd83,0xdd84,0xdd85,0xdd86,0xdd87, + 0xdd88,0xdd89,0xdd8a,0xdd8b,0xdd8c,0xdd8d,0xdd8e,0xdd8f, + 0xdd90,0xdd91,0xdd92,0xdd93,0xdd94,0xdd95,0xdd96,0xdd97, + 0xdd98,0xdd99,0xdd9a,0xdd9b,0xdd9c,0xdd9d,0xdd9e,0xdd9f, + 0xdda0,0xdda1,0xdda2,0xdda3,0xdda4,0xdda5,0xdda6,0xdda7, + 0xdda8,0xdda9,0xddaa,0xddab,0xddac,0xddad,0xddae,0xddaf, + 0xddb0,0xddb1,0xddb2,0xddb3,0xddb4,0xddb5,0xddb6,0xddb7, + 0xddb8,0xddb9,0xddba,0xddbb,0xddbc,0xddbd,0xddbe,0xddbf, + 0xddc0,0xddc1,0xddc2,0xddc3,0xddc4,0xddc5,0xddc6,0xddc7, + 0xddc8,0xddc9,0xddca,0xddcb,0xddcc,0xddcd,0xddce,0xddcf, + 0xddd0,0xddd1,0xddd2,0xddd3,0xddd4,0xddd5,0xddd6,0xddd7, + 0xddd8,0xddd9,0xddda,0xdddb,0xdddc,0xdddd,0xddde,0xdddf, + 0xdde0,0xdde1,0xdde2,0xdde3,0xdde4,0xdde5,0xdde6,0xdde7, + 0xdde8,0xdde9,0xddea,0xddeb,0xddec,0xdded,0xddee,0xddef, + 0xddf0,0xddf1,0xddf2,0xddf3,0xddf4,0xddf5,0xddf6,0xddf7, + 0xddf8,0xddf9,0xddfa,0xddfb,0xddfc,0xddfd,0xddfe,0xddff, + 0xde00,0xde01,0xde02,0xde03,0xde04,0xde05,0xde06,0xde07, + 0xde08,0xde09,0xde0a,0xde0b,0xde0c,0xde0d,0xde0e,0xde0f, + 0xde10,0xde11,0xde12,0xde13,0xde14,0xde15,0xde16,0xde17, + 0xde18,0xde19,0xde1a,0xde1b,0xde1c,0xde1d,0xde1e,0xde1f, + 0xde20,0xde21,0xde22,0xde23,0xde24,0xde25,0xde26,0xde27, + 0xde28,0xde29,0xde2a,0xde2b,0xde2c,0xde2d,0xde2e,0xde2f, + 0xde30,0xde31,0xde32,0xde33,0xde34,0xde35,0xde36,0xde37, + 0xde38,0xde39,0xde3a,0xde3b,0xde3c,0xde3d,0xde3e,0xde3f, + 0xde40,0xde41,0xde42,0xde43,0xde44,0xde45,0xde46,0xde47, + 0xde48,0xde49,0xde4a,0xde4b,0xde4c,0xde4d,0xde4e,0xde4f, + 0xde50,0xde51,0xde52,0xde53,0xde54,0xde55,0xde56,0xde57, + 0xde58,0xde59,0xde5a,0xde5b,0xde5c,0xde5d,0xde5e,0xde5f, + 0xde60,0xde61,0xde62,0xde63,0xde64,0xde65,0xde66,0xde67, + 0xde68,0xde69,0xde6a,0xde6b,0xde6c,0xde6d,0xde6e,0xde6f, + 0xde70,0xde71,0xde72,0xde73,0xde74,0xde75,0xde76,0xde77, + 0xde78,0xde79,0xde7a,0xde7b,0xde7c,0xde7d,0xde7e,0xde7f, + 0xde80,0xde81,0xde82,0xde83,0xde84,0xde85,0xde86,0xde87, + 0xde88,0xde89,0xde8a,0xde8b,0xde8c,0xde8d,0xde8e,0xde8f, + 0xde90,0xde91,0xde92,0xde93,0xde94,0xde95,0xde96,0xde97, + 0xde98,0xde99,0xde9a,0xde9b,0xde9c,0xde9d,0xde9e,0xde9f, + 0xdea0,0xdea1,0xdea2,0xdea3,0xdea4,0xdea5,0xdea6,0xdea7, + 0xdea8,0xdea9,0xdeaa,0xdeab,0xdeac,0xdead,0xdeae,0xdeaf, + 0xdeb0,0xdeb1,0xdeb2,0xdeb3,0xdeb4,0xdeb5,0xdeb6,0xdeb7, + 0xdeb8,0xdeb9,0xdeba,0xdebb,0xdebc,0xdebd,0xdebe,0xdebf, + 0xdec0,0xdec1,0xdec2,0xdec3,0xdec4,0xdec5,0xdec6,0xdec7, + 0xdec8,0xdec9,0xdeca,0xdecb,0xdecc,0xdecd,0xdece,0xdecf, + 0xded0,0xded1,0xded2,0xded3,0xded4,0xded5,0xded6,0xded7, + 0xded8,0xded9,0xdeda,0xdedb,0xdedc,0xdedd,0xdede,0xdedf, + 0xdee0,0xdee1,0xdee2,0xdee3,0xdee4,0xdee5,0xdee6,0xdee7, + 0xdee8,0xdee9,0xdeea,0xdeeb,0xdeec,0xdeed,0xdeee,0xdeef, + 0xdef0,0xdef1,0xdef2,0xdef3,0xdef4,0xdef5,0xdef6,0xdef7, + 0xdef8,0xdef9,0xdefa,0xdefb,0xdefc,0xdefd,0xdefe,0xdeff, + 0xdf00,0xdf01,0xdf02,0xdf03,0xdf04,0xdf05,0xdf06,0xdf07, + 0xdf08,0xdf09,0xdf0a,0xdf0b,0xdf0c,0xdf0d,0xdf0e,0xdf0f, + 0xdf10,0xdf11,0xdf12,0xdf13,0xdf14,0xdf15,0xdf16,0xdf17, + 0xdf18,0xdf19,0xdf1a,0xdf1b,0xdf1c,0xdf1d,0xdf1e,0xdf1f, + 0xdf20,0xdf21,0xdf22,0xdf23,0xdf24,0xdf25,0xdf26,0xdf27, + 0xdf28,0xdf29,0xdf2a,0xdf2b,0xdf2c,0xdf2d,0xdf2e,0xdf2f, + 0xdf30,0xdf31,0xdf32,0xdf33,0xdf34,0xdf35,0xdf36,0xdf37, + 0xdf38,0xdf39,0xdf3a,0xdf3b,0xdf3c,0xdf3d,0xdf3e,0xdf3f, + 0xdf40,0xdf41,0xdf42,0xdf43,0xdf44,0xdf45,0xdf46,0xdf47, + 0xdf48,0xdf49,0xdf4a,0xdf4b,0xdf4c,0xdf4d,0xdf4e,0xdf4f, + 0xdf50,0xdf51,0xdf52,0xdf53,0xdf54,0xdf55,0xdf56,0xdf57, + 0xdf58,0xdf59,0xdf5a,0xdf5b,0xdf5c,0xdf5d,0xdf5e,0xdf5f, + 0xdf60,0xdf61,0xdf62,0xdf63,0xdf64,0xdf65,0xdf66,0xdf67, + 0xdf68,0xdf69,0xdf6a,0xdf6b,0xdf6c,0xdf6d,0xdf6e,0xdf6f, + 0xdf70,0xdf71,0xdf72,0xdf73,0xdf74,0xdf75,0xdf76,0xdf77, + 0xdf78,0xdf79,0xdf7a,0xdf7b,0xdf7c,0xdf7d,0xdf7e,0xdf7f, + 0xdf80,0xdf81,0xdf82,0xdf83,0xdf84,0xdf85,0xdf86,0xdf87, + 0xdf88,0xdf89,0xdf8a,0xdf8b,0xdf8c,0xdf8d,0xdf8e,0xdf8f, + 0xdf90,0xdf91,0xdf92,0xdf93,0xdf94,0xdf95,0xdf96,0xdf97, + 0xdf98,0xdf99,0xdf9a,0xdf9b,0xdf9c,0xdf9d,0xdf9e,0xdf9f, + 0xdfa0,0xdfa1,0xdfa2,0xdfa3,0xdfa4,0xdfa5,0xdfa6,0xdfa7, + 0xdfa8,0xdfa9,0xdfaa,0xdfab,0xdfac,0xdfad,0xdfae,0xdfaf, + 0xdfb0,0xdfb1,0xdfb2,0xdfb3,0xdfb4,0xdfb5,0xdfb6,0xdfb7, + 0xdfb8,0xdfb9,0xdfba,0xdfbb,0xdfbc,0xdfbd,0xdfbe,0xdfbf, + 0xdfc0,0xdfc1,0xdfc2,0xdfc3,0xdfc4,0xdfc5,0xdfc6,0xdfc7, + 0xdfc8,0xdfc9,0xdfca,0xdfcb,0xdfcc,0xdfcd,0xdfce,0xdfcf, + 0xdfd0,0xdfd1,0xdfd2,0xdfd3,0xdfd4,0xdfd5,0xdfd6,0xdfd7, + 0xdfd8,0xdfd9,0xdfda,0xdfdb,0xdfdc,0xdfdd,0xdfde,0xdfdf, + 0xdfe0,0xdfe1,0xdfe2,0xdfe3,0xdfe4,0xdfe5,0xdfe6,0xdfe7, + 0xdfe8,0xdfe9,0xdfea,0xdfeb,0xdfec,0xdfed,0xdfee,0xdfef, + 0xdff0,0xdff1,0xdff2,0xdff3,0xdff4,0xdff5,0xdff6,0xdff7, + 0xdff8,0xdff9,0xdffa,0xdffb,0xdffc,0xdffd,0xdffe,0xdfff, + 0xe000,0xe001,0xe002,0xe003,0xe004,0xe005,0xe006,0xe007, + 0xe008,0xe009,0xe00a,0xe00b,0xe00c,0xe00d,0xe00e,0xe00f, + 0xe010,0xe011,0xe012,0xe013,0xe014,0xe015,0xe016,0xe017, + 0xe018,0xe019,0xe01a,0xe01b,0xe01c,0xe01d,0xe01e,0xe01f, + 0xe020,0xe021,0xe022,0xe023,0xe024,0xe025,0xe026,0xe027, + 0xe028,0xe029,0xe02a,0xe02b,0xe02c,0xe02d,0xe02e,0xe02f, + 0xe030,0xe031,0xe032,0xe033,0xe034,0xe035,0xe036,0xe037, + 0xe038,0xe039,0xe03a,0xe03b,0xe03c,0xe03d,0xe03e,0xe03f, + 0xe040,0xe041,0xe042,0xe043,0xe044,0xe045,0xe046,0xe047, + 0xe048,0xe049,0xe04a,0xe04b,0xe04c,0xe04d,0xe04e,0xe04f, + 0xe050,0xe051,0xe052,0xe053,0xe054,0xe055,0xe056,0xe057, + 0xe058,0xe059,0xe05a,0xe05b,0xe05c,0xe05d,0xe05e,0xe05f, + 0xe060,0xe061,0xe062,0xe063,0xe064,0xe065,0xe066,0xe067, + 0xe068,0xe069,0xe06a,0xe06b,0xe06c,0xe06d,0xe06e,0xe06f, + 0xe070,0xe071,0xe072,0xe073,0xe074,0xe075,0xe076,0xe077, + 0xe078,0xe079,0xe07a,0xe07b,0xe07c,0xe07d,0xe07e,0xe07f, + 0xe080,0xe081,0xe082,0xe083,0xe084,0xe085,0xe086,0xe087, + 0xe088,0xe089,0xe08a,0xe08b,0xe08c,0xe08d,0xe08e,0xe08f, + 0xe090,0xe091,0xe092,0xe093,0xe094,0xe095,0xe096,0xe097, + 0xe098,0xe099,0xe09a,0xe09b,0xe09c,0xe09d,0xe09e,0xe09f, + 0xe0a0,0xe0a1,0xe0a2,0xe0a3,0xe0a4,0xe0a5,0xe0a6,0xe0a7, + 0xe0a8,0xe0a9,0xe0aa,0xe0ab,0xe0ac,0xe0ad,0xe0ae,0xe0af, + 0xe0b0,0xe0b1,0xe0b2,0xe0b3,0xe0b4,0xe0b5,0xe0b6,0xe0b7, + 0xe0b8,0xe0b9,0xe0ba,0xe0bb,0xe0bc,0xe0bd,0xe0be,0xe0bf, + 0xe0c0,0xe0c1,0xe0c2,0xe0c3,0xe0c4,0xe0c5,0xe0c6,0xe0c7, + 0xe0c8,0xe0c9,0xe0ca,0xe0cb,0xe0cc,0xe0cd,0xe0ce,0xe0cf, + 0xe0d0,0xe0d1,0xe0d2,0xe0d3,0xe0d4,0xe0d5,0xe0d6,0xe0d7, + 0xe0d8,0xe0d9,0xe0da,0xe0db,0xe0dc,0xe0dd,0xe0de,0xe0df, + 0xe0e0,0xe0e1,0xe0e2,0xe0e3,0xe0e4,0xe0e5,0xe0e6,0xe0e7, + 0xe0e8,0xe0e9,0xe0ea,0xe0eb,0xe0ec,0xe0ed,0xe0ee,0xe0ef, + 0xe0f0,0xe0f1,0xe0f2,0xe0f3,0xe0f4,0xe0f5,0xe0f6,0xe0f7, + 0xe0f8,0xe0f9,0xe0fa,0xe0fb,0xe0fc,0xe0fd,0xe0fe,0xe0ff, + 0xe100,0xe101,0xe102,0xe103,0xe104,0xe105,0xe106,0xe107, + 0xe108,0xe109,0xe10a,0xe10b,0xe10c,0xe10d,0xe10e,0xe10f, + 0xe110,0xe111,0xe112,0xe113,0xe114,0xe115,0xe116,0xe117, + 0xe118,0xe119,0xe11a,0xe11b,0xe11c,0xe11d,0xe11e,0xe11f, + 0xe120,0xe121,0xe122,0xe123,0xe124,0xe125,0xe126,0xe127, + 0xe128,0xe129,0xe12a,0xe12b,0xe12c,0xe12d,0xe12e,0xe12f, + 0xe130,0xe131,0xe132,0xe133,0xe134,0xe135,0xe136,0xe137, + 0xe138,0xe139,0xe13a,0xe13b,0xe13c,0xe13d,0xe13e,0xe13f, + 0xe140,0xe141,0xe142,0xe143,0xe144,0xe145,0xe146,0xe147, + 0xe148,0xe149,0xe14a,0xe14b,0xe14c,0xe14d,0xe14e,0xe14f, + 0xe150,0xe151,0xe152,0xe153,0xe154,0xe155,0xe156,0xe157, + 0xe158,0xe159,0xe15a,0xe15b,0xe15c,0xe15d,0xe15e,0xe15f, + 0xe160,0xe161,0xe162,0xe163,0xe164,0xe165,0xe166,0xe167, + 0xe168,0xe169,0xe16a,0xe16b,0xe16c,0xe16d,0xe16e,0xe16f, + 0xe170,0xe171,0xe172,0xe173,0xe174,0xe175,0xe176,0xe177, + 0xe178,0xe179,0xe17a,0xe17b,0xe17c,0xe17d,0xe17e,0xe17f, + 0xe180,0xe181,0xe182,0xe183,0xe184,0xe185,0xe186,0xe187, + 0xe188,0xe189,0xe18a,0xe18b,0xe18c,0xe18d,0xe18e,0xe18f, + 0xe190,0xe191,0xe192,0xe193,0xe194,0xe195,0xe196,0xe197, + 0xe198,0xe199,0xe19a,0xe19b,0xe19c,0xe19d,0xe19e,0xe19f, + 0xe1a0,0xe1a1,0xe1a2,0xe1a3,0xe1a4,0xe1a5,0xe1a6,0xe1a7, + 0xe1a8,0xe1a9,0xe1aa,0xe1ab,0xe1ac,0xe1ad,0xe1ae,0xe1af, + 0xe1b0,0xe1b1,0xe1b2,0xe1b3,0xe1b4,0xe1b5,0xe1b6,0xe1b7, + 0xe1b8,0xe1b9,0xe1ba,0xe1bb,0xe1bc,0xe1bd,0xe1be,0xe1bf, + 0xe1c0,0xe1c1,0xe1c2,0xe1c3,0xe1c4,0xe1c5,0xe1c6,0xe1c7, + 0xe1c8,0xe1c9,0xe1ca,0xe1cb,0xe1cc,0xe1cd,0xe1ce,0xe1cf, + 0xe1d0,0xe1d1,0xe1d2,0xe1d3,0xe1d4,0xe1d5,0xe1d6,0xe1d7, + 0xe1d8,0xe1d9,0xe1da,0xe1db,0xe1dc,0xe1dd,0xe1de,0xe1df, + 0xe1e0,0xe1e1,0xe1e2,0xe1e3,0xe1e4,0xe1e5,0xe1e6,0xe1e7, + 0xe1e8,0xe1e9,0xe1ea,0xe1eb,0xe1ec,0xe1ed,0xe1ee,0xe1ef, + 0xe1f0,0xe1f1,0xe1f2,0xe1f3,0xe1f4,0xe1f5,0xe1f6,0xe1f7, + 0xe1f8,0xe1f9,0xe1fa,0xe1fb,0xe1fc,0xe1fd,0xe1fe,0xe1ff, + 0xe200,0xe201,0xe202,0xe203,0xe204,0xe205,0xe206,0xe207, + 0xe208,0xe209,0xe20a,0xe20b,0xe20c,0xe20d,0xe20e,0xe20f, + 0xe210,0xe211,0xe212,0xe213,0xe214,0xe215,0xe216,0xe217, + 0xe218,0xe219,0xe21a,0xe21b,0xe21c,0xe21d,0xe21e,0xe21f, + 0xe220,0xe221,0xe222,0xe223,0xe224,0xe225,0xe226,0xe227, + 0xe228,0xe229,0xe22a,0xe22b,0xe22c,0xe22d,0xe22e,0xe22f, + 0xe230,0xe231,0xe232,0xe233,0xe234,0xe235,0xe236,0xe237, + 0xe238,0xe239,0xe23a,0xe23b,0xe23c,0xe23d,0xe23e,0xe23f, + 0xe240,0xe241,0xe242,0xe243,0xe244,0xe245,0xe246,0xe247, + 0xe248,0xe249,0xe24a,0xe24b,0xe24c,0xe24d,0xe24e,0xe24f, + 0xe250,0xe251,0xe252,0xe253,0xe254,0xe255,0xe256,0xe257, + 0xe258,0xe259,0xe25a,0xe25b,0xe25c,0xe25d,0xe25e,0xe25f, + 0xe260,0xe261,0xe262,0xe263,0xe264,0xe265,0xe266,0xe267, + 0xe268,0xe269,0xe26a,0xe26b,0xe26c,0xe26d,0xe26e,0xe26f, + 0xe270,0xe271,0xe272,0xe273,0xe274,0xe275,0xe276,0xe277, + 0xe278,0xe279,0xe27a,0xe27b,0xe27c,0xe27d,0xe27e,0xe27f, + 0xe280,0xe281,0xe282,0xe283,0xe284,0xe285,0xe286,0xe287, + 0xe288,0xe289,0xe28a,0xe28b,0xe28c,0xe28d,0xe28e,0xe28f, + 0xe290,0xe291,0xe292,0xe293,0xe294,0xe295,0xe296,0xe297, + 0xe298,0xe299,0xe29a,0xe29b,0xe29c,0xe29d,0xe29e,0xe29f, + 0xe2a0,0xe2a1,0xe2a2,0xe2a3,0xe2a4,0xe2a5,0xe2a6,0xe2a7, + 0xe2a8,0xe2a9,0xe2aa,0xe2ab,0xe2ac,0xe2ad,0xe2ae,0xe2af, + 0xe2b0,0xe2b1,0xe2b2,0xe2b3,0xe2b4,0xe2b5,0xe2b6,0xe2b7, + 0xe2b8,0xe2b9,0xe2ba,0xe2bb,0xe2bc,0xe2bd,0xe2be,0xe2bf, + 0xe2c0,0xe2c1,0xe2c2,0xe2c3,0xe2c4,0xe2c5,0xe2c6,0xe2c7, + 0xe2c8,0xe2c9,0xe2ca,0xe2cb,0xe2cc,0xe2cd,0xe2ce,0xe2cf, + 0xe2d0,0xe2d1,0xe2d2,0xe2d3,0xe2d4,0xe2d5,0xe2d6,0xe2d7, + 0xe2d8,0xe2d9,0xe2da,0xe2db,0xe2dc,0xe2dd,0xe2de,0xe2df, + 0xe2e0,0xe2e1,0xe2e2,0xe2e3,0xe2e4,0xe2e5,0xe2e6,0xe2e7, + 0xe2e8,0xe2e9,0xe2ea,0xe2eb,0xe2ec,0xe2ed,0xe2ee,0xe2ef, + 0xe2f0,0xe2f1,0xe2f2,0xe2f3,0xe2f4,0xe2f5,0xe2f6,0xe2f7, + 0xe2f8,0xe2f9,0xe2fa,0xe2fb,0xe2fc,0xe2fd,0xe2fe,0xe2ff, + 0xe300,0xe301,0xe302,0xe303,0xe304,0xe305,0xe306,0xe307, + 0xe308,0xe309,0xe30a,0xe30b,0xe30c,0xe30d,0xe30e,0xe30f, + 0xe310,0xe311,0xe312,0xe313,0xe314,0xe315,0xe316,0xe317, + 0xe318,0xe319,0xe31a,0xe31b,0xe31c,0xe31d,0xe31e,0xe31f, + 0xe320,0xe321,0xe322,0xe323,0xe324,0xe325,0xe326,0xe327, + 0xe328,0xe329,0xe32a,0xe32b,0xe32c,0xe32d,0xe32e,0xe32f, + 0xe330,0xe331,0xe332,0xe333,0xe334,0xe335,0xe336,0xe337, + 0xe338,0xe339,0xe33a,0xe33b,0xe33c,0xe33d,0xe33e,0xe33f, + 0xe340,0xe341,0xe342,0xe343,0xe344,0xe345,0xe346,0xe347, + 0xe348,0xe349,0xe34a,0xe34b,0xe34c,0xe34d,0xe34e,0xe34f, + 0xe350,0xe351,0xe352,0xe353,0xe354,0xe355,0xe356,0xe357, + 0xe358,0xe359,0xe35a,0xe35b,0xe35c,0xe35d,0xe35e,0xe35f, + 0xe360,0xe361,0xe362,0xe363,0xe364,0xe365,0xe366,0xe367, + 0xe368,0xe369,0xe36a,0xe36b,0xe36c,0xe36d,0xe36e,0xe36f, + 0xe370,0xe371,0xe372,0xe373,0xe374,0xe375,0xe376,0xe377, + 0xe378,0xe379,0xe37a,0xe37b,0xe37c,0xe37d,0xe37e,0xe37f, + 0xe380,0xe381,0xe382,0xe383,0xe384,0xe385,0xe386,0xe387, + 0xe388,0xe389,0xe38a,0xe38b,0xe38c,0xe38d,0xe38e,0xe38f, + 0xe390,0xe391,0xe392,0xe393,0xe394,0xe395,0xe396,0xe397, + 0xe398,0xe399,0xe39a,0xe39b,0xe39c,0xe39d,0xe39e,0xe39f, + 0xe3a0,0xe3a1,0xe3a2,0xe3a3,0xe3a4,0xe3a5,0xe3a6,0xe3a7, + 0xe3a8,0xe3a9,0xe3aa,0xe3ab,0xe3ac,0xe3ad,0xe3ae,0xe3af, + 0xe3b0,0xe3b1,0xe3b2,0xe3b3,0xe3b4,0xe3b5,0xe3b6,0xe3b7, + 0xe3b8,0xe3b9,0xe3ba,0xe3bb,0xe3bc,0xe3bd,0xe3be,0xe3bf, + 0xe3c0,0xe3c1,0xe3c2,0xe3c3,0xe3c4,0xe3c5,0xe3c6,0xe3c7, + 0xe3c8,0xe3c9,0xe3ca,0xe3cb,0xe3cc,0xe3cd,0xe3ce,0xe3cf, + 0xe3d0,0xe3d1,0xe3d2,0xe3d3,0xe3d4,0xe3d5,0xe3d6,0xe3d7, + 0xe3d8,0xe3d9,0xe3da,0xe3db,0xe3dc,0xe3dd,0xe3de,0xe3df, + 0xe3e0,0xe3e1,0xe3e2,0xe3e3,0xe3e4,0xe3e5,0xe3e6,0xe3e7, + 0xe3e8,0xe3e9,0xe3ea,0xe3eb,0xe3ec,0xe3ed,0xe3ee,0xe3ef, + 0xe3f0,0xe3f1,0xe3f2,0xe3f3,0xe3f4,0xe3f5,0xe3f6,0xe3f7, + 0xe3f8,0xe3f9,0xe3fa,0xe3fb,0xe3fc,0xe3fd,0xe3fe,0xe3ff, + 0xe400,0xe401,0xe402,0xe403,0xe404,0xe405,0xe406,0xe407, + 0xe408,0xe409,0xe40a,0xe40b,0xe40c,0xe40d,0xe40e,0xe40f, + 0xe410,0xe411,0xe412,0xe413,0xe414,0xe415,0xe416,0xe417, + 0xe418,0xe419,0xe41a,0xe41b,0xe41c,0xe41d,0xe41e,0xe41f, + 0xe420,0xe421,0xe422,0xe423,0xe424,0xe425,0xe426,0xe427, + 0xe428,0xe429,0xe42a,0xe42b,0xe42c,0xe42d,0xe42e,0xe42f, + 0xe430,0xe431,0xe432,0xe433,0xe434,0xe435,0xe436,0xe437, + 0xe438,0xe439,0xe43a,0xe43b,0xe43c,0xe43d,0xe43e,0xe43f, + 0xe440,0xe441,0xe442,0xe443,0xe444,0xe445,0xe446,0xe447, + 0xe448,0xe449,0xe44a,0xe44b,0xe44c,0xe44d,0xe44e,0xe44f, + 0xe450,0xe451,0xe452,0xe453,0xe454,0xe455,0xe456,0xe457, + 0xe458,0xe459,0xe45a,0xe45b,0xe45c,0xe45d,0xe45e,0xe45f, + 0xe460,0xe461,0xe462,0xe463,0xe464,0xe465,0xe466,0xe467, + 0xe468,0xe469,0xe46a,0xe46b,0xe46c,0xe46d,0xe46e,0xe46f, + 0xe470,0xe471,0xe472,0xe473,0xe474,0xe475,0xe476,0xe477, + 0xe478,0xe479,0xe47a,0xe47b,0xe47c,0xe47d,0xe47e,0xe47f, + 0xe480,0xe481,0xe482,0xe483,0xe484,0xe485,0xe486,0xe487, + 0xe488,0xe489,0xe48a,0xe48b,0xe48c,0xe48d,0xe48e,0xe48f, + 0xe490,0xe491,0xe492,0xe493,0xe494,0xe495,0xe496,0xe497, + 0xe498,0xe499,0xe49a,0xe49b,0xe49c,0xe49d,0xe49e,0xe49f, + 0xe4a0,0xe4a1,0xe4a2,0xe4a3,0xe4a4,0xe4a5,0xe4a6,0xe4a7, + 0xe4a8,0xe4a9,0xe4aa,0xe4ab,0xe4ac,0xe4ad,0xe4ae,0xe4af, + 0xe4b0,0xe4b1,0xe4b2,0xe4b3,0xe4b4,0xe4b5,0xe4b6,0xe4b7, + 0xe4b8,0xe4b9,0xe4ba,0xe4bb,0xe4bc,0xe4bd,0xe4be,0xe4bf, + 0xe4c0,0xe4c1,0xe4c2,0xe4c3,0xe4c4,0xe4c5,0xe4c6,0xe4c7, + 0xe4c8,0xe4c9,0xe4ca,0xe4cb,0xe4cc,0xe4cd,0xe4ce,0xe4cf, + 0xe4d0,0xe4d1,0xe4d2,0xe4d3,0xe4d4,0xe4d5,0xe4d6,0xe4d7, + 0xe4d8,0xe4d9,0xe4da,0xe4db,0xe4dc,0xe4dd,0xe4de,0xe4df, + 0xe4e0,0xe4e1,0xe4e2,0xe4e3,0xe4e4,0xe4e5,0xe4e6,0xe4e7, + 0xe4e8,0xe4e9,0xe4ea,0xe4eb,0xe4ec,0xe4ed,0xe4ee,0xe4ef, + 0xe4f0,0xe4f1,0xe4f2,0xe4f3,0xe4f4,0xe4f5,0xe4f6,0xe4f7, + 0xe4f8,0xe4f9,0xe4fa,0xe4fb,0xe4fc,0xe4fd,0xe4fe,0xe4ff, + 0xe500,0xe501,0xe502,0xe503,0xe504,0xe505,0xe506,0xe507, + 0xe508,0xe509,0xe50a,0xe50b,0xe50c,0xe50d,0xe50e,0xe50f, + 0xe510,0xe511,0xe512,0xe513,0xe514,0xe515,0xe516,0xe517, + 0xe518,0xe519,0xe51a,0xe51b,0xe51c,0xe51d,0xe51e,0xe51f, + 0xe520,0xe521,0xe522,0xe523,0xe524,0xe525,0xe526,0xe527, + 0xe528,0xe529,0xe52a,0xe52b,0xe52c,0xe52d,0xe52e,0xe52f, + 0xe530,0xe531,0xe532,0xe533,0xe534,0xe535,0xe536,0xe537, + 0xe538,0xe539,0xe53a,0xe53b,0xe53c,0xe53d,0xe53e,0xe53f, + 0xe540,0xe541,0xe542,0xe543,0xe544,0xe545,0xe546,0xe547, + 0xe548,0xe549,0xe54a,0xe54b,0xe54c,0xe54d,0xe54e,0xe54f, + 0xe550,0xe551,0xe552,0xe553,0xe554,0xe555,0xe556,0xe557, + 0xe558,0xe559,0xe55a,0xe55b,0xe55c,0xe55d,0xe55e,0xe55f, + 0xe560,0xe561,0xe562,0xe563,0xe564,0xe565,0xe566,0xe567, + 0xe568,0xe569,0xe56a,0xe56b,0xe56c,0xe56d,0xe56e,0xe56f, + 0xe570,0xe571,0xe572,0xe573,0xe574,0xe575,0xe576,0xe577, + 0xe578,0xe579,0xe57a,0xe57b,0xe57c,0xe57d,0xe57e,0xe57f, + 0xe580,0xe581,0xe582,0xe583,0xe584,0xe585,0xe586,0xe587, + 0xe588,0xe589,0xe58a,0xe58b,0xe58c,0xe58d,0xe58e,0xe58f, + 0xe590,0xe591,0xe592,0xe593,0xe594,0xe595,0xe596,0xe597, + 0xe598,0xe599,0xe59a,0xe59b,0xe59c,0xe59d,0xe59e,0xe59f, + 0xe5a0,0xe5a1,0xe5a2,0xe5a3,0xe5a4,0xe5a5,0xe5a6,0xe5a7, + 0xe5a8,0xe5a9,0xe5aa,0xe5ab,0xe5ac,0xe5ad,0xe5ae,0xe5af, + 0xe5b0,0xe5b1,0xe5b2,0xe5b3,0xe5b4,0xe5b5,0xe5b6,0xe5b7, + 0xe5b8,0xe5b9,0xe5ba,0xe5bb,0xe5bc,0xe5bd,0xe5be,0xe5bf, + 0xe5c0,0xe5c1,0xe5c2,0xe5c3,0xe5c4,0xe5c5,0xe5c6,0xe5c7, + 0xe5c8,0xe5c9,0xe5ca,0xe5cb,0xe5cc,0xe5cd,0xe5ce,0xe5cf, + 0xe5d0,0xe5d1,0xe5d2,0xe5d3,0xe5d4,0xe5d5,0xe5d6,0xe5d7, + 0xe5d8,0xe5d9,0xe5da,0xe5db,0xe5dc,0xe5dd,0xe5de,0xe5df, + 0xe5e0,0xe5e1,0xe5e2,0xe5e3,0xe5e4,0xe5e5,0xe5e6,0xe5e7, + 0xe5e8,0xe5e9,0xe5ea,0xe5eb,0xe5ec,0xe5ed,0xe5ee,0xe5ef, + 0xe5f0,0xe5f1,0xe5f2,0xe5f3,0xe5f4,0xe5f5,0xe5f6,0xe5f7, + 0xe5f8,0xe5f9,0xe5fa,0xe5fb,0xe5fc,0xe5fd,0xe5fe,0xe5ff, + 0xe600,0xe601,0xe602,0xe603,0xe604,0xe605,0xe606,0xe607, + 0xe608,0xe609,0xe60a,0xe60b,0xe60c,0xe60d,0xe60e,0xe60f, + 0xe610,0xe611,0xe612,0xe613,0xe614,0xe615,0xe616,0xe617, + 0xe618,0xe619,0xe61a,0xe61b,0xe61c,0xe61d,0xe61e,0xe61f, + 0xe620,0xe621,0xe622,0xe623,0xe624,0xe625,0xe626,0xe627, + 0xe628,0xe629,0xe62a,0xe62b,0xe62c,0xe62d,0xe62e,0xe62f, + 0xe630,0xe631,0xe632,0xe633,0xe634,0xe635,0xe636,0xe637, + 0xe638,0xe639,0xe63a,0xe63b,0xe63c,0xe63d,0xe63e,0xe63f, + 0xe640,0xe641,0xe642,0xe643,0xe644,0xe645,0xe646,0xe647, + 0xe648,0xe649,0xe64a,0xe64b,0xe64c,0xe64d,0xe64e,0xe64f, + 0xe650,0xe651,0xe652,0xe653,0xe654,0xe655,0xe656,0xe657, + 0xe658,0xe659,0xe65a,0xe65b,0xe65c,0xe65d,0xe65e,0xe65f, + 0xe660,0xe661,0xe662,0xe663,0xe664,0xe665,0xe666,0xe667, + 0xe668,0xe669,0xe66a,0xe66b,0xe66c,0xe66d,0xe66e,0xe66f, + 0xe670,0xe671,0xe672,0xe673,0xe674,0xe675,0xe676,0xe677, + 0xe678,0xe679,0xe67a,0xe67b,0xe67c,0xe67d,0xe67e,0xe67f, + 0xe680,0xe681,0xe682,0xe683,0xe684,0xe685,0xe686,0xe687, + 0xe688,0xe689,0xe68a,0xe68b,0xe68c,0xe68d,0xe68e,0xe68f, + 0xe690,0xe691,0xe692,0xe693,0xe694,0xe695,0xe696,0xe697, + 0xe698,0xe699,0xe69a,0xe69b,0xe69c,0xe69d,0xe69e,0xe69f, + 0xe6a0,0xe6a1,0xe6a2,0xe6a3,0xe6a4,0xe6a5,0xe6a6,0xe6a7, + 0xe6a8,0xe6a9,0xe6aa,0xe6ab,0xe6ac,0xe6ad,0xe6ae,0xe6af, + 0xe6b0,0xe6b1,0xe6b2,0xe6b3,0xe6b4,0xe6b5,0xe6b6,0xe6b7, + 0xe6b8,0xe6b9,0xe6ba,0xe6bb,0xe6bc,0xe6bd,0xe6be,0xe6bf, + 0xe6c0,0xe6c1,0xe6c2,0xe6c3,0xe6c4,0xe6c5,0xe6c6,0xe6c7, + 0xe6c8,0xe6c9,0xe6ca,0xe6cb,0xe6cc,0xe6cd,0xe6ce,0xe6cf, + 0xe6d0,0xe6d1,0xe6d2,0xe6d3,0xe6d4,0xe6d5,0xe6d6,0xe6d7, + 0xe6d8,0xe6d9,0xe6da,0xe6db,0xe6dc,0xe6dd,0xe6de,0xe6df, + 0xe6e0,0xe6e1,0xe6e2,0xe6e3,0xe6e4,0xe6e5,0xe6e6,0xe6e7, + 0xe6e8,0xe6e9,0xe6ea,0xe6eb,0xe6ec,0xe6ed,0xe6ee,0xe6ef, + 0xe6f0,0xe6f1,0xe6f2,0xe6f3,0xe6f4,0xe6f5,0xe6f6,0xe6f7, + 0xe6f8,0xe6f9,0xe6fa,0xe6fb,0xe6fc,0xe6fd,0xe6fe,0xe6ff, + 0xe700,0xe701,0xe702,0xe703,0xe704,0xe705,0xe706,0xe707, + 0xe708,0xe709,0xe70a,0xe70b,0xe70c,0xe70d,0xe70e,0xe70f, + 0xe710,0xe711,0xe712,0xe713,0xe714,0xe715,0xe716,0xe717, + 0xe718,0xe719,0xe71a,0xe71b,0xe71c,0xe71d,0xe71e,0xe71f, + 0xe720,0xe721,0xe722,0xe723,0xe724,0xe725,0xe726,0xe727, + 0xe728,0xe729,0xe72a,0xe72b,0xe72c,0xe72d,0xe72e,0xe72f, + 0xe730,0xe731,0xe732,0xe733,0xe734,0xe735,0xe736,0xe737, + 0xe738,0xe739,0xe73a,0xe73b,0xe73c,0xe73d,0xe73e,0xe73f, + 0xe740,0xe741,0xe742,0xe743,0xe744,0xe745,0xe746,0xe747, + 0xe748,0xe749,0xe74a,0xe74b,0xe74c,0xe74d,0xe74e,0xe74f, + 0xe750,0xe751,0xe752,0xe753,0xe754,0xe755,0xe756,0xe757, + 0xe758,0xe759,0xe75a,0xe75b,0xe75c,0xe75d,0xe75e,0xe75f, + 0xe760,0xe761,0xe762,0xe763,0xe764,0xe765,0xe766,0xe767, + 0xe768,0xe769,0xe76a,0xe76b,0xe76c,0xe76d,0xe76e,0xe76f, + 0xe770,0xe771,0xe772,0xe773,0xe774,0xe775,0xe776,0xe777, + 0xe778,0xe779,0xe77a,0xe77b,0xe77c,0xe77d,0xe77e,0xe77f, + 0xe780,0xe781,0xe782,0xe783,0xe784,0xe785,0xe786,0xe787, + 0xe788,0xe789,0xe78a,0xe78b,0xe78c,0xe78d,0xe78e,0xe78f, + 0xe790,0xe791,0xe792,0xe793,0xe794,0xe795,0xe796,0xe797, + 0xe798,0xe799,0xe79a,0xe79b,0xe79c,0xe79d,0xe79e,0xe79f, + 0xe7a0,0xe7a1,0xe7a2,0xe7a3,0xe7a4,0xe7a5,0xe7a6,0xe7a7, + 0xe7a8,0xe7a9,0xe7aa,0xe7ab,0xe7ac,0xe7ad,0xe7ae,0xe7af, + 0xe7b0,0xe7b1,0xe7b2,0xe7b3,0xe7b4,0xe7b5,0xe7b6,0xe7b7, + 0xe7b8,0xe7b9,0xe7ba,0xe7bb,0xe7bc,0xe7bd,0xe7be,0xe7bf, + 0xe7c0,0xe7c1,0xe7c2,0xe7c3,0xe7c4,0xe7c5,0xe7c6,0xe7c7, + 0xe7c8,0xe7c9,0xe7ca,0xe7cb,0xe7cc,0xe7cd,0xe7ce,0xe7cf, + 0xe7d0,0xe7d1,0xe7d2,0xe7d3,0xe7d4,0xe7d5,0xe7d6,0xe7d7, + 0xe7d8,0xe7d9,0xe7da,0xe7db,0xe7dc,0xe7dd,0xe7de,0xe7df, + 0xe7e0,0xe7e1,0xe7e2,0xe7e3,0xe7e4,0xe7e5,0xe7e6,0xe7e7, + 0xe7e8,0xe7e9,0xe7ea,0xe7eb,0xe7ec,0xe7ed,0xe7ee,0xe7ef, + 0xe7f0,0xe7f1,0xe7f2,0xe7f3,0xe7f4,0xe7f5,0xe7f6,0xe7f7, + 0xe7f8,0xe7f9,0xe7fa,0xe7fb,0xe7fc,0xe7fd,0xe7fe,0xe7ff, + 0xe800,0xe801,0xe802,0xe803,0xe804,0xe805,0xe806,0xe807, + 0xe808,0xe809,0xe80a,0xe80b,0xe80c,0xe80d,0xe80e,0xe80f, + 0xe810,0xe811,0xe812,0xe813,0xe814,0xe815,0xe816,0xe817, + 0xe818,0xe819,0xe81a,0xe81b,0xe81c,0xe81d,0xe81e,0xe81f, + 0xe820,0xe821,0xe822,0xe823,0xe824,0xe825,0xe826,0xe827, + 0xe828,0xe829,0xe82a,0xe82b,0xe82c,0xe82d,0xe82e,0xe82f, + 0xe830,0xe831,0xe832,0xe833,0xe834,0xe835,0xe836,0xe837, + 0xe838,0xe839,0xe83a,0xe83b,0xe83c,0xe83d,0xe83e,0xe83f, + 0xe840,0xe841,0xe842,0xe843,0xe844,0xe845,0xe846,0xe847, + 0xe848,0xe849,0xe84a,0xe84b,0xe84c,0xe84d,0xe84e,0xe84f, + 0xe850,0xe851,0xe852,0xe853,0xe854,0xe855,0xe856,0xe857, + 0xe858,0xe859,0xe85a,0xe85b,0xe85c,0xe85d,0xe85e,0xe85f, + 0xe860,0xe861,0xe862,0xe863,0xe864,0xe865,0xe866,0xe867, + 0xe868,0xe869,0xe86a,0xe86b,0xe86c,0xe86d,0xe86e,0xe86f, + 0xe870,0xe871,0xe872,0xe873,0xe874,0xe875,0xe876,0xe877, + 0xe878,0xe879,0xe87a,0xe87b,0xe87c,0xe87d,0xe87e,0xe87f, + 0xe880,0xe881,0xe882,0xe883,0xe884,0xe885,0xe886,0xe887, + 0xe888,0xe889,0xe88a,0xe88b,0xe88c,0xe88d,0xe88e,0xe88f, + 0xe890,0xe891,0xe892,0xe893,0xe894,0xe895,0xe896,0xe897, + 0xe898,0xe899,0xe89a,0xe89b,0xe89c,0xe89d,0xe89e,0xe89f, + 0xe8a0,0xe8a1,0xe8a2,0xe8a3,0xe8a4,0xe8a5,0xe8a6,0xe8a7, + 0xe8a8,0xe8a9,0xe8aa,0xe8ab,0xe8ac,0xe8ad,0xe8ae,0xe8af, + 0xe8b0,0xe8b1,0xe8b2,0xe8b3,0xe8b4,0xe8b5,0xe8b6,0xe8b7, + 0xe8b8,0xe8b9,0xe8ba,0xe8bb,0xe8bc,0xe8bd,0xe8be,0xe8bf, + 0xe8c0,0xe8c1,0xe8c2,0xe8c3,0xe8c4,0xe8c5,0xe8c6,0xe8c7, + 0xe8c8,0xe8c9,0xe8ca,0xe8cb,0xe8cc,0xe8cd,0xe8ce,0xe8cf, + 0xe8d0,0xe8d1,0xe8d2,0xe8d3,0xe8d4,0xe8d5,0xe8d6,0xe8d7, + 0xe8d8,0xe8d9,0xe8da,0xe8db,0xe8dc,0xe8dd,0xe8de,0xe8df, + 0xe8e0,0xe8e1,0xe8e2,0xe8e3,0xe8e4,0xe8e5,0xe8e6,0xe8e7, + 0xe8e8,0xe8e9,0xe8ea,0xe8eb,0xe8ec,0xe8ed,0xe8ee,0xe8ef, + 0xe8f0,0xe8f1,0xe8f2,0xe8f3,0xe8f4,0xe8f5,0xe8f6,0xe8f7, + 0xe8f8,0xe8f9,0xe8fa,0xe8fb,0xe8fc,0xe8fd,0xe8fe,0xe8ff, + 0xe900,0xe901,0xe902,0xe903,0xe904,0xe905,0xe906,0xe907, + 0xe908,0xe909,0xe90a,0xe90b,0xe90c,0xe90d,0xe90e,0xe90f, + 0xe910,0xe911,0xe912,0xe913,0xe914,0xe915,0xe916,0xe917, + 0xe918,0xe919,0xe91a,0xe91b,0xe91c,0xe91d,0xe91e,0xe91f, + 0xe920,0xe921,0xe922,0xe923,0xe924,0xe925,0xe926,0xe927, + 0xe928,0xe929,0xe92a,0xe92b,0xe92c,0xe92d,0xe92e,0xe92f, + 0xe930,0xe931,0xe932,0xe933,0xe934,0xe935,0xe936,0xe937, + 0xe938,0xe939,0xe93a,0xe93b,0xe93c,0xe93d,0xe93e,0xe93f, + 0xe940,0xe941,0xe942,0xe943,0xe944,0xe945,0xe946,0xe947, + 0xe948,0xe949,0xe94a,0xe94b,0xe94c,0xe94d,0xe94e,0xe94f, + 0xe950,0xe951,0xe952,0xe953,0xe954,0xe955,0xe956,0xe957, + 0xe958,0xe959,0xe95a,0xe95b,0xe95c,0xe95d,0xe95e,0xe95f, + 0xe960,0xe961,0xe962,0xe963,0xe964,0xe965,0xe966,0xe967, + 0xe968,0xe969,0xe96a,0xe96b,0xe96c,0xe96d,0xe96e,0xe96f, + 0xe970,0xe971,0xe972,0xe973,0xe974,0xe975,0xe976,0xe977, + 0xe978,0xe979,0xe97a,0xe97b,0xe97c,0xe97d,0xe97e,0xe97f, + 0xe980,0xe981,0xe982,0xe983,0xe984,0xe985,0xe986,0xe987, + 0xe988,0xe989,0xe98a,0xe98b,0xe98c,0xe98d,0xe98e,0xe98f, + 0xe990,0xe991,0xe992,0xe993,0xe994,0xe995,0xe996,0xe997, + 0xe998,0xe999,0xe99a,0xe99b,0xe99c,0xe99d,0xe99e,0xe99f, + 0xe9a0,0xe9a1,0xe9a2,0xe9a3,0xe9a4,0xe9a5,0xe9a6,0xe9a7, + 0xe9a8,0xe9a9,0xe9aa,0xe9ab,0xe9ac,0xe9ad,0xe9ae,0xe9af, + 0xe9b0,0xe9b1,0xe9b2,0xe9b3,0xe9b4,0xe9b5,0xe9b6,0xe9b7, + 0xe9b8,0xe9b9,0xe9ba,0xe9bb,0xe9bc,0xe9bd,0xe9be,0xe9bf, + 0xe9c0,0xe9c1,0xe9c2,0xe9c3,0xe9c4,0xe9c5,0xe9c6,0xe9c7, + 0xe9c8,0xe9c9,0xe9ca,0xe9cb,0xe9cc,0xe9cd,0xe9ce,0xe9cf, + 0xe9d0,0xe9d1,0xe9d2,0xe9d3,0xe9d4,0xe9d5,0xe9d6,0xe9d7, + 0xe9d8,0xe9d9,0xe9da,0xe9db,0xe9dc,0xe9dd,0xe9de,0xe9df, + 0xe9e0,0xe9e1,0xe9e2,0xe9e3,0xe9e4,0xe9e5,0xe9e6,0xe9e7, + 0xe9e8,0xe9e9,0xe9ea,0xe9eb,0xe9ec,0xe9ed,0xe9ee,0xe9ef, + 0xe9f0,0xe9f1,0xe9f2,0xe9f3,0xe9f4,0xe9f5,0xe9f6,0xe9f7, + 0xe9f8,0xe9f9,0xe9fa,0xe9fb,0xe9fc,0xe9fd,0xe9fe,0xe9ff, + 0xea00,0xea01,0xea02,0xea03,0xea04,0xea05,0xea06,0xea07, + 0xea08,0xea09,0xea0a,0xea0b,0xea0c,0xea0d,0xea0e,0xea0f, + 0xea10,0xea11,0xea12,0xea13,0xea14,0xea15,0xea16,0xea17, + 0xea18,0xea19,0xea1a,0xea1b,0xea1c,0xea1d,0xea1e,0xea1f, + 0xea20,0xea21,0xea22,0xea23,0xea24,0xea25,0xea26,0xea27, + 0xea28,0xea29,0xea2a,0xea2b,0xea2c,0xea2d,0xea2e,0xea2f, + 0xea30,0xea31,0xea32,0xea33,0xea34,0xea35,0xea36,0xea37, + 0xea38,0xea39,0xea3a,0xea3b,0xea3c,0xea3d,0xea3e,0xea3f, + 0xea40,0xea41,0xea42,0xea43,0xea44,0xea45,0xea46,0xea47, + 0xea48,0xea49,0xea4a,0xea4b,0xea4c,0xea4d,0xea4e,0xea4f, + 0xea50,0xea51,0xea52,0xea53,0xea54,0xea55,0xea56,0xea57, + 0xea58,0xea59,0xea5a,0xea5b,0xea5c,0xea5d,0xea5e,0xea5f, + 0xea60,0xea61,0xea62,0xea63,0xea64,0xea65,0xea66,0xea67, + 0xea68,0xea69,0xea6a,0xea6b,0xea6c,0xea6d,0xea6e,0xea6f, + 0xea70,0xea71,0xea72,0xea73,0xea74,0xea75,0xea76,0xea77, + 0xea78,0xea79,0xea7a,0xea7b,0xea7c,0xea7d,0xea7e,0xea7f, + 0xea80,0xea81,0xea82,0xea83,0xea84,0xea85,0xea86,0xea87, + 0xea88,0xea89,0xea8a,0xea8b,0xea8c,0xea8d,0xea8e,0xea8f, + 0xea90,0xea91,0xea92,0xea93,0xea94,0xea95,0xea96,0xea97, + 0xea98,0xea99,0xea9a,0xea9b,0xea9c,0xea9d,0xea9e,0xea9f, + 0xeaa0,0xeaa1,0xeaa2,0xeaa3,0xeaa4,0xeaa5,0xeaa6,0xeaa7, + 0xeaa8,0xeaa9,0xeaaa,0xeaab,0xeaac,0xeaad,0xeaae,0xeaaf, + 0xeab0,0xeab1,0xeab2,0xeab3,0xeab4,0xeab5,0xeab6,0xeab7, + 0xeab8,0xeab9,0xeaba,0xeabb,0xeabc,0xeabd,0xeabe,0xeabf, + 0xeac0,0xeac1,0xeac2,0xeac3,0xeac4,0xeac5,0xeac6,0xeac7, + 0xeac8,0xeac9,0xeaca,0xeacb,0xeacc,0xeacd,0xeace,0xeacf, + 0xead0,0xead1,0xead2,0xead3,0xead4,0xead5,0xead6,0xead7, + 0xead8,0xead9,0xeada,0xeadb,0xeadc,0xeadd,0xeade,0xeadf, + 0xeae0,0xeae1,0xeae2,0xeae3,0xeae4,0xeae5,0xeae6,0xeae7, + 0xeae8,0xeae9,0xeaea,0xeaeb,0xeaec,0xeaed,0xeaee,0xeaef, + 0xeaf0,0xeaf1,0xeaf2,0xeaf3,0xeaf4,0xeaf5,0xeaf6,0xeaf7, + 0xeaf8,0xeaf9,0xeafa,0xeafb,0xeafc,0xeafd,0xeafe,0xeaff, + 0xeb00,0xeb01,0xeb02,0xeb03,0xeb04,0xeb05,0xeb06,0xeb07, + 0xeb08,0xeb09,0xeb0a,0xeb0b,0xeb0c,0xeb0d,0xeb0e,0xeb0f, + 0xeb10,0xeb11,0xeb12,0xeb13,0xeb14,0xeb15,0xeb16,0xeb17, + 0xeb18,0xeb19,0xeb1a,0xeb1b,0xeb1c,0xeb1d,0xeb1e,0xeb1f, + 0xeb20,0xeb21,0xeb22,0xeb23,0xeb24,0xeb25,0xeb26,0xeb27, + 0xeb28,0xeb29,0xeb2a,0xeb2b,0xeb2c,0xeb2d,0xeb2e,0xeb2f, + 0xeb30,0xeb31,0xeb32,0xeb33,0xeb34,0xeb35,0xeb36,0xeb37, + 0xeb38,0xeb39,0xeb3a,0xeb3b,0xeb3c,0xeb3d,0xeb3e,0xeb3f, + 0xeb40,0xeb41,0xeb42,0xeb43,0xeb44,0xeb45,0xeb46,0xeb47, + 0xeb48,0xeb49,0xeb4a,0xeb4b,0xeb4c,0xeb4d,0xeb4e,0xeb4f, + 0xeb50,0xeb51,0xeb52,0xeb53,0xeb54,0xeb55,0xeb56,0xeb57, + 0xeb58,0xeb59,0xeb5a,0xeb5b,0xeb5c,0xeb5d,0xeb5e,0xeb5f, + 0xeb60,0xeb61,0xeb62,0xeb63,0xeb64,0xeb65,0xeb66,0xeb67, + 0xeb68,0xeb69,0xeb6a,0xeb6b,0xeb6c,0xeb6d,0xeb6e,0xeb6f, + 0xeb70,0xeb71,0xeb72,0xeb73,0xeb74,0xeb75,0xeb76,0xeb77, + 0xeb78,0xeb79,0xeb7a,0xeb7b,0xeb7c,0xeb7d,0xeb7e,0xeb7f, + 0xeb80,0xeb81,0xeb82,0xeb83,0xeb84,0xeb85,0xeb86,0xeb87, + 0xeb88,0xeb89,0xeb8a,0xeb8b,0xeb8c,0xeb8d,0xeb8e,0xeb8f, + 0xeb90,0xeb91,0xeb92,0xeb93,0xeb94,0xeb95,0xeb96,0xeb97, + 0xeb98,0xeb99,0xeb9a,0xeb9b,0xeb9c,0xeb9d,0xeb9e,0xeb9f, + 0xeba0,0xeba1,0xeba2,0xeba3,0xeba4,0xeba5,0xeba6,0xeba7, + 0xeba8,0xeba9,0xebaa,0xebab,0xebac,0xebad,0xebae,0xebaf, + 0xebb0,0xebb1,0xebb2,0xebb3,0xebb4,0xebb5,0xebb6,0xebb7, + 0xebb8,0xebb9,0xebba,0xebbb,0xebbc,0xebbd,0xebbe,0xebbf, + 0xebc0,0xebc1,0xebc2,0xebc3,0xebc4,0xebc5,0xebc6,0xebc7, + 0xebc8,0xebc9,0xebca,0xebcb,0xebcc,0xebcd,0xebce,0xebcf, + 0xebd0,0xebd1,0xebd2,0xebd3,0xebd4,0xebd5,0xebd6,0xebd7, + 0xebd8,0xebd9,0xebda,0xebdb,0xebdc,0xebdd,0xebde,0xebdf, + 0xebe0,0xebe1,0xebe2,0xebe3,0xebe4,0xebe5,0xebe6,0xebe7, + 0xebe8,0xebe9,0xebea,0xebeb,0xebec,0xebed,0xebee,0xebef, + 0xebf0,0xebf1,0xebf2,0xebf3,0xebf4,0xebf5,0xebf6,0xebf7, + 0xebf8,0xebf9,0xebfa,0xebfb,0xebfc,0xebfd,0xebfe,0xebff, + 0xec00,0xec01,0xec02,0xec03,0xec04,0xec05,0xec06,0xec07, + 0xec08,0xec09,0xec0a,0xec0b,0xec0c,0xec0d,0xec0e,0xec0f, + 0xec10,0xec11,0xec12,0xec13,0xec14,0xec15,0xec16,0xec17, + 0xec18,0xec19,0xec1a,0xec1b,0xec1c,0xec1d,0xec1e,0xec1f, + 0xec20,0xec21,0xec22,0xec23,0xec24,0xec25,0xec26,0xec27, + 0xec28,0xec29,0xec2a,0xec2b,0xec2c,0xec2d,0xec2e,0xec2f, + 0xec30,0xec31,0xec32,0xec33,0xec34,0xec35,0xec36,0xec37, + 0xec38,0xec39,0xec3a,0xec3b,0xec3c,0xec3d,0xec3e,0xec3f, + 0xec40,0xec41,0xec42,0xec43,0xec44,0xec45,0xec46,0xec47, + 0xec48,0xec49,0xec4a,0xec4b,0xec4c,0xec4d,0xec4e,0xec4f, + 0xec50,0xec51,0xec52,0xec53,0xec54,0xec55,0xec56,0xec57, + 0xec58,0xec59,0xec5a,0xec5b,0xec5c,0xec5d,0xec5e,0xec5f, + 0xec60,0xec61,0xec62,0xec63,0xec64,0xec65,0xec66,0xec67, + 0xec68,0xec69,0xec6a,0xec6b,0xec6c,0xec6d,0xec6e,0xec6f, + 0xec70,0xec71,0xec72,0xec73,0xec74,0xec75,0xec76,0xec77, + 0xec78,0xec79,0xec7a,0xec7b,0xec7c,0xec7d,0xec7e,0xec7f, + 0xec80,0xec81,0xec82,0xec83,0xec84,0xec85,0xec86,0xec87, + 0xec88,0xec89,0xec8a,0xec8b,0xec8c,0xec8d,0xec8e,0xec8f, + 0xec90,0xec91,0xec92,0xec93,0xec94,0xec95,0xec96,0xec97, + 0xec98,0xec99,0xec9a,0xec9b,0xec9c,0xec9d,0xec9e,0xec9f, + 0xeca0,0xeca1,0xeca2,0xeca3,0xeca4,0xeca5,0xeca6,0xeca7, + 0xeca8,0xeca9,0xecaa,0xecab,0xecac,0xecad,0xecae,0xecaf, + 0xecb0,0xecb1,0xecb2,0xecb3,0xecb4,0xecb5,0xecb6,0xecb7, + 0xecb8,0xecb9,0xecba,0xecbb,0xecbc,0xecbd,0xecbe,0xecbf, + 0xecc0,0xecc1,0xecc2,0xecc3,0xecc4,0xecc5,0xecc6,0xecc7, + 0xecc8,0xecc9,0xecca,0xeccb,0xeccc,0xeccd,0xecce,0xeccf, + 0xecd0,0xecd1,0xecd2,0xecd3,0xecd4,0xecd5,0xecd6,0xecd7, + 0xecd8,0xecd9,0xecda,0xecdb,0xecdc,0xecdd,0xecde,0xecdf, + 0xece0,0xece1,0xece2,0xece3,0xece4,0xece5,0xece6,0xece7, + 0xece8,0xece9,0xecea,0xeceb,0xecec,0xeced,0xecee,0xecef, + 0xecf0,0xecf1,0xecf2,0xecf3,0xecf4,0xecf5,0xecf6,0xecf7, + 0xecf8,0xecf9,0xecfa,0xecfb,0xecfc,0xecfd,0xecfe,0xecff, + 0xed00,0xed01,0xed02,0xed03,0xed04,0xed05,0xed06,0xed07, + 0xed08,0xed09,0xed0a,0xed0b,0xed0c,0xed0d,0xed0e,0xed0f, + 0xed10,0xed11,0xed12,0xed13,0xed14,0xed15,0xed16,0xed17, + 0xed18,0xed19,0xed1a,0xed1b,0xed1c,0xed1d,0xed1e,0xed1f, + 0xed20,0xed21,0xed22,0xed23,0xed24,0xed25,0xed26,0xed27, + 0xed28,0xed29,0xed2a,0xed2b,0xed2c,0xed2d,0xed2e,0xed2f, + 0xed30,0xed31,0xed32,0xed33,0xed34,0xed35,0xed36,0xed37, + 0xed38,0xed39,0xed3a,0xed3b,0xed3c,0xed3d,0xed3e,0xed3f, + 0xed40,0xed41,0xed42,0xed43,0xed44,0xed45,0xed46,0xed47, + 0xed48,0xed49,0xed4a,0xed4b,0xed4c,0xed4d,0xed4e,0xed4f, + 0xed50,0xed51,0xed52,0xed53,0xed54,0xed55,0xed56,0xed57, + 0xed58,0xed59,0xed5a,0xed5b,0xed5c,0xed5d,0xed5e,0xed5f, + 0xed60,0xed61,0xed62,0xed63,0xed64,0xed65,0xed66,0xed67, + 0xed68,0xed69,0xed6a,0xed6b,0xed6c,0xed6d,0xed6e,0xed6f, + 0xed70,0xed71,0xed72,0xed73,0xed74,0xed75,0xed76,0xed77, + 0xed78,0xed79,0xed7a,0xed7b,0xed7c,0xed7d,0xed7e,0xed7f, + 0xed80,0xed81,0xed82,0xed83,0xed84,0xed85,0xed86,0xed87, + 0xed88,0xed89,0xed8a,0xed8b,0xed8c,0xed8d,0xed8e,0xed8f, + 0xed90,0xed91,0xed92,0xed93,0xed94,0xed95,0xed96,0xed97, + 0xed98,0xed99,0xed9a,0xed9b,0xed9c,0xed9d,0xed9e,0xed9f, + 0xeda0,0xeda1,0xeda2,0xeda3,0xeda4,0xeda5,0xeda6,0xeda7, + 0xeda8,0xeda9,0xedaa,0xedab,0xedac,0xedad,0xedae,0xedaf, + 0xedb0,0xedb1,0xedb2,0xedb3,0xedb4,0xedb5,0xedb6,0xedb7, + 0xedb8,0xedb9,0xedba,0xedbb,0xedbc,0xedbd,0xedbe,0xedbf, + 0xedc0,0xedc1,0xedc2,0xedc3,0xedc4,0xedc5,0xedc6,0xedc7, + 0xedc8,0xedc9,0xedca,0xedcb,0xedcc,0xedcd,0xedce,0xedcf, + 0xedd0,0xedd1,0xedd2,0xedd3,0xedd4,0xedd5,0xedd6,0xedd7, + 0xedd8,0xedd9,0xedda,0xeddb,0xeddc,0xeddd,0xedde,0xeddf, + 0xede0,0xede1,0xede2,0xede3,0xede4,0xede5,0xede6,0xede7, + 0xede8,0xede9,0xedea,0xedeb,0xedec,0xeded,0xedee,0xedef, + 0xedf0,0xedf1,0xedf2,0xedf3,0xedf4,0xedf5,0xedf6,0xedf7, + 0xedf8,0xedf9,0xedfa,0xedfb,0xedfc,0xedfd,0xedfe,0xedff, + 0xee00,0xee01,0xee02,0xee03,0xee04,0xee05,0xee06,0xee07, + 0xee08,0xee09,0xee0a,0xee0b,0xee0c,0xee0d,0xee0e,0xee0f, + 0xee10,0xee11,0xee12,0xee13,0xee14,0xee15,0xee16,0xee17, + 0xee18,0xee19,0xee1a,0xee1b,0xee1c,0xee1d,0xee1e,0xee1f, + 0xee20,0xee21,0xee22,0xee23,0xee24,0xee25,0xee26,0xee27, + 0xee28,0xee29,0xee2a,0xee2b,0xee2c,0xee2d,0xee2e,0xee2f, + 0xee30,0xee31,0xee32,0xee33,0xee34,0xee35,0xee36,0xee37, + 0xee38,0xee39,0xee3a,0xee3b,0xee3c,0xee3d,0xee3e,0xee3f, + 0xee40,0xee41,0xee42,0xee43,0xee44,0xee45,0xee46,0xee47, + 0xee48,0xee49,0xee4a,0xee4b,0xee4c,0xee4d,0xee4e,0xee4f, + 0xee50,0xee51,0xee52,0xee53,0xee54,0xee55,0xee56,0xee57, + 0xee58,0xee59,0xee5a,0xee5b,0xee5c,0xee5d,0xee5e,0xee5f, + 0xee60,0xee61,0xee62,0xee63,0xee64,0xee65,0xee66,0xee67, + 0xee68,0xee69,0xee6a,0xee6b,0xee6c,0xee6d,0xee6e,0xee6f, + 0xee70,0xee71,0xee72,0xee73,0xee74,0xee75,0xee76,0xee77, + 0xee78,0xee79,0xee7a,0xee7b,0xee7c,0xee7d,0xee7e,0xee7f, + 0xee80,0xee81,0xee82,0xee83,0xee84,0xee85,0xee86,0xee87, + 0xee88,0xee89,0xee8a,0xee8b,0xee8c,0xee8d,0xee8e,0xee8f, + 0xee90,0xee91,0xee92,0xee93,0xee94,0xee95,0xee96,0xee97, + 0xee98,0xee99,0xee9a,0xee9b,0xee9c,0xee9d,0xee9e,0xee9f, + 0xeea0,0xeea1,0xeea2,0xeea3,0xeea4,0xeea5,0xeea6,0xeea7, + 0xeea8,0xeea9,0xeeaa,0xeeab,0xeeac,0xeead,0xeeae,0xeeaf, + 0xeeb0,0xeeb1,0xeeb2,0xeeb3,0xeeb4,0xeeb5,0xeeb6,0xeeb7, + 0xeeb8,0xeeb9,0xeeba,0xeebb,0xeebc,0xeebd,0xeebe,0xeebf, + 0xeec0,0xeec1,0xeec2,0xeec3,0xeec4,0xeec5,0xeec6,0xeec7, + 0xeec8,0xeec9,0xeeca,0xeecb,0xeecc,0xeecd,0xeece,0xeecf, + 0xeed0,0xeed1,0xeed2,0xeed3,0xeed4,0xeed5,0xeed6,0xeed7, + 0xeed8,0xeed9,0xeeda,0xeedb,0xeedc,0xeedd,0xeede,0xeedf, + 0xeee0,0xeee1,0xeee2,0xeee3,0xeee4,0xeee5,0xeee6,0xeee7, + 0xeee8,0xeee9,0xeeea,0xeeeb,0xeeec,0xeeed,0xeeee,0xeeef, + 0xeef0,0xeef1,0xeef2,0xeef3,0xeef4,0xeef5,0xeef6,0xeef7, + 0xeef8,0xeef9,0xeefa,0xeefb,0xeefc,0xeefd,0xeefe,0xeeff, + 0xef00,0xef01,0xef02,0xef03,0xef04,0xef05,0xef06,0xef07, + 0xef08,0xef09,0xef0a,0xef0b,0xef0c,0xef0d,0xef0e,0xef0f, + 0xef10,0xef11,0xef12,0xef13,0xef14,0xef15,0xef16,0xef17, + 0xef18,0xef19,0xef1a,0xef1b,0xef1c,0xef1d,0xef1e,0xef1f, + 0xef20,0xef21,0xef22,0xef23,0xef24,0xef25,0xef26,0xef27, + 0xef28,0xef29,0xef2a,0xef2b,0xef2c,0xef2d,0xef2e,0xef2f, + 0xef30,0xef31,0xef32,0xef33,0xef34,0xef35,0xef36,0xef37, + 0xef38,0xef39,0xef3a,0xef3b,0xef3c,0xef3d,0xef3e,0xef3f, + 0xef40,0xef41,0xef42,0xef43,0xef44,0xef45,0xef46,0xef47, + 0xef48,0xef49,0xef4a,0xef4b,0xef4c,0xef4d,0xef4e,0xef4f, + 0xef50,0xef51,0xef52,0xef53,0xef54,0xef55,0xef56,0xef57, + 0xef58,0xef59,0xef5a,0xef5b,0xef5c,0xef5d,0xef5e,0xef5f, + 0xef60,0xef61,0xef62,0xef63,0xef64,0xef65,0xef66,0xef67, + 0xef68,0xef69,0xef6a,0xef6b,0xef6c,0xef6d,0xef6e,0xef6f, + 0xef70,0xef71,0xef72,0xef73,0xef74,0xef75,0xef76,0xef77, + 0xef78,0xef79,0xef7a,0xef7b,0xef7c,0xef7d,0xef7e,0xef7f, + 0xef80,0xef81,0xef82,0xef83,0xef84,0xef85,0xef86,0xef87, + 0xef88,0xef89,0xef8a,0xef8b,0xef8c,0xef8d,0xef8e,0xef8f, + 0xef90,0xef91,0xef92,0xef93,0xef94,0xef95,0xef96,0xef97, + 0xef98,0xef99,0xef9a,0xef9b,0xef9c,0xef9d,0xef9e,0xef9f, + 0xefa0,0xefa1,0xefa2,0xefa3,0xefa4,0xefa5,0xefa6,0xefa7, + 0xefa8,0xefa9,0xefaa,0xefab,0xefac,0xefad,0xefae,0xefaf, + 0xefb0,0xefb1,0xefb2,0xefb3,0xefb4,0xefb5,0xefb6,0xefb7, + 0xefb8,0xefb9,0xefba,0xefbb,0xefbc,0xefbd,0xefbe,0xefbf, + 0xefc0,0xefc1,0xefc2,0xefc3,0xefc4,0xefc5,0xefc6,0xefc7, + 0xefc8,0xefc9,0xefca,0xefcb,0xefcc,0xefcd,0xefce,0xefcf, + 0xefd0,0xefd1,0xefd2,0xefd3,0xefd4,0xefd5,0xefd6,0xefd7, + 0xefd8,0xefd9,0xefda,0xefdb,0xefdc,0xefdd,0xefde,0xefdf, + 0xefe0,0xefe1,0xefe2,0xefe3,0xefe4,0xefe5,0xefe6,0xefe7, + 0xefe8,0xefe9,0xefea,0xefeb,0xefec,0xefed,0xefee,0xefef, + 0xeff0,0xeff1,0xeff2,0xeff3,0xeff4,0xeff5,0xeff6,0xeff7, + 0xeff8,0xeff9,0xeffa,0xeffb,0xeffc,0xeffd,0xeffe,0xefff, + 0xf000,0xf001,0xf002,0xf003,0xf004,0xf005,0xf006,0xf007, + 0xf008,0xf009,0xf00a,0xf00b,0xf00c,0xf00d,0xf00e,0xf00f, + 0xf010,0xf011,0xf012,0xf013,0xf014,0xf015,0xf016,0xf017, + 0xf018,0xf019,0xf01a,0xf01b,0xf01c,0xf01d,0xf01e,0xf01f, + 0xf020,0xf021,0xf022,0xf023,0xf024,0xf025,0xf026,0xf027, + 0xf028,0xf029,0xf02a,0xf02b,0xf02c,0xf02d,0xf02e,0xf02f, + 0xf030,0xf031,0xf032,0xf033,0xf034,0xf035,0xf036,0xf037, + 0xf038,0xf039,0xf03a,0xf03b,0xf03c,0xf03d,0xf03e,0xf03f, + 0xf040,0xf041,0xf042,0xf043,0xf044,0xf045,0xf046,0xf047, + 0xf048,0xf049,0xf04a,0xf04b,0xf04c,0xf04d,0xf04e,0xf04f, + 0xf050,0xf051,0xf052,0xf053,0xf054,0xf055,0xf056,0xf057, + 0xf058,0xf059,0xf05a,0xf05b,0xf05c,0xf05d,0xf05e,0xf05f, + 0xf060,0xf061,0xf062,0xf063,0xf064,0xf065,0xf066,0xf067, + 0xf068,0xf069,0xf06a,0xf06b,0xf06c,0xf06d,0xf06e,0xf06f, + 0xf070,0xf071,0xf072,0xf073,0xf074,0xf075,0xf076,0xf077, + 0xf078,0xf079,0xf07a,0xf07b,0xf07c,0xf07d,0xf07e,0xf07f, + 0xf080,0xf081,0xf082,0xf083,0xf084,0xf085,0xf086,0xf087, + 0xf088,0xf089,0xf08a,0xf08b,0xf08c,0xf08d,0xf08e,0xf08f, + 0xf090,0xf091,0xf092,0xf093,0xf094,0xf095,0xf096,0xf097, + 0xf098,0xf099,0xf09a,0xf09b,0xf09c,0xf09d,0xf09e,0xf09f, + 0xf0a0,0xf0a1,0xf0a2,0xf0a3,0xf0a4,0xf0a5,0xf0a6,0xf0a7, + 0xf0a8,0xf0a9,0xf0aa,0xf0ab,0xf0ac,0xf0ad,0xf0ae,0xf0af, + 0xf0b0,0xf0b1,0xf0b2,0xf0b3,0xf0b4,0xf0b5,0xf0b6,0xf0b7, + 0xf0b8,0xf0b9,0xf0ba,0xf0bb,0xf0bc,0xf0bd,0xf0be,0xf0bf, + 0xf0c0,0xf0c1,0xf0c2,0xf0c3,0xf0c4,0xf0c5,0xf0c6,0xf0c7, + 0xf0c8,0xf0c9,0xf0ca,0xf0cb,0xf0cc,0xf0cd,0xf0ce,0xf0cf, + 0xf0d0,0xf0d1,0xf0d2,0xf0d3,0xf0d4,0xf0d5,0xf0d6,0xf0d7, + 0xf0d8,0xf0d9,0xf0da,0xf0db,0xf0dc,0xf0dd,0xf0de,0xf0df, + 0xf0e0,0xf0e1,0xf0e2,0xf0e3,0xf0e4,0xf0e5,0xf0e6,0xf0e7, + 0xf0e8,0xf0e9,0xf0ea,0xf0eb,0xf0ec,0xf0ed,0xf0ee,0xf0ef, + 0xf0f0,0xf0f1,0xf0f2,0xf0f3,0xf0f4,0xf0f5,0xf0f6,0xf0f7, + 0xf0f8,0xf0f9,0xf0fa,0xf0fb,0xf0fc,0xf0fd,0xf0fe,0xf0ff, + 0xf100,0xf101,0xf102,0xf103,0xf104,0xf105,0xf106,0xf107, + 0xf108,0xf109,0xf10a,0xf10b,0xf10c,0xf10d,0xf10e,0xf10f, + 0xf110,0xf111,0xf112,0xf113,0xf114,0xf115,0xf116,0xf117, + 0xf118,0xf119,0xf11a,0xf11b,0xf11c,0xf11d,0xf11e,0xf11f, + 0xf120,0xf121,0xf122,0xf123,0xf124,0xf125,0xf126,0xf127, + 0xf128,0xf129,0xf12a,0xf12b,0xf12c,0xf12d,0xf12e,0xf12f, + 0xf130,0xf131,0xf132,0xf133,0xf134,0xf135,0xf136,0xf137, + 0xf138,0xf139,0xf13a,0xf13b,0xf13c,0xf13d,0xf13e,0xf13f, + 0xf140,0xf141,0xf142,0xf143,0xf144,0xf145,0xf146,0xf147, + 0xf148,0xf149,0xf14a,0xf14b,0xf14c,0xf14d,0xf14e,0xf14f, + 0xf150,0xf151,0xf152,0xf153,0xf154,0xf155,0xf156,0xf157, + 0xf158,0xf159,0xf15a,0xf15b,0xf15c,0xf15d,0xf15e,0xf15f, + 0xf160,0xf161,0xf162,0xf163,0xf164,0xf165,0xf166,0xf167, + 0xf168,0xf169,0xf16a,0xf16b,0xf16c,0xf16d,0xf16e,0xf16f, + 0xf170,0xf171,0xf172,0xf173,0xf174,0xf175,0xf176,0xf177, + 0xf178,0xf179,0xf17a,0xf17b,0xf17c,0xf17d,0xf17e,0xf17f, + 0xf180,0xf181,0xf182,0xf183,0xf184,0xf185,0xf186,0xf187, + 0xf188,0xf189,0xf18a,0xf18b,0xf18c,0xf18d,0xf18e,0xf18f, + 0xf190,0xf191,0xf192,0xf193,0xf194,0xf195,0xf196,0xf197, + 0xf198,0xf199,0xf19a,0xf19b,0xf19c,0xf19d,0xf19e,0xf19f, + 0xf1a0,0xf1a1,0xf1a2,0xf1a3,0xf1a4,0xf1a5,0xf1a6,0xf1a7, + 0xf1a8,0xf1a9,0xf1aa,0xf1ab,0xf1ac,0xf1ad,0xf1ae,0xf1af, + 0xf1b0,0xf1b1,0xf1b2,0xf1b3,0xf1b4,0xf1b5,0xf1b6,0xf1b7, + 0xf1b8,0xf1b9,0xf1ba,0xf1bb,0xf1bc,0xf1bd,0xf1be,0xf1bf, + 0xf1c0,0xf1c1,0xf1c2,0xf1c3,0xf1c4,0xf1c5,0xf1c6,0xf1c7, + 0xf1c8,0xf1c9,0xf1ca,0xf1cb,0xf1cc,0xf1cd,0xf1ce,0xf1cf, + 0xf1d0,0xf1d1,0xf1d2,0xf1d3,0xf1d4,0xf1d5,0xf1d6,0xf1d7, + 0xf1d8,0xf1d9,0xf1da,0xf1db,0xf1dc,0xf1dd,0xf1de,0xf1df, + 0xf1e0,0xf1e1,0xf1e2,0xf1e3,0xf1e4,0xf1e5,0xf1e6,0xf1e7, + 0xf1e8,0xf1e9,0xf1ea,0xf1eb,0xf1ec,0xf1ed,0xf1ee,0xf1ef, + 0xf1f0,0xf1f1,0xf1f2,0xf1f3,0xf1f4,0xf1f5,0xf1f6,0xf1f7, + 0xf1f8,0xf1f9,0xf1fa,0xf1fb,0xf1fc,0xf1fd,0xf1fe,0xf1ff, + 0xf200,0xf201,0xf202,0xf203,0xf204,0xf205,0xf206,0xf207, + 0xf208,0xf209,0xf20a,0xf20b,0xf20c,0xf20d,0xf20e,0xf20f, + 0xf210,0xf211,0xf212,0xf213,0xf214,0xf215,0xf216,0xf217, + 0xf218,0xf219,0xf21a,0xf21b,0xf21c,0xf21d,0xf21e,0xf21f, + 0xf220,0xf221,0xf222,0xf223,0xf224,0xf225,0xf226,0xf227, + 0xf228,0xf229,0xf22a,0xf22b,0xf22c,0xf22d,0xf22e,0xf22f, + 0xf230,0xf231,0xf232,0xf233,0xf234,0xf235,0xf236,0xf237, + 0xf238,0xf239,0xf23a,0xf23b,0xf23c,0xf23d,0xf23e,0xf23f, + 0xf240,0xf241,0xf242,0xf243,0xf244,0xf245,0xf246,0xf247, + 0xf248,0xf249,0xf24a,0xf24b,0xf24c,0xf24d,0xf24e,0xf24f, + 0xf250,0xf251,0xf252,0xf253,0xf254,0xf255,0xf256,0xf257, + 0xf258,0xf259,0xf25a,0xf25b,0xf25c,0xf25d,0xf25e,0xf25f, + 0xf260,0xf261,0xf262,0xf263,0xf264,0xf265,0xf266,0xf267, + 0xf268,0xf269,0xf26a,0xf26b,0xf26c,0xf26d,0xf26e,0xf26f, + 0xf270,0xf271,0xf272,0xf273,0xf274,0xf275,0xf276,0xf277, + 0xf278,0xf279,0xf27a,0xf27b,0xf27c,0xf27d,0xf27e,0xf27f, + 0xf280,0xf281,0xf282,0xf283,0xf284,0xf285,0xf286,0xf287, + 0xf288,0xf289,0xf28a,0xf28b,0xf28c,0xf28d,0xf28e,0xf28f, + 0xf290,0xf291,0xf292,0xf293,0xf294,0xf295,0xf296,0xf297, + 0xf298,0xf299,0xf29a,0xf29b,0xf29c,0xf29d,0xf29e,0xf29f, + 0xf2a0,0xf2a1,0xf2a2,0xf2a3,0xf2a4,0xf2a5,0xf2a6,0xf2a7, + 0xf2a8,0xf2a9,0xf2aa,0xf2ab,0xf2ac,0xf2ad,0xf2ae,0xf2af, + 0xf2b0,0xf2b1,0xf2b2,0xf2b3,0xf2b4,0xf2b5,0xf2b6,0xf2b7, + 0xf2b8,0xf2b9,0xf2ba,0xf2bb,0xf2bc,0xf2bd,0xf2be,0xf2bf, + 0xf2c0,0xf2c1,0xf2c2,0xf2c3,0xf2c4,0xf2c5,0xf2c6,0xf2c7, + 0xf2c8,0xf2c9,0xf2ca,0xf2cb,0xf2cc,0xf2cd,0xf2ce,0xf2cf, + 0xf2d0,0xf2d1,0xf2d2,0xf2d3,0xf2d4,0xf2d5,0xf2d6,0xf2d7, + 0xf2d8,0xf2d9,0xf2da,0xf2db,0xf2dc,0xf2dd,0xf2de,0xf2df, + 0xf2e0,0xf2e1,0xf2e2,0xf2e3,0xf2e4,0xf2e5,0xf2e6,0xf2e7, + 0xf2e8,0xf2e9,0xf2ea,0xf2eb,0xf2ec,0xf2ed,0xf2ee,0xf2ef, + 0xf2f0,0xf2f1,0xf2f2,0xf2f3,0xf2f4,0xf2f5,0xf2f6,0xf2f7, + 0xf2f8,0xf2f9,0xf2fa,0xf2fb,0xf2fc,0xf2fd,0xf2fe,0xf2ff, + 0xf300,0xf301,0xf302,0xf303,0xf304,0xf305,0xf306,0xf307, + 0xf308,0xf309,0xf30a,0xf30b,0xf30c,0xf30d,0xf30e,0xf30f, + 0xf310,0xf311,0xf312,0xf313,0xf314,0xf315,0xf316,0xf317, + 0xf318,0xf319,0xf31a,0xf31b,0xf31c,0xf31d,0xf31e,0xf31f, + 0xf320,0xf321,0xf322,0xf323,0xf324,0xf325,0xf326,0xf327, + 0xf328,0xf329,0xf32a,0xf32b,0xf32c,0xf32d,0xf32e,0xf32f, + 0xf330,0xf331,0xf332,0xf333,0xf334,0xf335,0xf336,0xf337, + 0xf338,0xf339,0xf33a,0xf33b,0xf33c,0xf33d,0xf33e,0xf33f, + 0xf340,0xf341,0xf342,0xf343,0xf344,0xf345,0xf346,0xf347, + 0xf348,0xf349,0xf34a,0xf34b,0xf34c,0xf34d,0xf34e,0xf34f, + 0xf350,0xf351,0xf352,0xf353,0xf354,0xf355,0xf356,0xf357, + 0xf358,0xf359,0xf35a,0xf35b,0xf35c,0xf35d,0xf35e,0xf35f, + 0xf360,0xf361,0xf362,0xf363,0xf364,0xf365,0xf366,0xf367, + 0xf368,0xf369,0xf36a,0xf36b,0xf36c,0xf36d,0xf36e,0xf36f, + 0xf370,0xf371,0xf372,0xf373,0xf374,0xf375,0xf376,0xf377, + 0xf378,0xf379,0xf37a,0xf37b,0xf37c,0xf37d,0xf37e,0xf37f, + 0xf380,0xf381,0xf382,0xf383,0xf384,0xf385,0xf386,0xf387, + 0xf388,0xf389,0xf38a,0xf38b,0xf38c,0xf38d,0xf38e,0xf38f, + 0xf390,0xf391,0xf392,0xf393,0xf394,0xf395,0xf396,0xf397, + 0xf398,0xf399,0xf39a,0xf39b,0xf39c,0xf39d,0xf39e,0xf39f, + 0xf3a0,0xf3a1,0xf3a2,0xf3a3,0xf3a4,0xf3a5,0xf3a6,0xf3a7, + 0xf3a8,0xf3a9,0xf3aa,0xf3ab,0xf3ac,0xf3ad,0xf3ae,0xf3af, + 0xf3b0,0xf3b1,0xf3b2,0xf3b3,0xf3b4,0xf3b5,0xf3b6,0xf3b7, + 0xf3b8,0xf3b9,0xf3ba,0xf3bb,0xf3bc,0xf3bd,0xf3be,0xf3bf, + 0xf3c0,0xf3c1,0xf3c2,0xf3c3,0xf3c4,0xf3c5,0xf3c6,0xf3c7, + 0xf3c8,0xf3c9,0xf3ca,0xf3cb,0xf3cc,0xf3cd,0xf3ce,0xf3cf, + 0xf3d0,0xf3d1,0xf3d2,0xf3d3,0xf3d4,0xf3d5,0xf3d6,0xf3d7, + 0xf3d8,0xf3d9,0xf3da,0xf3db,0xf3dc,0xf3dd,0xf3de,0xf3df, + 0xf3e0,0xf3e1,0xf3e2,0xf3e3,0xf3e4,0xf3e5,0xf3e6,0xf3e7, + 0xf3e8,0xf3e9,0xf3ea,0xf3eb,0xf3ec,0xf3ed,0xf3ee,0xf3ef, + 0xf3f0,0xf3f1,0xf3f2,0xf3f3,0xf3f4,0xf3f5,0xf3f6,0xf3f7, + 0xf3f8,0xf3f9,0xf3fa,0xf3fb,0xf3fc,0xf3fd,0xf3fe,0xf3ff, + 0xf400,0xf401,0xf402,0xf403,0xf404,0xf405,0xf406,0xf407, + 0xf408,0xf409,0xf40a,0xf40b,0xf40c,0xf40d,0xf40e,0xf40f, + 0xf410,0xf411,0xf412,0xf413,0xf414,0xf415,0xf416,0xf417, + 0xf418,0xf419,0xf41a,0xf41b,0xf41c,0xf41d,0xf41e,0xf41f, + 0xf420,0xf421,0xf422,0xf423,0xf424,0xf425,0xf426,0xf427, + 0xf428,0xf429,0xf42a,0xf42b,0xf42c,0xf42d,0xf42e,0xf42f, + 0xf430,0xf431,0xf432,0xf433,0xf434,0xf435,0xf436,0xf437, + 0xf438,0xf439,0xf43a,0xf43b,0xf43c,0xf43d,0xf43e,0xf43f, + 0xf440,0xf441,0xf442,0xf443,0xf444,0xf445,0xf446,0xf447, + 0xf448,0xf449,0xf44a,0xf44b,0xf44c,0xf44d,0xf44e,0xf44f, + 0xf450,0xf451,0xf452,0xf453,0xf454,0xf455,0xf456,0xf457, + 0xf458,0xf459,0xf45a,0xf45b,0xf45c,0xf45d,0xf45e,0xf45f, + 0xf460,0xf461,0xf462,0xf463,0xf464,0xf465,0xf466,0xf467, + 0xf468,0xf469,0xf46a,0xf46b,0xf46c,0xf46d,0xf46e,0xf46f, + 0xf470,0xf471,0xf472,0xf473,0xf474,0xf475,0xf476,0xf477, + 0xf478,0xf479,0xf47a,0xf47b,0xf47c,0xf47d,0xf47e,0xf47f, + 0xf480,0xf481,0xf482,0xf483,0xf484,0xf485,0xf486,0xf487, + 0xf488,0xf489,0xf48a,0xf48b,0xf48c,0xf48d,0xf48e,0xf48f, + 0xf490,0xf491,0xf492,0xf493,0xf494,0xf495,0xf496,0xf497, + 0xf498,0xf499,0xf49a,0xf49b,0xf49c,0xf49d,0xf49e,0xf49f, + 0xf4a0,0xf4a1,0xf4a2,0xf4a3,0xf4a4,0xf4a5,0xf4a6,0xf4a7, + 0xf4a8,0xf4a9,0xf4aa,0xf4ab,0xf4ac,0xf4ad,0xf4ae,0xf4af, + 0xf4b0,0xf4b1,0xf4b2,0xf4b3,0xf4b4,0xf4b5,0xf4b6,0xf4b7, + 0xf4b8,0xf4b9,0xf4ba,0xf4bb,0xf4bc,0xf4bd,0xf4be,0xf4bf, + 0xf4c0,0xf4c1,0xf4c2,0xf4c3,0xf4c4,0xf4c5,0xf4c6,0xf4c7, + 0xf4c8,0xf4c9,0xf4ca,0xf4cb,0xf4cc,0xf4cd,0xf4ce,0xf4cf, + 0xf4d0,0xf4d1,0xf4d2,0xf4d3,0xf4d4,0xf4d5,0xf4d6,0xf4d7, + 0xf4d8,0xf4d9,0xf4da,0xf4db,0xf4dc,0xf4dd,0xf4de,0xf4df, + 0xf4e0,0xf4e1,0xf4e2,0xf4e3,0xf4e4,0xf4e5,0xf4e6,0xf4e7, + 0xf4e8,0xf4e9,0xf4ea,0xf4eb,0xf4ec,0xf4ed,0xf4ee,0xf4ef, + 0xf4f0,0xf4f1,0xf4f2,0xf4f3,0xf4f4,0xf4f5,0xf4f6,0xf4f7, + 0xf4f8,0xf4f9,0xf4fa,0xf4fb,0xf4fc,0xf4fd,0xf4fe,0xf4ff, + 0xf500,0xf501,0xf502,0xf503,0xf504,0xf505,0xf506,0xf507, + 0xf508,0xf509,0xf50a,0xf50b,0xf50c,0xf50d,0xf50e,0xf50f, + 0xf510,0xf511,0xf512,0xf513,0xf514,0xf515,0xf516,0xf517, + 0xf518,0xf519,0xf51a,0xf51b,0xf51c,0xf51d,0xf51e,0xf51f, + 0xf520,0xf521,0xf522,0xf523,0xf524,0xf525,0xf526,0xf527, + 0xf528,0xf529,0xf52a,0xf52b,0xf52c,0xf52d,0xf52e,0xf52f, + 0xf530,0xf531,0xf532,0xf533,0xf534,0xf535,0xf536,0xf537, + 0xf538,0xf539,0xf53a,0xf53b,0xf53c,0xf53d,0xf53e,0xf53f, + 0xf540,0xf541,0xf542,0xf543,0xf544,0xf545,0xf546,0xf547, + 0xf548,0xf549,0xf54a,0xf54b,0xf54c,0xf54d,0xf54e,0xf54f, + 0xf550,0xf551,0xf552,0xf553,0xf554,0xf555,0xf556,0xf557, + 0xf558,0xf559,0xf55a,0xf55b,0xf55c,0xf55d,0xf55e,0xf55f, + 0xf560,0xf561,0xf562,0xf563,0xf564,0xf565,0xf566,0xf567, + 0xf568,0xf569,0xf56a,0xf56b,0xf56c,0xf56d,0xf56e,0xf56f, + 0xf570,0xf571,0xf572,0xf573,0xf574,0xf575,0xf576,0xf577, + 0xf578,0xf579,0xf57a,0xf57b,0xf57c,0xf57d,0xf57e,0xf57f, + 0xf580,0xf581,0xf582,0xf583,0xf584,0xf585,0xf586,0xf587, + 0xf588,0xf589,0xf58a,0xf58b,0xf58c,0xf58d,0xf58e,0xf58f, + 0xf590,0xf591,0xf592,0xf593,0xf594,0xf595,0xf596,0xf597, + 0xf598,0xf599,0xf59a,0xf59b,0xf59c,0xf59d,0xf59e,0xf59f, + 0xf5a0,0xf5a1,0xf5a2,0xf5a3,0xf5a4,0xf5a5,0xf5a6,0xf5a7, + 0xf5a8,0xf5a9,0xf5aa,0xf5ab,0xf5ac,0xf5ad,0xf5ae,0xf5af, + 0xf5b0,0xf5b1,0xf5b2,0xf5b3,0xf5b4,0xf5b5,0xf5b6,0xf5b7, + 0xf5b8,0xf5b9,0xf5ba,0xf5bb,0xf5bc,0xf5bd,0xf5be,0xf5bf, + 0xf5c0,0xf5c1,0xf5c2,0xf5c3,0xf5c4,0xf5c5,0xf5c6,0xf5c7, + 0xf5c8,0xf5c9,0xf5ca,0xf5cb,0xf5cc,0xf5cd,0xf5ce,0xf5cf, + 0xf5d0,0xf5d1,0xf5d2,0xf5d3,0xf5d4,0xf5d5,0xf5d6,0xf5d7, + 0xf5d8,0xf5d9,0xf5da,0xf5db,0xf5dc,0xf5dd,0xf5de,0xf5df, + 0xf5e0,0xf5e1,0xf5e2,0xf5e3,0xf5e4,0xf5e5,0xf5e6,0xf5e7, + 0xf5e8,0xf5e9,0xf5ea,0xf5eb,0xf5ec,0xf5ed,0xf5ee,0xf5ef, + 0xf5f0,0xf5f1,0xf5f2,0xf5f3,0xf5f4,0xf5f5,0xf5f6,0xf5f7, + 0xf5f8,0xf5f9,0xf5fa,0xf5fb,0xf5fc,0xf5fd,0xf5fe,0xf5ff, + 0xf600,0xf601,0xf602,0xf603,0xf604,0xf605,0xf606,0xf607, + 0xf608,0xf609,0xf60a,0xf60b,0xf60c,0xf60d,0xf60e,0xf60f, + 0xf610,0xf611,0xf612,0xf613,0xf614,0xf615,0xf616,0xf617, + 0xf618,0xf619,0xf61a,0xf61b,0xf61c,0xf61d,0xf61e,0xf61f, + 0xf620,0xf621,0xf622,0xf623,0xf624,0xf625,0xf626,0xf627, + 0xf628,0xf629,0xf62a,0xf62b,0xf62c,0xf62d,0xf62e,0xf62f, + 0xf630,0xf631,0xf632,0xf633,0xf634,0xf635,0xf636,0xf637, + 0xf638,0xf639,0xf63a,0xf63b,0xf63c,0xf63d,0xf63e,0xf63f, + 0xf640,0xf641,0xf642,0xf643,0xf644,0xf645,0xf646,0xf647, + 0xf648,0xf649,0xf64a,0xf64b,0xf64c,0xf64d,0xf64e,0xf64f, + 0xf650,0xf651,0xf652,0xf653,0xf654,0xf655,0xf656,0xf657, + 0xf658,0xf659,0xf65a,0xf65b,0xf65c,0xf65d,0xf65e,0xf65f, + 0xf660,0xf661,0xf662,0xf663,0xf664,0xf665,0xf666,0xf667, + 0xf668,0xf669,0xf66a,0xf66b,0xf66c,0xf66d,0xf66e,0xf66f, + 0xf670,0xf671,0xf672,0xf673,0xf674,0xf675,0xf676,0xf677, + 0xf678,0xf679,0xf67a,0xf67b,0xf67c,0xf67d,0xf67e,0xf67f, + 0xf680,0xf681,0xf682,0xf683,0xf684,0xf685,0xf686,0xf687, + 0xf688,0xf689,0xf68a,0xf68b,0xf68c,0xf68d,0xf68e,0xf68f, + 0xf690,0xf691,0xf692,0xf693,0xf694,0xf695,0xf696,0xf697, + 0xf698,0xf699,0xf69a,0xf69b,0xf69c,0xf69d,0xf69e,0xf69f, + 0xf6a0,0xf6a1,0xf6a2,0xf6a3,0xf6a4,0xf6a5,0xf6a6,0xf6a7, + 0xf6a8,0xf6a9,0xf6aa,0xf6ab,0xf6ac,0xf6ad,0xf6ae,0xf6af, + 0xf6b0,0xf6b1,0xf6b2,0xf6b3,0xf6b4,0xf6b5,0xf6b6,0xf6b7, + 0xf6b8,0xf6b9,0xf6ba,0xf6bb,0xf6bc,0xf6bd,0xf6be,0xf6bf, + 0xf6c0,0xf6c1,0xf6c2,0xf6c3,0xf6c4,0xf6c5,0xf6c6,0xf6c7, + 0xf6c8,0xf6c9,0xf6ca,0xf6cb,0xf6cc,0xf6cd,0xf6ce,0xf6cf, + 0xf6d0,0xf6d1,0xf6d2,0xf6d3,0xf6d4,0xf6d5,0xf6d6,0xf6d7, + 0xf6d8,0xf6d9,0xf6da,0xf6db,0xf6dc,0xf6dd,0xf6de,0xf6df, + 0xf6e0,0xf6e1,0xf6e2,0xf6e3,0xf6e4,0xf6e5,0xf6e6,0xf6e7, + 0xf6e8,0xf6e9,0xf6ea,0xf6eb,0xf6ec,0xf6ed,0xf6ee,0xf6ef, + 0xf6f0,0xf6f1,0xf6f2,0xf6f3,0xf6f4,0xf6f5,0xf6f6,0xf6f7, + 0xf6f8,0xf6f9,0xf6fa,0xf6fb,0xf6fc,0xf6fd,0xf6fe,0xf6ff, + 0xf700,0xf701,0xf702,0xf703,0xf704,0xf705,0xf706,0xf707, + 0xf708,0xf709,0xf70a,0xf70b,0xf70c,0xf70d,0xf70e,0xf70f, + 0xf710,0xf711,0xf712,0xf713,0xf714,0xf715,0xf716,0xf717, + 0xf718,0xf719,0xf71a,0xf71b,0xf71c,0xf71d,0xf71e,0xf71f, + 0xf720,0xf721,0xf722,0xf723,0xf724,0xf725,0xf726,0xf727, + 0xf728,0xf729,0xf72a,0xf72b,0xf72c,0xf72d,0xf72e,0xf72f, + 0xf730,0xf731,0xf732,0xf733,0xf734,0xf735,0xf736,0xf737, + 0xf738,0xf739,0xf73a,0xf73b,0xf73c,0xf73d,0xf73e,0xf73f, + 0xf740,0xf741,0xf742,0xf743,0xf744,0xf745,0xf746,0xf747, + 0xf748,0xf749,0xf74a,0xf74b,0xf74c,0xf74d,0xf74e,0xf74f, + 0xf750,0xf751,0xf752,0xf753,0xf754,0xf755,0xf756,0xf757, + 0xf758,0xf759,0xf75a,0xf75b,0xf75c,0xf75d,0xf75e,0xf75f, + 0xf760,0xf761,0xf762,0xf763,0xf764,0xf765,0xf766,0xf767, + 0xf768,0xf769,0xf76a,0xf76b,0xf76c,0xf76d,0xf76e,0xf76f, + 0xf770,0xf771,0xf772,0xf773,0xf774,0xf775,0xf776,0xf777, + 0xf778,0xf779,0xf77a,0xf77b,0xf77c,0xf77d,0xf77e,0xf77f, + 0xf780,0xf781,0xf782,0xf783,0xf784,0xf785,0xf786,0xf787, + 0xf788,0xf789,0xf78a,0xf78b,0xf78c,0xf78d,0xf78e,0xf78f, + 0xf790,0xf791,0xf792,0xf793,0xf794,0xf795,0xf796,0xf797, + 0xf798,0xf799,0xf79a,0xf79b,0xf79c,0xf79d,0xf79e,0xf79f, + 0xf7a0,0xf7a1,0xf7a2,0xf7a3,0xf7a4,0xf7a5,0xf7a6,0xf7a7, + 0xf7a8,0xf7a9,0xf7aa,0xf7ab,0xf7ac,0xf7ad,0xf7ae,0xf7af, + 0xf7b0,0xf7b1,0xf7b2,0xf7b3,0xf7b4,0xf7b5,0xf7b6,0xf7b7, + 0xf7b8,0xf7b9,0xf7ba,0xf7bb,0xf7bc,0xf7bd,0xf7be,0xf7bf, + 0xf7c0,0xf7c1,0xf7c2,0xf7c3,0xf7c4,0xf7c5,0xf7c6,0xf7c7, + 0xf7c8,0xf7c9,0xf7ca,0xf7cb,0xf7cc,0xf7cd,0xf7ce,0xf7cf, + 0xf7d0,0xf7d1,0xf7d2,0xf7d3,0xf7d4,0xf7d5,0xf7d6,0xf7d7, + 0xf7d8,0xf7d9,0xf7da,0xf7db,0xf7dc,0xf7dd,0xf7de,0xf7df, + 0xf7e0,0xf7e1,0xf7e2,0xf7e3,0xf7e4,0xf7e5,0xf7e6,0xf7e7, + 0xf7e8,0xf7e9,0xf7ea,0xf7eb,0xf7ec,0xf7ed,0xf7ee,0xf7ef, + 0xf7f0,0xf7f1,0xf7f2,0xf7f3,0xf7f4,0xf7f5,0xf7f6,0xf7f7, + 0xf7f8,0xf7f9,0xf7fa,0xf7fb,0xf7fc,0xf7fd,0xf7fe,0xf7ff, + 0xf800,0xf801,0xf802,0xf803,0xf804,0xf805,0xf806,0xf807, + 0xf808,0xf809,0xf80a,0xf80b,0xf80c,0xf80d,0xf80e,0xf80f, + 0xf810,0xf811,0xf812,0xf813,0xf814,0xf815,0xf816,0xf817, + 0xf818,0xf819,0xf81a,0xf81b,0xf81c,0xf81d,0xf81e,0xf81f, + 0xf820,0xf821,0xf822,0xf823,0xf824,0xf825,0xf826,0xf827, + 0xf828,0xf829,0xf82a,0xf82b,0xf82c,0xf82d,0xf82e,0xf82f, + 0xf830,0xf831,0xf832,0xf833,0xf834,0xf835,0xf836,0xf837, + 0xf838,0xf839,0xf83a,0xf83b,0xf83c,0xf83d,0xf83e,0xf83f, + 0xf840,0xf841,0xf842,0xf843,0xf844,0xf845,0xf846,0xf847, + 0xf848,0xf849,0xf84a,0xf84b,0xf84c,0xf84d,0xf84e,0xf84f, + 0xf850,0xf851,0xf852,0xf853,0xf854,0xf855,0xf856,0xf857, + 0xf858,0xf859,0xf85a,0xf85b,0xf85c,0xf85d,0xf85e,0xf85f, + 0xf860,0xf861,0xf862,0xf863,0xf864,0xf865,0xf866,0xf867, + 0xf868,0xf869,0xf86a,0xf86b,0xf86c,0xf86d,0xf86e,0xf86f, + 0xf870,0xf871,0xf872,0xf873,0xf874,0xf875,0xf876,0xf877, + 0xf878,0xf879,0xf87a,0xf87b,0xf87c,0xf87d,0xf87e,0xf87f, + 0xf880,0xf881,0xf882,0xf883,0xf884,0xf885,0xf886,0xf887, + 0xf888,0xf889,0xf88a,0xf88b,0xf88c,0xf88d,0xf88e,0xf88f, + 0xf890,0xf891,0xf892,0xf893,0xf894,0xf895,0xf896,0xf897, + 0xf898,0xf899,0xf89a,0xf89b,0xf89c,0xf89d,0xf89e,0xf89f, + 0xf8a0,0xf8a1,0xf8a2,0xf8a3,0xf8a4,0xf8a5,0xf8a6,0xf8a7, + 0xf8a8,0xf8a9,0xf8aa,0xf8ab,0xf8ac,0xf8ad,0xf8ae,0xf8af, + 0xf8b0,0xf8b1,0xf8b2,0xf8b3,0xf8b4,0xf8b5,0xf8b6,0xf8b7, + 0xf8b8,0xf8b9,0xf8ba,0xf8bb,0xf8bc,0xf8bd,0xf8be,0xf8bf, + 0xf8c0,0xf8c1,0xf8c2,0xf8c3,0xf8c4,0xf8c5,0xf8c6,0xf8c7, + 0xf8c8,0xf8c9,0xf8ca,0xf8cb,0xf8cc,0xf8cd,0xf8ce,0xf8cf, + 0xf8d0,0xf8d1,0xf8d2,0xf8d3,0xf8d4,0xf8d5,0xf8d6,0xf8d7, + 0xf8d8,0xf8d9,0xf8da,0xf8db,0xf8dc,0xf8dd,0xf8de,0xf8df, + 0xf8e0,0xf8e1,0xf8e2,0xf8e3,0xf8e4,0xf8e5,0xf8e6,0xf8e7, + 0xf8e8,0xf8e9,0xf8ea,0xf8eb,0xf8ec,0xf8ed,0xf8ee,0xf8ef, + 0xf8f0,0xf8f1,0xf8f2,0xf8f3,0xf8f4,0xf8f5,0xf8f6,0xf8f7, + 0xf8f8,0xf8f9,0xf8fa,0xf8fb,0xf8fc,0xf8fd,0xf8fe,0xf8ff, + 0xf900,0xf901,0xf902,0xf903,0xf904,0xf905,0xf906,0xf907, + 0xf908,0xf909,0xf90a,0xf90b,0xf90c,0xf90d,0xf90e,0xf90f, + 0xf910,0xf911,0xf912,0xf913,0xf914,0xf915,0xf916,0xf917, + 0xf918,0xf919,0xf91a,0xf91b,0xf91c,0xf91d,0xf91e,0xf91f, + 0xf920,0xf921,0xf922,0xf923,0xf924,0xf925,0xf926,0xf927, + 0xf928,0xf929,0xf92a,0xf92b,0xf92c,0xf92d,0xf92e,0xf92f, + 0xf930,0xf931,0xf932,0xf933,0xf934,0xf935,0xf936,0xf937, + 0xf938,0xf939,0xf93a,0xf93b,0xf93c,0xf93d,0xf93e,0xf93f, + 0xf940,0xf941,0xf942,0xf943,0xf944,0xf945,0xf946,0xf947, + 0xf948,0xf949,0xf94a,0xf94b,0xf94c,0xf94d,0xf94e,0xf94f, + 0xf950,0xf951,0xf952,0xf953,0xf954,0xf955,0xf956,0xf957, + 0xf958,0xf959,0xf95a,0xf95b,0xf95c,0xf95d,0xf95e,0xf95f, + 0xf960,0xf961,0xf962,0xf963,0xf964,0xf965,0xf966,0xf967, + 0xf968,0xf969,0xf96a,0xf96b,0xf96c,0xf96d,0xf96e,0xf96f, + 0xf970,0xf971,0xf972,0xf973,0xf974,0xf975,0xf976,0xf977, + 0xf978,0xf979,0xf97a,0xf97b,0xf97c,0xf97d,0xf97e,0xf97f, + 0xf980,0xf981,0xf982,0xf983,0xf984,0xf985,0xf986,0xf987, + 0xf988,0xf989,0xf98a,0xf98b,0xf98c,0xf98d,0xf98e,0xf98f, + 0xf990,0xf991,0xf992,0xf993,0xf994,0xf995,0xf996,0xf997, + 0xf998,0xf999,0xf99a,0xf99b,0xf99c,0xf99d,0xf99e,0xf99f, + 0xf9a0,0xf9a1,0xf9a2,0xf9a3,0xf9a4,0xf9a5,0xf9a6,0xf9a7, + 0xf9a8,0xf9a9,0xf9aa,0xf9ab,0xf9ac,0xf9ad,0xf9ae,0xf9af, + 0xf9b0,0xf9b1,0xf9b2,0xf9b3,0xf9b4,0xf9b5,0xf9b6,0xf9b7, + 0xf9b8,0xf9b9,0xf9ba,0xf9bb,0xf9bc,0xf9bd,0xf9be,0xf9bf, + 0xf9c0,0xf9c1,0xf9c2,0xf9c3,0xf9c4,0xf9c5,0xf9c6,0xf9c7, + 0xf9c8,0xf9c9,0xf9ca,0xf9cb,0xf9cc,0xf9cd,0xf9ce,0xf9cf, + 0xf9d0,0xf9d1,0xf9d2,0xf9d3,0xf9d4,0xf9d5,0xf9d6,0xf9d7, + 0xf9d8,0xf9d9,0xf9da,0xf9db,0xf9dc,0xf9dd,0xf9de,0xf9df, + 0xf9e0,0xf9e1,0xf9e2,0xf9e3,0xf9e4,0xf9e5,0xf9e6,0xf9e7, + 0xf9e8,0xf9e9,0xf9ea,0xf9eb,0xf9ec,0xf9ed,0xf9ee,0xf9ef, + 0xf9f0,0xf9f1,0xf9f2,0xf9f3,0xf9f4,0xf9f5,0xf9f6,0xf9f7, + 0xf9f8,0xf9f9,0xf9fa,0xf9fb,0xf9fc,0xf9fd,0xf9fe,0xf9ff, + 0xfa00,0xfa01,0xfa02,0xfa03,0xfa04,0xfa05,0xfa06,0xfa07, + 0xfa08,0xfa09,0xfa0a,0xfa0b,0xfa0c,0xfa0d,0xfa0e,0xfa0f, + 0xfa10,0xfa11,0xfa12,0xfa13,0xfa14,0xfa15,0xfa16,0xfa17, + 0xfa18,0xfa19,0xfa1a,0xfa1b,0xfa1c,0xfa1d,0xfa1e,0xfa1f, + 0xfa20,0xfa21,0xfa22,0xfa23,0xfa24,0xfa25,0xfa26,0xfa27, + 0xfa28,0xfa29,0xfa2a,0xfa2b,0xfa2c,0xfa2d,0xfa2e,0xfa2f, + 0xfa30,0xfa31,0xfa32,0xfa33,0xfa34,0xfa35,0xfa36,0xfa37, + 0xfa38,0xfa39,0xfa3a,0xfa3b,0xfa3c,0xfa3d,0xfa3e,0xfa3f, + 0xfa40,0xfa41,0xfa42,0xfa43,0xfa44,0xfa45,0xfa46,0xfa47, + 0xfa48,0xfa49,0xfa4a,0xfa4b,0xfa4c,0xfa4d,0xfa4e,0xfa4f, + 0xfa50,0xfa51,0xfa52,0xfa53,0xfa54,0xfa55,0xfa56,0xfa57, + 0xfa58,0xfa59,0xfa5a,0xfa5b,0xfa5c,0xfa5d,0xfa5e,0xfa5f, + 0xfa60,0xfa61,0xfa62,0xfa63,0xfa64,0xfa65,0xfa66,0xfa67, + 0xfa68,0xfa69,0xfa6a,0xfa6b,0xfa6c,0xfa6d,0xfa6e,0xfa6f, + 0xfa70,0xfa71,0xfa72,0xfa73,0xfa74,0xfa75,0xfa76,0xfa77, + 0xfa78,0xfa79,0xfa7a,0xfa7b,0xfa7c,0xfa7d,0xfa7e,0xfa7f, + 0xfa80,0xfa81,0xfa82,0xfa83,0xfa84,0xfa85,0xfa86,0xfa87, + 0xfa88,0xfa89,0xfa8a,0xfa8b,0xfa8c,0xfa8d,0xfa8e,0xfa8f, + 0xfa90,0xfa91,0xfa92,0xfa93,0xfa94,0xfa95,0xfa96,0xfa97, + 0xfa98,0xfa99,0xfa9a,0xfa9b,0xfa9c,0xfa9d,0xfa9e,0xfa9f, + 0xfaa0,0xfaa1,0xfaa2,0xfaa3,0xfaa4,0xfaa5,0xfaa6,0xfaa7, + 0xfaa8,0xfaa9,0xfaaa,0xfaab,0xfaac,0xfaad,0xfaae,0xfaaf, + 0xfab0,0xfab1,0xfab2,0xfab3,0xfab4,0xfab5,0xfab6,0xfab7, + 0xfab8,0xfab9,0xfaba,0xfabb,0xfabc,0xfabd,0xfabe,0xfabf, + 0xfac0,0xfac1,0xfac2,0xfac3,0xfac4,0xfac5,0xfac6,0xfac7, + 0xfac8,0xfac9,0xfaca,0xfacb,0xfacc,0xfacd,0xface,0xfacf, + 0xfad0,0xfad1,0xfad2,0xfad3,0xfad4,0xfad5,0xfad6,0xfad7, + 0xfad8,0xfad9,0xfada,0xfadb,0xfadc,0xfadd,0xfade,0xfadf, + 0xfae0,0xfae1,0xfae2,0xfae3,0xfae4,0xfae5,0xfae6,0xfae7, + 0xfae8,0xfae9,0xfaea,0xfaeb,0xfaec,0xfaed,0xfaee,0xfaef, + 0xfaf0,0xfaf1,0xfaf2,0xfaf3,0xfaf4,0xfaf5,0xfaf6,0xfaf7, + 0xfaf8,0xfaf9,0xfafa,0xfafb,0xfafc,0xfafd,0xfafe,0xfaff, + 0xfb00,0xfb01,0xfb02,0xfb03,0xfb04,0xfb05,0xfb06,0xfb07, + 0xfb08,0xfb09,0xfb0a,0xfb0b,0xfb0c,0xfb0d,0xfb0e,0xfb0f, + 0xfb10,0xfb11,0xfb12,0xfb13,0xfb14,0xfb15,0xfb16,0xfb17, + 0xfb18,0xfb19,0xfb1a,0xfb1b,0xfb1c,0xfb1d,0xfb1e,0xfb1f, + 0xfb20,0xfb21,0xfb22,0xfb23,0xfb24,0xfb25,0xfb26,0xfb27, + 0xfb28,0xfb29,0xfb2a,0xfb2b,0xfb2c,0xfb2d,0xfb2e,0xfb2f, + 0xfb30,0xfb31,0xfb32,0xfb33,0xfb34,0xfb35,0xfb36,0xfb37, + 0xfb38,0xfb39,0xfb3a,0xfb3b,0xfb3c,0xfb3d,0xfb3e,0xfb3f, + 0xfb40,0xfb41,0xfb42,0xfb43,0xfb44,0xfb45,0xfb46,0xfb47, + 0xfb48,0xfb49,0xfb4a,0xfb4b,0xfb4c,0xfb4d,0xfb4e,0xfb4f, + 0xfb50,0xfb51,0xfb52,0xfb53,0xfb54,0xfb55,0xfb56,0xfb57, + 0xfb58,0xfb59,0xfb5a,0xfb5b,0xfb5c,0xfb5d,0xfb5e,0xfb5f, + 0xfb60,0xfb61,0xfb62,0xfb63,0xfb64,0xfb65,0xfb66,0xfb67, + 0xfb68,0xfb69,0xfb6a,0xfb6b,0xfb6c,0xfb6d,0xfb6e,0xfb6f, + 0xfb70,0xfb71,0xfb72,0xfb73,0xfb74,0xfb75,0xfb76,0xfb77, + 0xfb78,0xfb79,0xfb7a,0xfb7b,0xfb7c,0xfb7d,0xfb7e,0xfb7f, + 0xfb80,0xfb81,0xfb82,0xfb83,0xfb84,0xfb85,0xfb86,0xfb87, + 0xfb88,0xfb89,0xfb8a,0xfb8b,0xfb8c,0xfb8d,0xfb8e,0xfb8f, + 0xfb90,0xfb91,0xfb92,0xfb93,0xfb94,0xfb95,0xfb96,0xfb97, + 0xfb98,0xfb99,0xfb9a,0xfb9b,0xfb9c,0xfb9d,0xfb9e,0xfb9f, + 0xfba0,0xfba1,0xfba2,0xfba3,0xfba4,0xfba5,0xfba6,0xfba7, + 0xfba8,0xfba9,0xfbaa,0xfbab,0xfbac,0xfbad,0xfbae,0xfbaf, + 0xfbb0,0xfbb1,0xfbb2,0xfbb3,0xfbb4,0xfbb5,0xfbb6,0xfbb7, + 0xfbb8,0xfbb9,0xfbba,0xfbbb,0xfbbc,0xfbbd,0xfbbe,0xfbbf, + 0xfbc0,0xfbc1,0xfbc2,0xfbc3,0xfbc4,0xfbc5,0xfbc6,0xfbc7, + 0xfbc8,0xfbc9,0xfbca,0xfbcb,0xfbcc,0xfbcd,0xfbce,0xfbcf, + 0xfbd0,0xfbd1,0xfbd2,0xfbd3,0xfbd4,0xfbd5,0xfbd6,0xfbd7, + 0xfbd8,0xfbd9,0xfbda,0xfbdb,0xfbdc,0xfbdd,0xfbde,0xfbdf, + 0xfbe0,0xfbe1,0xfbe2,0xfbe3,0xfbe4,0xfbe5,0xfbe6,0xfbe7, + 0xfbe8,0xfbe9,0xfbea,0xfbeb,0xfbec,0xfbed,0xfbee,0xfbef, + 0xfbf0,0xfbf1,0xfbf2,0xfbf3,0xfbf4,0xfbf5,0xfbf6,0xfbf7, + 0xfbf8,0xfbf9,0xfbfa,0xfbfb,0xfbfc,0xfbfd,0xfbfe,0xfbff, + 0xfc00,0xfc01,0xfc02,0xfc03,0xfc04,0xfc05,0xfc06,0xfc07, + 0xfc08,0xfc09,0xfc0a,0xfc0b,0xfc0c,0xfc0d,0xfc0e,0xfc0f, + 0xfc10,0xfc11,0xfc12,0xfc13,0xfc14,0xfc15,0xfc16,0xfc17, + 0xfc18,0xfc19,0xfc1a,0xfc1b,0xfc1c,0xfc1d,0xfc1e,0xfc1f, + 0xfc20,0xfc21,0xfc22,0xfc23,0xfc24,0xfc25,0xfc26,0xfc27, + 0xfc28,0xfc29,0xfc2a,0xfc2b,0xfc2c,0xfc2d,0xfc2e,0xfc2f, + 0xfc30,0xfc31,0xfc32,0xfc33,0xfc34,0xfc35,0xfc36,0xfc37, + 0xfc38,0xfc39,0xfc3a,0xfc3b,0xfc3c,0xfc3d,0xfc3e,0xfc3f, + 0xfc40,0xfc41,0xfc42,0xfc43,0xfc44,0xfc45,0xfc46,0xfc47, + 0xfc48,0xfc49,0xfc4a,0xfc4b,0xfc4c,0xfc4d,0xfc4e,0xfc4f, + 0xfc50,0xfc51,0xfc52,0xfc53,0xfc54,0xfc55,0xfc56,0xfc57, + 0xfc58,0xfc59,0xfc5a,0xfc5b,0xfc5c,0xfc5d,0xfc5e,0xfc5f, + 0xfc60,0xfc61,0xfc62,0xfc63,0xfc64,0xfc65,0xfc66,0xfc67, + 0xfc68,0xfc69,0xfc6a,0xfc6b,0xfc6c,0xfc6d,0xfc6e,0xfc6f, + 0xfc70,0xfc71,0xfc72,0xfc73,0xfc74,0xfc75,0xfc76,0xfc77, + 0xfc78,0xfc79,0xfc7a,0xfc7b,0xfc7c,0xfc7d,0xfc7e,0xfc7f, + 0xfc80,0xfc81,0xfc82,0xfc83,0xfc84,0xfc85,0xfc86,0xfc87, + 0xfc88,0xfc89,0xfc8a,0xfc8b,0xfc8c,0xfc8d,0xfc8e,0xfc8f, + 0xfc90,0xfc91,0xfc92,0xfc93,0xfc94,0xfc95,0xfc96,0xfc97, + 0xfc98,0xfc99,0xfc9a,0xfc9b,0xfc9c,0xfc9d,0xfc9e,0xfc9f, + 0xfca0,0xfca1,0xfca2,0xfca3,0xfca4,0xfca5,0xfca6,0xfca7, + 0xfca8,0xfca9,0xfcaa,0xfcab,0xfcac,0xfcad,0xfcae,0xfcaf, + 0xfcb0,0xfcb1,0xfcb2,0xfcb3,0xfcb4,0xfcb5,0xfcb6,0xfcb7, + 0xfcb8,0xfcb9,0xfcba,0xfcbb,0xfcbc,0xfcbd,0xfcbe,0xfcbf, + 0xfcc0,0xfcc1,0xfcc2,0xfcc3,0xfcc4,0xfcc5,0xfcc6,0xfcc7, + 0xfcc8,0xfcc9,0xfcca,0xfccb,0xfccc,0xfccd,0xfcce,0xfccf, + 0xfcd0,0xfcd1,0xfcd2,0xfcd3,0xfcd4,0xfcd5,0xfcd6,0xfcd7, + 0xfcd8,0xfcd9,0xfcda,0xfcdb,0xfcdc,0xfcdd,0xfcde,0xfcdf, + 0xfce0,0xfce1,0xfce2,0xfce3,0xfce4,0xfce5,0xfce6,0xfce7, + 0xfce8,0xfce9,0xfcea,0xfceb,0xfcec,0xfced,0xfcee,0xfcef, + 0xfcf0,0xfcf1,0xfcf2,0xfcf3,0xfcf4,0xfcf5,0xfcf6,0xfcf7, + 0xfcf8,0xfcf9,0xfcfa,0xfcfb,0xfcfc,0xfcfd,0xfcfe,0xfcff, + 0xfd00,0xfd01,0xfd02,0xfd03,0xfd04,0xfd05,0xfd06,0xfd07, + 0xfd08,0xfd09,0xfd0a,0xfd0b,0xfd0c,0xfd0d,0xfd0e,0xfd0f, + 0xfd10,0xfd11,0xfd12,0xfd13,0xfd14,0xfd15,0xfd16,0xfd17, + 0xfd18,0xfd19,0xfd1a,0xfd1b,0xfd1c,0xfd1d,0xfd1e,0xfd1f, + 0xfd20,0xfd21,0xfd22,0xfd23,0xfd24,0xfd25,0xfd26,0xfd27, + 0xfd28,0xfd29,0xfd2a,0xfd2b,0xfd2c,0xfd2d,0xfd2e,0xfd2f, + 0xfd30,0xfd31,0xfd32,0xfd33,0xfd34,0xfd35,0xfd36,0xfd37, + 0xfd38,0xfd39,0xfd3a,0xfd3b,0xfd3c,0xfd3d,0xfd3e,0xfd3f, + 0xfd40,0xfd41,0xfd42,0xfd43,0xfd44,0xfd45,0xfd46,0xfd47, + 0xfd48,0xfd49,0xfd4a,0xfd4b,0xfd4c,0xfd4d,0xfd4e,0xfd4f, + 0xfd50,0xfd51,0xfd52,0xfd53,0xfd54,0xfd55,0xfd56,0xfd57, + 0xfd58,0xfd59,0xfd5a,0xfd5b,0xfd5c,0xfd5d,0xfd5e,0xfd5f, + 0xfd60,0xfd61,0xfd62,0xfd63,0xfd64,0xfd65,0xfd66,0xfd67, + 0xfd68,0xfd69,0xfd6a,0xfd6b,0xfd6c,0xfd6d,0xfd6e,0xfd6f, + 0xfd70,0xfd71,0xfd72,0xfd73,0xfd74,0xfd75,0xfd76,0xfd77, + 0xfd78,0xfd79,0xfd7a,0xfd7b,0xfd7c,0xfd7d,0xfd7e,0xfd7f, + 0xfd80,0xfd81,0xfd82,0xfd83,0xfd84,0xfd85,0xfd86,0xfd87, + 0xfd88,0xfd89,0xfd8a,0xfd8b,0xfd8c,0xfd8d,0xfd8e,0xfd8f, + 0xfd90,0xfd91,0xfd92,0xfd93,0xfd94,0xfd95,0xfd96,0xfd97, + 0xfd98,0xfd99,0xfd9a,0xfd9b,0xfd9c,0xfd9d,0xfd9e,0xfd9f, + 0xfda0,0xfda1,0xfda2,0xfda3,0xfda4,0xfda5,0xfda6,0xfda7, + 0xfda8,0xfda9,0xfdaa,0xfdab,0xfdac,0xfdad,0xfdae,0xfdaf, + 0xfdb0,0xfdb1,0xfdb2,0xfdb3,0xfdb4,0xfdb5,0xfdb6,0xfdb7, + 0xfdb8,0xfdb9,0xfdba,0xfdbb,0xfdbc,0xfdbd,0xfdbe,0xfdbf, + 0xfdc0,0xfdc1,0xfdc2,0xfdc3,0xfdc4,0xfdc5,0xfdc6,0xfdc7, + 0xfdc8,0xfdc9,0xfdca,0xfdcb,0xfdcc,0xfdcd,0xfdce,0xfdcf, + 0xfdd0,0xfdd1,0xfdd2,0xfdd3,0xfdd4,0xfdd5,0xfdd6,0xfdd7, + 0xfdd8,0xfdd9,0xfdda,0xfddb,0xfddc,0xfddd,0xfdde,0xfddf, + 0xfde0,0xfde1,0xfde2,0xfde3,0xfde4,0xfde5,0xfde6,0xfde7, + 0xfde8,0xfde9,0xfdea,0xfdeb,0xfdec,0xfded,0xfdee,0xfdef, + 0xfdf0,0xfdf1,0xfdf2,0xfdf3,0xfdf4,0xfdf5,0xfdf6,0xfdf7, + 0xfdf8,0xfdf9,0xfdfa,0xfdfb,0xfdfc,0xfdfd,0xfdfe,0xfdff, + 0xfe00,0xfe01,0xfe02,0xfe03,0xfe04,0xfe05,0xfe06,0xfe07, + 0xfe08,0xfe09,0xfe0a,0xfe0b,0xfe0c,0xfe0d,0xfe0e,0xfe0f, + 0xfe10,0xfe11,0xfe12,0xfe13,0xfe14,0xfe15,0xfe16,0xfe17, + 0xfe18,0xfe19,0xfe1a,0xfe1b,0xfe1c,0xfe1d,0xfe1e,0xfe1f, + 0xfe20,0xfe21,0xfe22,0xfe23,0xfe24,0xfe25,0xfe26,0xfe27, + 0xfe28,0xfe29,0xfe2a,0xfe2b,0xfe2c,0xfe2d,0xfe2e,0xfe2f, + 0xfe30,0xfe31,0xfe32,0xfe33,0xfe34,0xfe35,0xfe36,0xfe37, + 0xfe38,0xfe39,0xfe3a,0xfe3b,0xfe3c,0xfe3d,0xfe3e,0xfe3f, + 0xfe40,0xfe41,0xfe42,0xfe43,0xfe44,0xfe45,0xfe46,0xfe47, + 0xfe48,0xfe49,0xfe4a,0xfe4b,0xfe4c,0xfe4d,0xfe4e,0xfe4f, + 0xfe50,0xfe51,0xfe52,0xfe53,0xfe54,0xfe55,0xfe56,0xfe57, + 0xfe58,0xfe59,0xfe5a,0xfe5b,0xfe5c,0xfe5d,0xfe5e,0xfe5f, + 0xfe60,0xfe61,0xfe62,0xfe63,0xfe64,0xfe65,0xfe66,0xfe67, + 0xfe68,0xfe69,0xfe6a,0xfe6b,0xfe6c,0xfe6d,0xfe6e,0xfe6f, + 0xfe70,0xfe71,0xfe72,0xfe73,0xfe74,0xfe75,0xfe76,0xfe77, + 0xfe78,0xfe79,0xfe7a,0xfe7b,0xfe7c,0xfe7d,0xfe7e,0xfe7f, + 0xfe80,0xfe81,0xfe82,0xfe83,0xfe84,0xfe85,0xfe86,0xfe87, + 0xfe88,0xfe89,0xfe8a,0xfe8b,0xfe8c,0xfe8d,0xfe8e,0xfe8f, + 0xfe90,0xfe91,0xfe92,0xfe93,0xfe94,0xfe95,0xfe96,0xfe97, + 0xfe98,0xfe99,0xfe9a,0xfe9b,0xfe9c,0xfe9d,0xfe9e,0xfe9f, + 0xfea0,0xfea1,0xfea2,0xfea3,0xfea4,0xfea5,0xfea6,0xfea7, + 0xfea8,0xfea9,0xfeaa,0xfeab,0xfeac,0xfead,0xfeae,0xfeaf, + 0xfeb0,0xfeb1,0xfeb2,0xfeb3,0xfeb4,0xfeb5,0xfeb6,0xfeb7, + 0xfeb8,0xfeb9,0xfeba,0xfebb,0xfebc,0xfebd,0xfebe,0xfebf, + 0xfec0,0xfec1,0xfec2,0xfec3,0xfec4,0xfec5,0xfec6,0xfec7, + 0xfec8,0xfec9,0xfeca,0xfecb,0xfecc,0xfecd,0xfece,0xfecf, + 0xfed0,0xfed1,0xfed2,0xfed3,0xfed4,0xfed5,0xfed6,0xfed7, + 0xfed8,0xfed9,0xfeda,0xfedb,0xfedc,0xfedd,0xfede,0xfedf, + 0xfee0,0xfee1,0xfee2,0xfee3,0xfee4,0xfee5,0xfee6,0xfee7, + 0xfee8,0xfee9,0xfeea,0xfeeb,0xfeec,0xfeed,0xfeee,0xfeef, + 0xfef0,0xfef1,0xfef2,0xfef3,0xfef4,0xfef5,0xfef6,0xfef7, + 0xfef8,0xfef9,0xfefa,0xfefb,0xfefc,0xfefd,0xfefe,0xfeff, + 0xff00,0xff01,0xff02,0xff03,0xff04,0xff05,0xff06,0xff07, + 0xff08,0xff09,0xff0a,0xff0b,0xff0c,0xff0d,0xff0e,0xff0f, + 0xff10,0xff11,0xff12,0xff13,0xff14,0xff15,0xff16,0xff17, + 0xff18,0xff19,0xff1a,0xff1b,0xff1c,0xff1d,0xff1e,0xff1f, + 0xff20,0xff41,0xff42,0xff43,0xff44,0xff45,0xff46,0xff47, + 0xff48,0xff49,0xff4a,0xff4b,0xff4c,0xff4d,0xff4e,0xff4f, + 0xff50,0xff51,0xff52,0xff53,0xff54,0xff55,0xff56,0xff57, + 0xff58,0xff59,0xff5a,0xff3b,0xff3c,0xff3d,0xff3e,0xff3f, + 0xff40,0xff41,0xff42,0xff43,0xff44,0xff45,0xff46,0xff47, + 0xff48,0xff49,0xff4a,0xff4b,0xff4c,0xff4d,0xff4e,0xff4f, + 0xff50,0xff51,0xff52,0xff53,0xff54,0xff55,0xff56,0xff57, + 0xff58,0xff59,0xff5a,0xff5b,0xff5c,0xff5d,0xff5e,0xff5f, + 0xff60,0xff61,0xff62,0xff63,0xff64,0xff65,0xff66,0xff67, + 0xff68,0xff69,0xff6a,0xff6b,0xff6c,0xff6d,0xff6e,0xff6f, + 0xff70,0xff71,0xff72,0xff73,0xff74,0xff75,0xff76,0xff77, + 0xff78,0xff79,0xff7a,0xff7b,0xff7c,0xff7d,0xff7e,0xff7f, + 0xff80,0xff81,0xff82,0xff83,0xff84,0xff85,0xff86,0xff87, + 0xff88,0xff89,0xff8a,0xff8b,0xff8c,0xff8d,0xff8e,0xff8f, + 0xff90,0xff91,0xff92,0xff93,0xff94,0xff95,0xff96,0xff97, + 0xff98,0xff99,0xff9a,0xff9b,0xff9c,0xff9d,0xff9e,0xff9f, + 0xffa0,0xffa1,0xffa2,0xffa3,0xffa4,0xffa5,0xffa6,0xffa7, + 0xffa8,0xffa9,0xffaa,0xffab,0xffac,0xffad,0xffae,0xffaf, + 0xffb0,0xffb1,0xffb2,0xffb3,0xffb4,0xffb5,0xffb6,0xffb7, + 0xffb8,0xffb9,0xffba,0xffbb,0xffbc,0xffbd,0xffbe,0xffbf, + 0xffc0,0xffc1,0xffc2,0xffc3,0xffc4,0xffc5,0xffc6,0xffc7, + 0xffc8,0xffc9,0xffca,0xffcb,0xffcc,0xffcd,0xffce,0xffcf, + 0xffd0,0xffd1,0xffd2,0xffd3,0xffd4,0xffd5,0xffd6,0xffd7, + 0xffd8,0xffd9,0xffda,0xffdb,0xffdc,0xffdd,0xffde,0xffdf, + 0xffe0,0xffe1,0xffe2,0xffe3,0xffe4,0xffe5,0xffe6,0xffe7, + 0xffe8,0xffe9,0xffea,0xffeb,0xffec,0xffed,0xffee,0xffef, + 0xfff0,0xfff1,0xfff2,0xfff3,0xfff4,0xfff5,0xfff6,0xfff7, + 0xfff8,0xfff9,0xfffa,0xfffb,0xfffc,0xfffd,0xfffe,0xffff +}; + +static const uint16_t upcase_table[] = { + 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, + 0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, + 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, + 0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, + 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, + 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, + 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, + 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, + 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, + 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, + 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, + 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, + 0x0060,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, + 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, + 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, + 0x0058,0x0059,0x005a,0x007b,0x007c,0x007d,0x007e,0x007f, + 0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087, + 0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f, + 0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097, + 0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f, + 0x00a0,0x00a1,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7, + 0x00a8,0x00a9,0x00aa,0x00ab,0x00ac,0x00ad,0x00ae,0x00af, + 0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7, + 0x00b8,0x00b9,0x00ba,0x00bb,0x00bc,0x00bd,0x00be,0x00bf, + 0x00c0,0x00c1,0x00c2,0x00c3,0x00c4,0x00c5,0x00c6,0x00c7, + 0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd,0x00ce,0x00cf, + 0x00d0,0x00d1,0x00d2,0x00d3,0x00d4,0x00d5,0x00d6,0x00d7, + 0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x00dd,0x00de,0x00df, + 0x00c0,0x00c1,0x00c2,0x00c3,0x00c4,0x00c5,0x00c6,0x00c7, + 0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd,0x00ce,0x00cf, + 0x00d0,0x00d1,0x00d2,0x00d3,0x00d4,0x00d5,0x00d6,0x00f7, + 0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x00dd,0x00de,0x0178, + 0x0100,0x0100,0x0102,0x0102,0x0104,0x0104,0x0106,0x0106, + 0x0108,0x0108,0x010a,0x010a,0x010c,0x010c,0x010e,0x010e, + 0x0110,0x0110,0x0112,0x0112,0x0114,0x0114,0x0116,0x0116, + 0x0118,0x0118,0x011a,0x011a,0x011c,0x011c,0x011e,0x011e, + 0x0120,0x0120,0x0122,0x0122,0x0124,0x0124,0x0126,0x0126, + 0x0128,0x0128,0x012a,0x012a,0x012c,0x012c,0x012e,0x012e, + 0x0130,0x0131,0x0132,0x0132,0x0134,0x0134,0x0136,0x0136, + 0x0138,0x0139,0x0139,0x013b,0x013b,0x013d,0x013d,0x013f, + 0x013f,0x0141,0x0141,0x0143,0x0143,0x0145,0x0145,0x0147, + 0x0147,0x0149,0x014a,0x014a,0x014c,0x014c,0x014e,0x014e, + 0x0150,0x0150,0x0152,0x0152,0x0154,0x0154,0x0156,0x0156, + 0x0158,0x0158,0x015a,0x015a,0x015c,0x015c,0x015e,0x015e, + 0x0160,0x0160,0x0162,0x0162,0x0164,0x0164,0x0166,0x0166, + 0x0168,0x0168,0x016a,0x016a,0x016c,0x016c,0x016e,0x016e, + 0x0170,0x0170,0x0172,0x0172,0x0174,0x0174,0x0176,0x0176, + 0x0178,0x0179,0x0179,0x017b,0x017b,0x017d,0x017d,0x017f, + 0x0180,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187, + 0x0187,0x0189,0x018a,0x018b,0x018b,0x018d,0x018e,0x018f, + 0x0190,0x0191,0x0191,0x0193,0x0194,0x0195,0x0196,0x0197, + 0x0198,0x0198,0x019a,0x019b,0x019c,0x019d,0x019e,0x019f, + 0x01a0,0x01a0,0x01a2,0x01a2,0x01a4,0x01a4,0x01a6,0x01a7, + 0x01a7,0x01a9,0x01aa,0x01ab,0x01ac,0x01ac,0x01ae,0x01af, + 0x01af,0x01b1,0x01b2,0x01b3,0x01b3,0x01b5,0x01b5,0x01b7, + 0x01b8,0x01b8,0x01ba,0x01bb,0x01bc,0x01bc,0x01be,0x01bf, + 0x01c0,0x01c1,0x01c2,0x01c3,0x01c4,0x01c5,0x01c4,0x01c7, + 0x01c8,0x01c7,0x01ca,0x01cb,0x01ca,0x01cd,0x01cd,0x01cf, + 0x01cf,0x01d1,0x01d1,0x01d3,0x01d3,0x01d5,0x01d5,0x01d7, + 0x01d7,0x01d9,0x01d9,0x01db,0x01db,0x018e,0x01de,0x01de, + 0x01e0,0x01e0,0x01e2,0x01e2,0x01e4,0x01e4,0x01e6,0x01e6, + 0x01e8,0x01e8,0x01ea,0x01ea,0x01ec,0x01ec,0x01ee,0x01ee, + 0x01f0,0x01f1,0x01f2,0x01f1,0x01f4,0x01f4,0x01f6,0x01f7, + 0x01f8,0x01f9,0x01fa,0x01fa,0x01fc,0x01fc,0x01fe,0x01fe, + 0x0200,0x0200,0x0202,0x0202,0x0204,0x0204,0x0206,0x0206, + 0x0208,0x0208,0x020a,0x020a,0x020c,0x020c,0x020e,0x020e, + 0x0210,0x0210,0x0212,0x0212,0x0214,0x0214,0x0216,0x0216, + 0x0218,0x0219,0x021a,0x021b,0x021c,0x021d,0x021e,0x021f, + 0x0220,0x0221,0x0222,0x0223,0x0224,0x0225,0x0226,0x0227, + 0x0228,0x0229,0x022a,0x022b,0x022c,0x022d,0x022e,0x022f, + 0x0230,0x0231,0x0232,0x0233,0x0234,0x0235,0x0236,0x0237, + 0x0238,0x0239,0x023a,0x023b,0x023c,0x023d,0x023e,0x023f, + 0x0240,0x0241,0x0242,0x0243,0x0244,0x0245,0x0246,0x0247, + 0x0248,0x0249,0x024a,0x024b,0x024c,0x024d,0x024e,0x024f, + 0x0250,0x0251,0x0252,0x0181,0x0186,0x0255,0x0189,0x018a, + 0x0258,0x018f,0x025a,0x0190,0x025c,0x025d,0x025e,0x025f, + 0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267, + 0x0197,0x0196,0x026a,0x026b,0x026c,0x026d,0x026e,0x019c, + 0x0270,0x0271,0x019d,0x0273,0x0274,0x019f,0x0276,0x0277, + 0x0278,0x0279,0x027a,0x027b,0x027c,0x027d,0x027e,0x027f, + 0x0280,0x0281,0x0282,0x01a9,0x0284,0x0285,0x0286,0x0287, + 0x01ae,0x0289,0x01b1,0x01b2,0x028c,0x028d,0x028e,0x028f, + 0x0290,0x0291,0x01b7,0x0293,0x0294,0x0295,0x0296,0x0297, + 0x0298,0x0299,0x029a,0x029b,0x029c,0x029d,0x029e,0x029f, + 0x02a0,0x02a1,0x02a2,0x02a3,0x02a4,0x02a5,0x02a6,0x02a7, + 0x02a8,0x02a9,0x02aa,0x02ab,0x02ac,0x02ad,0x02ae,0x02af, + 0x02b0,0x02b1,0x02b2,0x02b3,0x02b4,0x02b5,0x02b6,0x02b7, + 0x02b8,0x02b9,0x02ba,0x02bb,0x02bc,0x02bd,0x02be,0x02bf, + 0x02c0,0x02c1,0x02c2,0x02c3,0x02c4,0x02c5,0x02c6,0x02c7, + 0x02c8,0x02c9,0x02ca,0x02cb,0x02cc,0x02cd,0x02ce,0x02cf, + 0x02d0,0x02d1,0x02d2,0x02d3,0x02d4,0x02d5,0x02d6,0x02d7, + 0x02d8,0x02d9,0x02da,0x02db,0x02dc,0x02dd,0x02de,0x02df, + 0x02e0,0x02e1,0x02e2,0x02e3,0x02e4,0x02e5,0x02e6,0x02e7, + 0x02e8,0x02e9,0x02ea,0x02eb,0x02ec,0x02ed,0x02ee,0x02ef, + 0x02f0,0x02f1,0x02f2,0x02f3,0x02f4,0x02f5,0x02f6,0x02f7, + 0x02f8,0x02f9,0x02fa,0x02fb,0x02fc,0x02fd,0x02fe,0x02ff, + 0x0300,0x0301,0x0302,0x0303,0x0304,0x0305,0x0306,0x0307, + 0x0308,0x0309,0x030a,0x030b,0x030c,0x030d,0x030e,0x030f, + 0x0310,0x0311,0x0312,0x0313,0x0314,0x0315,0x0316,0x0317, + 0x0318,0x0319,0x031a,0x031b,0x031c,0x031d,0x031e,0x031f, + 0x0320,0x0321,0x0322,0x0323,0x0324,0x0325,0x0326,0x0327, + 0x0328,0x0329,0x032a,0x032b,0x032c,0x032d,0x032e,0x032f, + 0x0330,0x0331,0x0332,0x0333,0x0334,0x0335,0x0336,0x0337, + 0x0338,0x0339,0x033a,0x033b,0x033c,0x033d,0x033e,0x033f, + 0x0340,0x0341,0x0342,0x0343,0x0344,0x0345,0x0346,0x0347, + 0x0348,0x0349,0x034a,0x034b,0x034c,0x034d,0x034e,0x034f, + 0x0350,0x0351,0x0352,0x0353,0x0354,0x0355,0x0356,0x0357, + 0x0358,0x0359,0x035a,0x035b,0x035c,0x035d,0x035e,0x035f, + 0x0360,0x0361,0x0362,0x0363,0x0364,0x0365,0x0366,0x0367, + 0x0368,0x0369,0x036a,0x036b,0x036c,0x036d,0x036e,0x036f, + 0x0370,0x0371,0x0372,0x0373,0x0374,0x0375,0x0376,0x0377, + 0x0378,0x0379,0x037a,0x037b,0x037c,0x037d,0x037e,0x037f, + 0x0380,0x0381,0x0382,0x0383,0x0384,0x0385,0x0386,0x0387, + 0x0388,0x0389,0x038a,0x038b,0x038c,0x038d,0x038e,0x038f, + 0x0390,0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397, + 0x0398,0x0399,0x039a,0x039b,0x039c,0x039d,0x039e,0x039f, + 0x03a0,0x03a1,0x03a2,0x03a3,0x03a4,0x03a5,0x03a6,0x03a7, + 0x03a8,0x03a9,0x03aa,0x03ab,0x0386,0x0388,0x0389,0x038a, + 0x03b0,0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397, + 0x0398,0x0399,0x039a,0x039b,0x039c,0x039d,0x039e,0x039f, + 0x03a0,0x03a1,0x03a3,0x03a3,0x03a4,0x03a5,0x03a6,0x03a7, + 0x03a8,0x03a9,0x03aa,0x03ab,0x038c,0x038e,0x038f,0x03cf, + 0x03d0,0x03d1,0x03d2,0x03d3,0x03d4,0x03d5,0x03d6,0x03d7, + 0x03d8,0x03d9,0x03da,0x03db,0x03dc,0x03dd,0x03de,0x03df, + 0x03e0,0x03e1,0x03e2,0x03e2,0x03e4,0x03e4,0x03e6,0x03e6, + 0x03e8,0x03e8,0x03ea,0x03ea,0x03ec,0x03ec,0x03ee,0x03ee, + 0x03f0,0x03f1,0x03f2,0x03f3,0x03f4,0x03f5,0x03f6,0x03f7, + 0x03f8,0x03f9,0x03fa,0x03fb,0x03fc,0x03fd,0x03fe,0x03ff, + 0x0400,0x0401,0x0402,0x0403,0x0404,0x0405,0x0406,0x0407, + 0x0408,0x0409,0x040a,0x040b,0x040c,0x040d,0x040e,0x040f, + 0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417, + 0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f, + 0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427, + 0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f, + 0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417, + 0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f, + 0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427, + 0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f, + 0x0450,0x0401,0x0402,0x0403,0x0404,0x0405,0x0406,0x0407, + 0x0408,0x0409,0x040a,0x040b,0x040c,0x045d,0x040e,0x040f, + 0x0460,0x0460,0x0462,0x0462,0x0464,0x0464,0x0466,0x0466, + 0x0468,0x0468,0x046a,0x046a,0x046c,0x046c,0x046e,0x046e, + 0x0470,0x0470,0x0472,0x0472,0x0474,0x0474,0x0476,0x0476, + 0x0478,0x0478,0x047a,0x047a,0x047c,0x047c,0x047e,0x047e, + 0x0480,0x0480,0x0482,0x0483,0x0484,0x0485,0x0486,0x0487, + 0x0488,0x0489,0x048a,0x048b,0x048c,0x048d,0x048e,0x048f, + 0x0490,0x0490,0x0492,0x0492,0x0494,0x0494,0x0496,0x0496, + 0x0498,0x0498,0x049a,0x049a,0x049c,0x049c,0x049e,0x049e, + 0x04a0,0x04a0,0x04a2,0x04a2,0x04a4,0x04a4,0x04a6,0x04a6, + 0x04a8,0x04a8,0x04aa,0x04aa,0x04ac,0x04ac,0x04ae,0x04ae, + 0x04b0,0x04b0,0x04b2,0x04b2,0x04b4,0x04b4,0x04b6,0x04b6, + 0x04b8,0x04b8,0x04ba,0x04ba,0x04bc,0x04bc,0x04be,0x04be, + 0x04c0,0x04c1,0x04c1,0x04c3,0x04c3,0x04c5,0x04c6,0x04c7, + 0x04c7,0x04c9,0x04ca,0x04cb,0x04cb,0x04cd,0x04ce,0x04cf, + 0x04d0,0x04d0,0x04d2,0x04d2,0x04d4,0x04d4,0x04d6,0x04d6, + 0x04d8,0x04d8,0x04da,0x04da,0x04dc,0x04dc,0x04de,0x04de, + 0x04e0,0x04e0,0x04e2,0x04e2,0x04e4,0x04e4,0x04e6,0x04e6, + 0x04e8,0x04e8,0x04ea,0x04ea,0x04ec,0x04ed,0x04ee,0x04ee, + 0x04f0,0x04f0,0x04f2,0x04f2,0x04f4,0x04f4,0x04f6,0x04f7, + 0x04f8,0x04f8,0x04fa,0x04fb,0x04fc,0x04fd,0x04fe,0x04ff, + 0x0500,0x0501,0x0502,0x0503,0x0504,0x0505,0x0506,0x0507, + 0x0508,0x0509,0x050a,0x050b,0x050c,0x050d,0x050e,0x050f, + 0x0510,0x0511,0x0512,0x0513,0x0514,0x0515,0x0516,0x0517, + 0x0518,0x0519,0x051a,0x051b,0x051c,0x051d,0x051e,0x051f, + 0x0520,0x0521,0x0522,0x0523,0x0524,0x0525,0x0526,0x0527, + 0x0528,0x0529,0x052a,0x052b,0x052c,0x052d,0x052e,0x052f, + 0x0530,0x0531,0x0532,0x0533,0x0534,0x0535,0x0536,0x0537, + 0x0538,0x0539,0x053a,0x053b,0x053c,0x053d,0x053e,0x053f, + 0x0540,0x0541,0x0542,0x0543,0x0544,0x0545,0x0546,0x0547, + 0x0548,0x0549,0x054a,0x054b,0x054c,0x054d,0x054e,0x054f, + 0x0550,0x0551,0x0552,0x0553,0x0554,0x0555,0x0556,0x0557, + 0x0558,0x0559,0x055a,0x055b,0x055c,0x055d,0x055e,0x055f, + 0x0560,0x0531,0x0532,0x0533,0x0534,0x0535,0x0536,0x0537, + 0x0538,0x0539,0x053a,0x053b,0x053c,0x053d,0x053e,0x053f, + 0x0540,0x0541,0x0542,0x0543,0x0544,0x0545,0x0546,0x0547, + 0x0548,0x0549,0x054a,0x054b,0x054c,0x054d,0x054e,0x054f, + 0x0550,0x0551,0x0552,0x0553,0x0554,0x0555,0x0556,0x0587, + 0x0588,0x0589,0x058a,0x058b,0x058c,0x058d,0x058e,0x058f, + 0x0590,0x0591,0x0592,0x0593,0x0594,0x0595,0x0596,0x0597, + 0x0598,0x0599,0x059a,0x059b,0x059c,0x059d,0x059e,0x059f, + 0x05a0,0x05a1,0x05a2,0x05a3,0x05a4,0x05a5,0x05a6,0x05a7, + 0x05a8,0x05a9,0x05aa,0x05ab,0x05ac,0x05ad,0x05ae,0x05af, + 0x05b0,0x05b1,0x05b2,0x05b3,0x05b4,0x05b5,0x05b6,0x05b7, + 0x05b8,0x05b9,0x05ba,0x05bb,0x05bc,0x05bd,0x05be,0x05bf, + 0x05c0,0x05c1,0x05c2,0x05c3,0x05c4,0x05c5,0x05c6,0x05c7, + 0x05c8,0x05c9,0x05ca,0x05cb,0x05cc,0x05cd,0x05ce,0x05cf, + 0x05d0,0x05d1,0x05d2,0x05d3,0x05d4,0x05d5,0x05d6,0x05d7, + 0x05d8,0x05d9,0x05da,0x05db,0x05dc,0x05dd,0x05de,0x05df, + 0x05e0,0x05e1,0x05e2,0x05e3,0x05e4,0x05e5,0x05e6,0x05e7, + 0x05e8,0x05e9,0x05ea,0x05eb,0x05ec,0x05ed,0x05ee,0x05ef, + 0x05f0,0x05f1,0x05f2,0x05f3,0x05f4,0x05f5,0x05f6,0x05f7, + 0x05f8,0x05f9,0x05fa,0x05fb,0x05fc,0x05fd,0x05fe,0x05ff, + 0x0600,0x0601,0x0602,0x0603,0x0604,0x0605,0x0606,0x0607, + 0x0608,0x0609,0x060a,0x060b,0x060c,0x060d,0x060e,0x060f, + 0x0610,0x0611,0x0612,0x0613,0x0614,0x0615,0x0616,0x0617, + 0x0618,0x0619,0x061a,0x061b,0x061c,0x061d,0x061e,0x061f, + 0x0620,0x0621,0x0622,0x0623,0x0624,0x0625,0x0626,0x0627, + 0x0628,0x0629,0x062a,0x062b,0x062c,0x062d,0x062e,0x062f, + 0x0630,0x0631,0x0632,0x0633,0x0634,0x0635,0x0636,0x0637, + 0x0638,0x0639,0x063a,0x063b,0x063c,0x063d,0x063e,0x063f, + 0x0640,0x0641,0x0642,0x0643,0x0644,0x0645,0x0646,0x0647, + 0x0648,0x0649,0x064a,0x064b,0x064c,0x064d,0x064e,0x064f, + 0x0650,0x0651,0x0652,0x0653,0x0654,0x0655,0x0656,0x0657, + 0x0658,0x0659,0x065a,0x065b,0x065c,0x065d,0x065e,0x065f, + 0x0660,0x0661,0x0662,0x0663,0x0664,0x0665,0x0666,0x0667, + 0x0668,0x0669,0x066a,0x066b,0x066c,0x066d,0x066e,0x066f, + 0x0670,0x0671,0x0672,0x0673,0x0674,0x0675,0x0676,0x0677, + 0x0678,0x0679,0x067a,0x067b,0x067c,0x067d,0x067e,0x067f, + 0x0680,0x0681,0x0682,0x0683,0x0684,0x0685,0x0686,0x0687, + 0x0688,0x0689,0x068a,0x068b,0x068c,0x068d,0x068e,0x068f, + 0x0690,0x0691,0x0692,0x0693,0x0694,0x0695,0x0696,0x0697, + 0x0698,0x0699,0x069a,0x069b,0x069c,0x069d,0x069e,0x069f, + 0x06a0,0x06a1,0x06a2,0x06a3,0x06a4,0x06a5,0x06a6,0x06a7, + 0x06a8,0x06a9,0x06aa,0x06ab,0x06ac,0x06ad,0x06ae,0x06af, + 0x06b0,0x06b1,0x06b2,0x06b3,0x06b4,0x06b5,0x06b6,0x06b7, + 0x06b8,0x06b9,0x06ba,0x06bb,0x06bc,0x06bd,0x06be,0x06bf, + 0x06c0,0x06c1,0x06c2,0x06c3,0x06c4,0x06c5,0x06c6,0x06c7, + 0x06c8,0x06c9,0x06ca,0x06cb,0x06cc,0x06cd,0x06ce,0x06cf, + 0x06d0,0x06d1,0x06d2,0x06d3,0x06d4,0x06d5,0x06d6,0x06d7, + 0x06d8,0x06d9,0x06da,0x06db,0x06dc,0x06dd,0x06de,0x06df, + 0x06e0,0x06e1,0x06e2,0x06e3,0x06e4,0x06e5,0x06e6,0x06e7, + 0x06e8,0x06e9,0x06ea,0x06eb,0x06ec,0x06ed,0x06ee,0x06ef, + 0x06f0,0x06f1,0x06f2,0x06f3,0x06f4,0x06f5,0x06f6,0x06f7, + 0x06f8,0x06f9,0x06fa,0x06fb,0x06fc,0x06fd,0x06fe,0x06ff, + 0x0700,0x0701,0x0702,0x0703,0x0704,0x0705,0x0706,0x0707, + 0x0708,0x0709,0x070a,0x070b,0x070c,0x070d,0x070e,0x070f, + 0x0710,0x0711,0x0712,0x0713,0x0714,0x0715,0x0716,0x0717, + 0x0718,0x0719,0x071a,0x071b,0x071c,0x071d,0x071e,0x071f, + 0x0720,0x0721,0x0722,0x0723,0x0724,0x0725,0x0726,0x0727, + 0x0728,0x0729,0x072a,0x072b,0x072c,0x072d,0x072e,0x072f, + 0x0730,0x0731,0x0732,0x0733,0x0734,0x0735,0x0736,0x0737, + 0x0738,0x0739,0x073a,0x073b,0x073c,0x073d,0x073e,0x073f, + 0x0740,0x0741,0x0742,0x0743,0x0744,0x0745,0x0746,0x0747, + 0x0748,0x0749,0x074a,0x074b,0x074c,0x074d,0x074e,0x074f, + 0x0750,0x0751,0x0752,0x0753,0x0754,0x0755,0x0756,0x0757, + 0x0758,0x0759,0x075a,0x075b,0x075c,0x075d,0x075e,0x075f, + 0x0760,0x0761,0x0762,0x0763,0x0764,0x0765,0x0766,0x0767, + 0x0768,0x0769,0x076a,0x076b,0x076c,0x076d,0x076e,0x076f, + 0x0770,0x0771,0x0772,0x0773,0x0774,0x0775,0x0776,0x0777, + 0x0778,0x0779,0x077a,0x077b,0x077c,0x077d,0x077e,0x077f, + 0x0780,0x0781,0x0782,0x0783,0x0784,0x0785,0x0786,0x0787, + 0x0788,0x0789,0x078a,0x078b,0x078c,0x078d,0x078e,0x078f, + 0x0790,0x0791,0x0792,0x0793,0x0794,0x0795,0x0796,0x0797, + 0x0798,0x0799,0x079a,0x079b,0x079c,0x079d,0x079e,0x079f, + 0x07a0,0x07a1,0x07a2,0x07a3,0x07a4,0x07a5,0x07a6,0x07a7, + 0x07a8,0x07a9,0x07aa,0x07ab,0x07ac,0x07ad,0x07ae,0x07af, + 0x07b0,0x07b1,0x07b2,0x07b3,0x07b4,0x07b5,0x07b6,0x07b7, + 0x07b8,0x07b9,0x07ba,0x07bb,0x07bc,0x07bd,0x07be,0x07bf, + 0x07c0,0x07c1,0x07c2,0x07c3,0x07c4,0x07c5,0x07c6,0x07c7, + 0x07c8,0x07c9,0x07ca,0x07cb,0x07cc,0x07cd,0x07ce,0x07cf, + 0x07d0,0x07d1,0x07d2,0x07d3,0x07d4,0x07d5,0x07d6,0x07d7, + 0x07d8,0x07d9,0x07da,0x07db,0x07dc,0x07dd,0x07de,0x07df, + 0x07e0,0x07e1,0x07e2,0x07e3,0x07e4,0x07e5,0x07e6,0x07e7, + 0x07e8,0x07e9,0x07ea,0x07eb,0x07ec,0x07ed,0x07ee,0x07ef, + 0x07f0,0x07f1,0x07f2,0x07f3,0x07f4,0x07f5,0x07f6,0x07f7, + 0x07f8,0x07f9,0x07fa,0x07fb,0x07fc,0x07fd,0x07fe,0x07ff, + 0x0800,0x0801,0x0802,0x0803,0x0804,0x0805,0x0806,0x0807, + 0x0808,0x0809,0x080a,0x080b,0x080c,0x080d,0x080e,0x080f, + 0x0810,0x0811,0x0812,0x0813,0x0814,0x0815,0x0816,0x0817, + 0x0818,0x0819,0x081a,0x081b,0x081c,0x081d,0x081e,0x081f, + 0x0820,0x0821,0x0822,0x0823,0x0824,0x0825,0x0826,0x0827, + 0x0828,0x0829,0x082a,0x082b,0x082c,0x082d,0x082e,0x082f, + 0x0830,0x0831,0x0832,0x0833,0x0834,0x0835,0x0836,0x0837, + 0x0838,0x0839,0x083a,0x083b,0x083c,0x083d,0x083e,0x083f, + 0x0840,0x0841,0x0842,0x0843,0x0844,0x0845,0x0846,0x0847, + 0x0848,0x0849,0x084a,0x084b,0x084c,0x084d,0x084e,0x084f, + 0x0850,0x0851,0x0852,0x0853,0x0854,0x0855,0x0856,0x0857, + 0x0858,0x0859,0x085a,0x085b,0x085c,0x085d,0x085e,0x085f, + 0x0860,0x0861,0x0862,0x0863,0x0864,0x0865,0x0866,0x0867, + 0x0868,0x0869,0x086a,0x086b,0x086c,0x086d,0x086e,0x086f, + 0x0870,0x0871,0x0872,0x0873,0x0874,0x0875,0x0876,0x0877, + 0x0878,0x0879,0x087a,0x087b,0x087c,0x087d,0x087e,0x087f, + 0x0880,0x0881,0x0882,0x0883,0x0884,0x0885,0x0886,0x0887, + 0x0888,0x0889,0x088a,0x088b,0x088c,0x088d,0x088e,0x088f, + 0x0890,0x0891,0x0892,0x0893,0x0894,0x0895,0x0896,0x0897, + 0x0898,0x0899,0x089a,0x089b,0x089c,0x089d,0x089e,0x089f, + 0x08a0,0x08a1,0x08a2,0x08a3,0x08a4,0x08a5,0x08a6,0x08a7, + 0x08a8,0x08a9,0x08aa,0x08ab,0x08ac,0x08ad,0x08ae,0x08af, + 0x08b0,0x08b1,0x08b2,0x08b3,0x08b4,0x08b5,0x08b6,0x08b7, + 0x08b8,0x08b9,0x08ba,0x08bb,0x08bc,0x08bd,0x08be,0x08bf, + 0x08c0,0x08c1,0x08c2,0x08c3,0x08c4,0x08c5,0x08c6,0x08c7, + 0x08c8,0x08c9,0x08ca,0x08cb,0x08cc,0x08cd,0x08ce,0x08cf, + 0x08d0,0x08d1,0x08d2,0x08d3,0x08d4,0x08d5,0x08d6,0x08d7, + 0x08d8,0x08d9,0x08da,0x08db,0x08dc,0x08dd,0x08de,0x08df, + 0x08e0,0x08e1,0x08e2,0x08e3,0x08e4,0x08e5,0x08e6,0x08e7, + 0x08e8,0x08e9,0x08ea,0x08eb,0x08ec,0x08ed,0x08ee,0x08ef, + 0x08f0,0x08f1,0x08f2,0x08f3,0x08f4,0x08f5,0x08f6,0x08f7, + 0x08f8,0x08f9,0x08fa,0x08fb,0x08fc,0x08fd,0x08fe,0x08ff, + 0x0900,0x0901,0x0902,0x0903,0x0904,0x0905,0x0906,0x0907, + 0x0908,0x0909,0x090a,0x090b,0x090c,0x090d,0x090e,0x090f, + 0x0910,0x0911,0x0912,0x0913,0x0914,0x0915,0x0916,0x0917, + 0x0918,0x0919,0x091a,0x091b,0x091c,0x091d,0x091e,0x091f, + 0x0920,0x0921,0x0922,0x0923,0x0924,0x0925,0x0926,0x0927, + 0x0928,0x0929,0x092a,0x092b,0x092c,0x092d,0x092e,0x092f, + 0x0930,0x0931,0x0932,0x0933,0x0934,0x0935,0x0936,0x0937, + 0x0938,0x0939,0x093a,0x093b,0x093c,0x093d,0x093e,0x093f, + 0x0940,0x0941,0x0942,0x0943,0x0944,0x0945,0x0946,0x0947, + 0x0948,0x0949,0x094a,0x094b,0x094c,0x094d,0x094e,0x094f, + 0x0950,0x0951,0x0952,0x0953,0x0954,0x0955,0x0956,0x0957, + 0x0958,0x0959,0x095a,0x095b,0x095c,0x095d,0x095e,0x095f, + 0x0960,0x0961,0x0962,0x0963,0x0964,0x0965,0x0966,0x0967, + 0x0968,0x0969,0x096a,0x096b,0x096c,0x096d,0x096e,0x096f, + 0x0970,0x0971,0x0972,0x0973,0x0974,0x0975,0x0976,0x0977, + 0x0978,0x0979,0x097a,0x097b,0x097c,0x097d,0x097e,0x097f, + 0x0980,0x0981,0x0982,0x0983,0x0984,0x0985,0x0986,0x0987, + 0x0988,0x0989,0x098a,0x098b,0x098c,0x098d,0x098e,0x098f, + 0x0990,0x0991,0x0992,0x0993,0x0994,0x0995,0x0996,0x0997, + 0x0998,0x0999,0x099a,0x099b,0x099c,0x099d,0x099e,0x099f, + 0x09a0,0x09a1,0x09a2,0x09a3,0x09a4,0x09a5,0x09a6,0x09a7, + 0x09a8,0x09a9,0x09aa,0x09ab,0x09ac,0x09ad,0x09ae,0x09af, + 0x09b0,0x09b1,0x09b2,0x09b3,0x09b4,0x09b5,0x09b6,0x09b7, + 0x09b8,0x09b9,0x09ba,0x09bb,0x09bc,0x09bd,0x09be,0x09bf, + 0x09c0,0x09c1,0x09c2,0x09c3,0x09c4,0x09c5,0x09c6,0x09c7, + 0x09c8,0x09c9,0x09ca,0x09cb,0x09cc,0x09cd,0x09ce,0x09cf, + 0x09d0,0x09d1,0x09d2,0x09d3,0x09d4,0x09d5,0x09d6,0x09d7, + 0x09d8,0x09d9,0x09da,0x09db,0x09dc,0x09dd,0x09de,0x09df, + 0x09e0,0x09e1,0x09e2,0x09e3,0x09e4,0x09e5,0x09e6,0x09e7, + 0x09e8,0x09e9,0x09ea,0x09eb,0x09ec,0x09ed,0x09ee,0x09ef, + 0x09f0,0x09f1,0x09f2,0x09f3,0x09f4,0x09f5,0x09f6,0x09f7, + 0x09f8,0x09f9,0x09fa,0x09fb,0x09fc,0x09fd,0x09fe,0x09ff, + 0x0a00,0x0a01,0x0a02,0x0a03,0x0a04,0x0a05,0x0a06,0x0a07, + 0x0a08,0x0a09,0x0a0a,0x0a0b,0x0a0c,0x0a0d,0x0a0e,0x0a0f, + 0x0a10,0x0a11,0x0a12,0x0a13,0x0a14,0x0a15,0x0a16,0x0a17, + 0x0a18,0x0a19,0x0a1a,0x0a1b,0x0a1c,0x0a1d,0x0a1e,0x0a1f, + 0x0a20,0x0a21,0x0a22,0x0a23,0x0a24,0x0a25,0x0a26,0x0a27, + 0x0a28,0x0a29,0x0a2a,0x0a2b,0x0a2c,0x0a2d,0x0a2e,0x0a2f, + 0x0a30,0x0a31,0x0a32,0x0a33,0x0a34,0x0a35,0x0a36,0x0a37, + 0x0a38,0x0a39,0x0a3a,0x0a3b,0x0a3c,0x0a3d,0x0a3e,0x0a3f, + 0x0a40,0x0a41,0x0a42,0x0a43,0x0a44,0x0a45,0x0a46,0x0a47, + 0x0a48,0x0a49,0x0a4a,0x0a4b,0x0a4c,0x0a4d,0x0a4e,0x0a4f, + 0x0a50,0x0a51,0x0a52,0x0a53,0x0a54,0x0a55,0x0a56,0x0a57, + 0x0a58,0x0a59,0x0a5a,0x0a5b,0x0a5c,0x0a5d,0x0a5e,0x0a5f, + 0x0a60,0x0a61,0x0a62,0x0a63,0x0a64,0x0a65,0x0a66,0x0a67, + 0x0a68,0x0a69,0x0a6a,0x0a6b,0x0a6c,0x0a6d,0x0a6e,0x0a6f, + 0x0a70,0x0a71,0x0a72,0x0a73,0x0a74,0x0a75,0x0a76,0x0a77, + 0x0a78,0x0a79,0x0a7a,0x0a7b,0x0a7c,0x0a7d,0x0a7e,0x0a7f, + 0x0a80,0x0a81,0x0a82,0x0a83,0x0a84,0x0a85,0x0a86,0x0a87, + 0x0a88,0x0a89,0x0a8a,0x0a8b,0x0a8c,0x0a8d,0x0a8e,0x0a8f, + 0x0a90,0x0a91,0x0a92,0x0a93,0x0a94,0x0a95,0x0a96,0x0a97, + 0x0a98,0x0a99,0x0a9a,0x0a9b,0x0a9c,0x0a9d,0x0a9e,0x0a9f, + 0x0aa0,0x0aa1,0x0aa2,0x0aa3,0x0aa4,0x0aa5,0x0aa6,0x0aa7, + 0x0aa8,0x0aa9,0x0aaa,0x0aab,0x0aac,0x0aad,0x0aae,0x0aaf, + 0x0ab0,0x0ab1,0x0ab2,0x0ab3,0x0ab4,0x0ab5,0x0ab6,0x0ab7, + 0x0ab8,0x0ab9,0x0aba,0x0abb,0x0abc,0x0abd,0x0abe,0x0abf, + 0x0ac0,0x0ac1,0x0ac2,0x0ac3,0x0ac4,0x0ac5,0x0ac6,0x0ac7, + 0x0ac8,0x0ac9,0x0aca,0x0acb,0x0acc,0x0acd,0x0ace,0x0acf, + 0x0ad0,0x0ad1,0x0ad2,0x0ad3,0x0ad4,0x0ad5,0x0ad6,0x0ad7, + 0x0ad8,0x0ad9,0x0ada,0x0adb,0x0adc,0x0add,0x0ade,0x0adf, + 0x0ae0,0x0ae1,0x0ae2,0x0ae3,0x0ae4,0x0ae5,0x0ae6,0x0ae7, + 0x0ae8,0x0ae9,0x0aea,0x0aeb,0x0aec,0x0aed,0x0aee,0x0aef, + 0x0af0,0x0af1,0x0af2,0x0af3,0x0af4,0x0af5,0x0af6,0x0af7, + 0x0af8,0x0af9,0x0afa,0x0afb,0x0afc,0x0afd,0x0afe,0x0aff, + 0x0b00,0x0b01,0x0b02,0x0b03,0x0b04,0x0b05,0x0b06,0x0b07, + 0x0b08,0x0b09,0x0b0a,0x0b0b,0x0b0c,0x0b0d,0x0b0e,0x0b0f, + 0x0b10,0x0b11,0x0b12,0x0b13,0x0b14,0x0b15,0x0b16,0x0b17, + 0x0b18,0x0b19,0x0b1a,0x0b1b,0x0b1c,0x0b1d,0x0b1e,0x0b1f, + 0x0b20,0x0b21,0x0b22,0x0b23,0x0b24,0x0b25,0x0b26,0x0b27, + 0x0b28,0x0b29,0x0b2a,0x0b2b,0x0b2c,0x0b2d,0x0b2e,0x0b2f, + 0x0b30,0x0b31,0x0b32,0x0b33,0x0b34,0x0b35,0x0b36,0x0b37, + 0x0b38,0x0b39,0x0b3a,0x0b3b,0x0b3c,0x0b3d,0x0b3e,0x0b3f, + 0x0b40,0x0b41,0x0b42,0x0b43,0x0b44,0x0b45,0x0b46,0x0b47, + 0x0b48,0x0b49,0x0b4a,0x0b4b,0x0b4c,0x0b4d,0x0b4e,0x0b4f, + 0x0b50,0x0b51,0x0b52,0x0b53,0x0b54,0x0b55,0x0b56,0x0b57, + 0x0b58,0x0b59,0x0b5a,0x0b5b,0x0b5c,0x0b5d,0x0b5e,0x0b5f, + 0x0b60,0x0b61,0x0b62,0x0b63,0x0b64,0x0b65,0x0b66,0x0b67, + 0x0b68,0x0b69,0x0b6a,0x0b6b,0x0b6c,0x0b6d,0x0b6e,0x0b6f, + 0x0b70,0x0b71,0x0b72,0x0b73,0x0b74,0x0b75,0x0b76,0x0b77, + 0x0b78,0x0b79,0x0b7a,0x0b7b,0x0b7c,0x0b7d,0x0b7e,0x0b7f, + 0x0b80,0x0b81,0x0b82,0x0b83,0x0b84,0x0b85,0x0b86,0x0b87, + 0x0b88,0x0b89,0x0b8a,0x0b8b,0x0b8c,0x0b8d,0x0b8e,0x0b8f, + 0x0b90,0x0b91,0x0b92,0x0b93,0x0b94,0x0b95,0x0b96,0x0b97, + 0x0b98,0x0b99,0x0b9a,0x0b9b,0x0b9c,0x0b9d,0x0b9e,0x0b9f, + 0x0ba0,0x0ba1,0x0ba2,0x0ba3,0x0ba4,0x0ba5,0x0ba6,0x0ba7, + 0x0ba8,0x0ba9,0x0baa,0x0bab,0x0bac,0x0bad,0x0bae,0x0baf, + 0x0bb0,0x0bb1,0x0bb2,0x0bb3,0x0bb4,0x0bb5,0x0bb6,0x0bb7, + 0x0bb8,0x0bb9,0x0bba,0x0bbb,0x0bbc,0x0bbd,0x0bbe,0x0bbf, + 0x0bc0,0x0bc1,0x0bc2,0x0bc3,0x0bc4,0x0bc5,0x0bc6,0x0bc7, + 0x0bc8,0x0bc9,0x0bca,0x0bcb,0x0bcc,0x0bcd,0x0bce,0x0bcf, + 0x0bd0,0x0bd1,0x0bd2,0x0bd3,0x0bd4,0x0bd5,0x0bd6,0x0bd7, + 0x0bd8,0x0bd9,0x0bda,0x0bdb,0x0bdc,0x0bdd,0x0bde,0x0bdf, + 0x0be0,0x0be1,0x0be2,0x0be3,0x0be4,0x0be5,0x0be6,0x0be7, + 0x0be8,0x0be9,0x0bea,0x0beb,0x0bec,0x0bed,0x0bee,0x0bef, + 0x0bf0,0x0bf1,0x0bf2,0x0bf3,0x0bf4,0x0bf5,0x0bf6,0x0bf7, + 0x0bf8,0x0bf9,0x0bfa,0x0bfb,0x0bfc,0x0bfd,0x0bfe,0x0bff, + 0x0c00,0x0c01,0x0c02,0x0c03,0x0c04,0x0c05,0x0c06,0x0c07, + 0x0c08,0x0c09,0x0c0a,0x0c0b,0x0c0c,0x0c0d,0x0c0e,0x0c0f, + 0x0c10,0x0c11,0x0c12,0x0c13,0x0c14,0x0c15,0x0c16,0x0c17, + 0x0c18,0x0c19,0x0c1a,0x0c1b,0x0c1c,0x0c1d,0x0c1e,0x0c1f, + 0x0c20,0x0c21,0x0c22,0x0c23,0x0c24,0x0c25,0x0c26,0x0c27, + 0x0c28,0x0c29,0x0c2a,0x0c2b,0x0c2c,0x0c2d,0x0c2e,0x0c2f, + 0x0c30,0x0c31,0x0c32,0x0c33,0x0c34,0x0c35,0x0c36,0x0c37, + 0x0c38,0x0c39,0x0c3a,0x0c3b,0x0c3c,0x0c3d,0x0c3e,0x0c3f, + 0x0c40,0x0c41,0x0c42,0x0c43,0x0c44,0x0c45,0x0c46,0x0c47, + 0x0c48,0x0c49,0x0c4a,0x0c4b,0x0c4c,0x0c4d,0x0c4e,0x0c4f, + 0x0c50,0x0c51,0x0c52,0x0c53,0x0c54,0x0c55,0x0c56,0x0c57, + 0x0c58,0x0c59,0x0c5a,0x0c5b,0x0c5c,0x0c5d,0x0c5e,0x0c5f, + 0x0c60,0x0c61,0x0c62,0x0c63,0x0c64,0x0c65,0x0c66,0x0c67, + 0x0c68,0x0c69,0x0c6a,0x0c6b,0x0c6c,0x0c6d,0x0c6e,0x0c6f, + 0x0c70,0x0c71,0x0c72,0x0c73,0x0c74,0x0c75,0x0c76,0x0c77, + 0x0c78,0x0c79,0x0c7a,0x0c7b,0x0c7c,0x0c7d,0x0c7e,0x0c7f, + 0x0c80,0x0c81,0x0c82,0x0c83,0x0c84,0x0c85,0x0c86,0x0c87, + 0x0c88,0x0c89,0x0c8a,0x0c8b,0x0c8c,0x0c8d,0x0c8e,0x0c8f, + 0x0c90,0x0c91,0x0c92,0x0c93,0x0c94,0x0c95,0x0c96,0x0c97, + 0x0c98,0x0c99,0x0c9a,0x0c9b,0x0c9c,0x0c9d,0x0c9e,0x0c9f, + 0x0ca0,0x0ca1,0x0ca2,0x0ca3,0x0ca4,0x0ca5,0x0ca6,0x0ca7, + 0x0ca8,0x0ca9,0x0caa,0x0cab,0x0cac,0x0cad,0x0cae,0x0caf, + 0x0cb0,0x0cb1,0x0cb2,0x0cb3,0x0cb4,0x0cb5,0x0cb6,0x0cb7, + 0x0cb8,0x0cb9,0x0cba,0x0cbb,0x0cbc,0x0cbd,0x0cbe,0x0cbf, + 0x0cc0,0x0cc1,0x0cc2,0x0cc3,0x0cc4,0x0cc5,0x0cc6,0x0cc7, + 0x0cc8,0x0cc9,0x0cca,0x0ccb,0x0ccc,0x0ccd,0x0cce,0x0ccf, + 0x0cd0,0x0cd1,0x0cd2,0x0cd3,0x0cd4,0x0cd5,0x0cd6,0x0cd7, + 0x0cd8,0x0cd9,0x0cda,0x0cdb,0x0cdc,0x0cdd,0x0cde,0x0cdf, + 0x0ce0,0x0ce1,0x0ce2,0x0ce3,0x0ce4,0x0ce5,0x0ce6,0x0ce7, + 0x0ce8,0x0ce9,0x0cea,0x0ceb,0x0cec,0x0ced,0x0cee,0x0cef, + 0x0cf0,0x0cf1,0x0cf2,0x0cf3,0x0cf4,0x0cf5,0x0cf6,0x0cf7, + 0x0cf8,0x0cf9,0x0cfa,0x0cfb,0x0cfc,0x0cfd,0x0cfe,0x0cff, + 0x0d00,0x0d01,0x0d02,0x0d03,0x0d04,0x0d05,0x0d06,0x0d07, + 0x0d08,0x0d09,0x0d0a,0x0d0b,0x0d0c,0x0d0d,0x0d0e,0x0d0f, + 0x0d10,0x0d11,0x0d12,0x0d13,0x0d14,0x0d15,0x0d16,0x0d17, + 0x0d18,0x0d19,0x0d1a,0x0d1b,0x0d1c,0x0d1d,0x0d1e,0x0d1f, + 0x0d20,0x0d21,0x0d22,0x0d23,0x0d24,0x0d25,0x0d26,0x0d27, + 0x0d28,0x0d29,0x0d2a,0x0d2b,0x0d2c,0x0d2d,0x0d2e,0x0d2f, + 0x0d30,0x0d31,0x0d32,0x0d33,0x0d34,0x0d35,0x0d36,0x0d37, + 0x0d38,0x0d39,0x0d3a,0x0d3b,0x0d3c,0x0d3d,0x0d3e,0x0d3f, + 0x0d40,0x0d41,0x0d42,0x0d43,0x0d44,0x0d45,0x0d46,0x0d47, + 0x0d48,0x0d49,0x0d4a,0x0d4b,0x0d4c,0x0d4d,0x0d4e,0x0d4f, + 0x0d50,0x0d51,0x0d52,0x0d53,0x0d54,0x0d55,0x0d56,0x0d57, + 0x0d58,0x0d59,0x0d5a,0x0d5b,0x0d5c,0x0d5d,0x0d5e,0x0d5f, + 0x0d60,0x0d61,0x0d62,0x0d63,0x0d64,0x0d65,0x0d66,0x0d67, + 0x0d68,0x0d69,0x0d6a,0x0d6b,0x0d6c,0x0d6d,0x0d6e,0x0d6f, + 0x0d70,0x0d71,0x0d72,0x0d73,0x0d74,0x0d75,0x0d76,0x0d77, + 0x0d78,0x0d79,0x0d7a,0x0d7b,0x0d7c,0x0d7d,0x0d7e,0x0d7f, + 0x0d80,0x0d81,0x0d82,0x0d83,0x0d84,0x0d85,0x0d86,0x0d87, + 0x0d88,0x0d89,0x0d8a,0x0d8b,0x0d8c,0x0d8d,0x0d8e,0x0d8f, + 0x0d90,0x0d91,0x0d92,0x0d93,0x0d94,0x0d95,0x0d96,0x0d97, + 0x0d98,0x0d99,0x0d9a,0x0d9b,0x0d9c,0x0d9d,0x0d9e,0x0d9f, + 0x0da0,0x0da1,0x0da2,0x0da3,0x0da4,0x0da5,0x0da6,0x0da7, + 0x0da8,0x0da9,0x0daa,0x0dab,0x0dac,0x0dad,0x0dae,0x0daf, + 0x0db0,0x0db1,0x0db2,0x0db3,0x0db4,0x0db5,0x0db6,0x0db7, + 0x0db8,0x0db9,0x0dba,0x0dbb,0x0dbc,0x0dbd,0x0dbe,0x0dbf, + 0x0dc0,0x0dc1,0x0dc2,0x0dc3,0x0dc4,0x0dc5,0x0dc6,0x0dc7, + 0x0dc8,0x0dc9,0x0dca,0x0dcb,0x0dcc,0x0dcd,0x0dce,0x0dcf, + 0x0dd0,0x0dd1,0x0dd2,0x0dd3,0x0dd4,0x0dd5,0x0dd6,0x0dd7, + 0x0dd8,0x0dd9,0x0dda,0x0ddb,0x0ddc,0x0ddd,0x0dde,0x0ddf, + 0x0de0,0x0de1,0x0de2,0x0de3,0x0de4,0x0de5,0x0de6,0x0de7, + 0x0de8,0x0de9,0x0dea,0x0deb,0x0dec,0x0ded,0x0dee,0x0def, + 0x0df0,0x0df1,0x0df2,0x0df3,0x0df4,0x0df5,0x0df6,0x0df7, + 0x0df8,0x0df9,0x0dfa,0x0dfb,0x0dfc,0x0dfd,0x0dfe,0x0dff, + 0x0e00,0x0e01,0x0e02,0x0e03,0x0e04,0x0e05,0x0e06,0x0e07, + 0x0e08,0x0e09,0x0e0a,0x0e0b,0x0e0c,0x0e0d,0x0e0e,0x0e0f, + 0x0e10,0x0e11,0x0e12,0x0e13,0x0e14,0x0e15,0x0e16,0x0e17, + 0x0e18,0x0e19,0x0e1a,0x0e1b,0x0e1c,0x0e1d,0x0e1e,0x0e1f, + 0x0e20,0x0e21,0x0e22,0x0e23,0x0e24,0x0e25,0x0e26,0x0e27, + 0x0e28,0x0e29,0x0e2a,0x0e2b,0x0e2c,0x0e2d,0x0e2e,0x0e2f, + 0x0e30,0x0e31,0x0e32,0x0e33,0x0e34,0x0e35,0x0e36,0x0e37, + 0x0e38,0x0e39,0x0e3a,0x0e3b,0x0e3c,0x0e3d,0x0e3e,0x0e3f, + 0x0e40,0x0e41,0x0e42,0x0e43,0x0e44,0x0e45,0x0e46,0x0e47, + 0x0e48,0x0e49,0x0e4a,0x0e4b,0x0e4c,0x0e4d,0x0e4e,0x0e4f, + 0x0e50,0x0e51,0x0e52,0x0e53,0x0e54,0x0e55,0x0e56,0x0e57, + 0x0e58,0x0e59,0x0e5a,0x0e5b,0x0e5c,0x0e5d,0x0e5e,0x0e5f, + 0x0e60,0x0e61,0x0e62,0x0e63,0x0e64,0x0e65,0x0e66,0x0e67, + 0x0e68,0x0e69,0x0e6a,0x0e6b,0x0e6c,0x0e6d,0x0e6e,0x0e6f, + 0x0e70,0x0e71,0x0e72,0x0e73,0x0e74,0x0e75,0x0e76,0x0e77, + 0x0e78,0x0e79,0x0e7a,0x0e7b,0x0e7c,0x0e7d,0x0e7e,0x0e7f, + 0x0e80,0x0e81,0x0e82,0x0e83,0x0e84,0x0e85,0x0e86,0x0e87, + 0x0e88,0x0e89,0x0e8a,0x0e8b,0x0e8c,0x0e8d,0x0e8e,0x0e8f, + 0x0e90,0x0e91,0x0e92,0x0e93,0x0e94,0x0e95,0x0e96,0x0e97, + 0x0e98,0x0e99,0x0e9a,0x0e9b,0x0e9c,0x0e9d,0x0e9e,0x0e9f, + 0x0ea0,0x0ea1,0x0ea2,0x0ea3,0x0ea4,0x0ea5,0x0ea6,0x0ea7, + 0x0ea8,0x0ea9,0x0eaa,0x0eab,0x0eac,0x0ead,0x0eae,0x0eaf, + 0x0eb0,0x0eb1,0x0eb2,0x0eb3,0x0eb4,0x0eb5,0x0eb6,0x0eb7, + 0x0eb8,0x0eb9,0x0eba,0x0ebb,0x0ebc,0x0ebd,0x0ebe,0x0ebf, + 0x0ec0,0x0ec1,0x0ec2,0x0ec3,0x0ec4,0x0ec5,0x0ec6,0x0ec7, + 0x0ec8,0x0ec9,0x0eca,0x0ecb,0x0ecc,0x0ecd,0x0ece,0x0ecf, + 0x0ed0,0x0ed1,0x0ed2,0x0ed3,0x0ed4,0x0ed5,0x0ed6,0x0ed7, + 0x0ed8,0x0ed9,0x0eda,0x0edb,0x0edc,0x0edd,0x0ede,0x0edf, + 0x0ee0,0x0ee1,0x0ee2,0x0ee3,0x0ee4,0x0ee5,0x0ee6,0x0ee7, + 0x0ee8,0x0ee9,0x0eea,0x0eeb,0x0eec,0x0eed,0x0eee,0x0eef, + 0x0ef0,0x0ef1,0x0ef2,0x0ef3,0x0ef4,0x0ef5,0x0ef6,0x0ef7, + 0x0ef8,0x0ef9,0x0efa,0x0efb,0x0efc,0x0efd,0x0efe,0x0eff, + 0x0f00,0x0f01,0x0f02,0x0f03,0x0f04,0x0f05,0x0f06,0x0f07, + 0x0f08,0x0f09,0x0f0a,0x0f0b,0x0f0c,0x0f0d,0x0f0e,0x0f0f, + 0x0f10,0x0f11,0x0f12,0x0f13,0x0f14,0x0f15,0x0f16,0x0f17, + 0x0f18,0x0f19,0x0f1a,0x0f1b,0x0f1c,0x0f1d,0x0f1e,0x0f1f, + 0x0f20,0x0f21,0x0f22,0x0f23,0x0f24,0x0f25,0x0f26,0x0f27, + 0x0f28,0x0f29,0x0f2a,0x0f2b,0x0f2c,0x0f2d,0x0f2e,0x0f2f, + 0x0f30,0x0f31,0x0f32,0x0f33,0x0f34,0x0f35,0x0f36,0x0f37, + 0x0f38,0x0f39,0x0f3a,0x0f3b,0x0f3c,0x0f3d,0x0f3e,0x0f3f, + 0x0f40,0x0f41,0x0f42,0x0f43,0x0f44,0x0f45,0x0f46,0x0f47, + 0x0f48,0x0f49,0x0f4a,0x0f4b,0x0f4c,0x0f4d,0x0f4e,0x0f4f, + 0x0f50,0x0f51,0x0f52,0x0f53,0x0f54,0x0f55,0x0f56,0x0f57, + 0x0f58,0x0f59,0x0f5a,0x0f5b,0x0f5c,0x0f5d,0x0f5e,0x0f5f, + 0x0f60,0x0f61,0x0f62,0x0f63,0x0f64,0x0f65,0x0f66,0x0f67, + 0x0f68,0x0f69,0x0f6a,0x0f6b,0x0f6c,0x0f6d,0x0f6e,0x0f6f, + 0x0f70,0x0f71,0x0f72,0x0f73,0x0f74,0x0f75,0x0f76,0x0f77, + 0x0f78,0x0f79,0x0f7a,0x0f7b,0x0f7c,0x0f7d,0x0f7e,0x0f7f, + 0x0f80,0x0f81,0x0f82,0x0f83,0x0f84,0x0f85,0x0f86,0x0f87, + 0x0f88,0x0f89,0x0f8a,0x0f8b,0x0f8c,0x0f8d,0x0f8e,0x0f8f, + 0x0f90,0x0f91,0x0f92,0x0f93,0x0f94,0x0f95,0x0f96,0x0f97, + 0x0f98,0x0f99,0x0f9a,0x0f9b,0x0f9c,0x0f9d,0x0f9e,0x0f9f, + 0x0fa0,0x0fa1,0x0fa2,0x0fa3,0x0fa4,0x0fa5,0x0fa6,0x0fa7, + 0x0fa8,0x0fa9,0x0faa,0x0fab,0x0fac,0x0fad,0x0fae,0x0faf, + 0x0fb0,0x0fb1,0x0fb2,0x0fb3,0x0fb4,0x0fb5,0x0fb6,0x0fb7, + 0x0fb8,0x0fb9,0x0fba,0x0fbb,0x0fbc,0x0fbd,0x0fbe,0x0fbf, + 0x0fc0,0x0fc1,0x0fc2,0x0fc3,0x0fc4,0x0fc5,0x0fc6,0x0fc7, + 0x0fc8,0x0fc9,0x0fca,0x0fcb,0x0fcc,0x0fcd,0x0fce,0x0fcf, + 0x0fd0,0x0fd1,0x0fd2,0x0fd3,0x0fd4,0x0fd5,0x0fd6,0x0fd7, + 0x0fd8,0x0fd9,0x0fda,0x0fdb,0x0fdc,0x0fdd,0x0fde,0x0fdf, + 0x0fe0,0x0fe1,0x0fe2,0x0fe3,0x0fe4,0x0fe5,0x0fe6,0x0fe7, + 0x0fe8,0x0fe9,0x0fea,0x0feb,0x0fec,0x0fed,0x0fee,0x0fef, + 0x0ff0,0x0ff1,0x0ff2,0x0ff3,0x0ff4,0x0ff5,0x0ff6,0x0ff7, + 0x0ff8,0x0ff9,0x0ffa,0x0ffb,0x0ffc,0x0ffd,0x0ffe,0x0fff, + 0x1000,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007, + 0x1008,0x1009,0x100a,0x100b,0x100c,0x100d,0x100e,0x100f, + 0x1010,0x1011,0x1012,0x1013,0x1014,0x1015,0x1016,0x1017, + 0x1018,0x1019,0x101a,0x101b,0x101c,0x101d,0x101e,0x101f, + 0x1020,0x1021,0x1022,0x1023,0x1024,0x1025,0x1026,0x1027, + 0x1028,0x1029,0x102a,0x102b,0x102c,0x102d,0x102e,0x102f, + 0x1030,0x1031,0x1032,0x1033,0x1034,0x1035,0x1036,0x1037, + 0x1038,0x1039,0x103a,0x103b,0x103c,0x103d,0x103e,0x103f, + 0x1040,0x1041,0x1042,0x1043,0x1044,0x1045,0x1046,0x1047, + 0x1048,0x1049,0x104a,0x104b,0x104c,0x104d,0x104e,0x104f, + 0x1050,0x1051,0x1052,0x1053,0x1054,0x1055,0x1056,0x1057, + 0x1058,0x1059,0x105a,0x105b,0x105c,0x105d,0x105e,0x105f, + 0x1060,0x1061,0x1062,0x1063,0x1064,0x1065,0x1066,0x1067, + 0x1068,0x1069,0x106a,0x106b,0x106c,0x106d,0x106e,0x106f, + 0x1070,0x1071,0x1072,0x1073,0x1074,0x1075,0x1076,0x1077, + 0x1078,0x1079,0x107a,0x107b,0x107c,0x107d,0x107e,0x107f, + 0x1080,0x1081,0x1082,0x1083,0x1084,0x1085,0x1086,0x1087, + 0x1088,0x1089,0x108a,0x108b,0x108c,0x108d,0x108e,0x108f, + 0x1090,0x1091,0x1092,0x1093,0x1094,0x1095,0x1096,0x1097, + 0x1098,0x1099,0x109a,0x109b,0x109c,0x109d,0x109e,0x109f, + 0x10a0,0x10a1,0x10a2,0x10a3,0x10a4,0x10a5,0x10a6,0x10a7, + 0x10a8,0x10a9,0x10aa,0x10ab,0x10ac,0x10ad,0x10ae,0x10af, + 0x10b0,0x10b1,0x10b2,0x10b3,0x10b4,0x10b5,0x10b6,0x10b7, + 0x10b8,0x10b9,0x10ba,0x10bb,0x10bc,0x10bd,0x10be,0x10bf, + 0x10c0,0x10c1,0x10c2,0x10c3,0x10c4,0x10c5,0x10c6,0x10c7, + 0x10c8,0x10c9,0x10ca,0x10cb,0x10cc,0x10cd,0x10ce,0x10cf, + 0x10d0,0x10d1,0x10d2,0x10d3,0x10d4,0x10d5,0x10d6,0x10d7, + 0x10d8,0x10d9,0x10da,0x10db,0x10dc,0x10dd,0x10de,0x10df, + 0x10e0,0x10e1,0x10e2,0x10e3,0x10e4,0x10e5,0x10e6,0x10e7, + 0x10e8,0x10e9,0x10ea,0x10eb,0x10ec,0x10ed,0x10ee,0x10ef, + 0x10f0,0x10f1,0x10f2,0x10f3,0x10f4,0x10f5,0x10f6,0x10f7, + 0x10f8,0x10f9,0x10fa,0x10fb,0x10fc,0x10fd,0x10fe,0x10ff, + 0x1100,0x1101,0x1102,0x1103,0x1104,0x1105,0x1106,0x1107, + 0x1108,0x1109,0x110a,0x110b,0x110c,0x110d,0x110e,0x110f, + 0x1110,0x1111,0x1112,0x1113,0x1114,0x1115,0x1116,0x1117, + 0x1118,0x1119,0x111a,0x111b,0x111c,0x111d,0x111e,0x111f, + 0x1120,0x1121,0x1122,0x1123,0x1124,0x1125,0x1126,0x1127, + 0x1128,0x1129,0x112a,0x112b,0x112c,0x112d,0x112e,0x112f, + 0x1130,0x1131,0x1132,0x1133,0x1134,0x1135,0x1136,0x1137, + 0x1138,0x1139,0x113a,0x113b,0x113c,0x113d,0x113e,0x113f, + 0x1140,0x1141,0x1142,0x1143,0x1144,0x1145,0x1146,0x1147, + 0x1148,0x1149,0x114a,0x114b,0x114c,0x114d,0x114e,0x114f, + 0x1150,0x1151,0x1152,0x1153,0x1154,0x1155,0x1156,0x1157, + 0x1158,0x1159,0x115a,0x115b,0x115c,0x115d,0x115e,0x115f, + 0x1160,0x1161,0x1162,0x1163,0x1164,0x1165,0x1166,0x1167, + 0x1168,0x1169,0x116a,0x116b,0x116c,0x116d,0x116e,0x116f, + 0x1170,0x1171,0x1172,0x1173,0x1174,0x1175,0x1176,0x1177, + 0x1178,0x1179,0x117a,0x117b,0x117c,0x117d,0x117e,0x117f, + 0x1180,0x1181,0x1182,0x1183,0x1184,0x1185,0x1186,0x1187, + 0x1188,0x1189,0x118a,0x118b,0x118c,0x118d,0x118e,0x118f, + 0x1190,0x1191,0x1192,0x1193,0x1194,0x1195,0x1196,0x1197, + 0x1198,0x1199,0x119a,0x119b,0x119c,0x119d,0x119e,0x119f, + 0x11a0,0x11a1,0x11a2,0x11a3,0x11a4,0x11a5,0x11a6,0x11a7, + 0x11a8,0x11a9,0x11aa,0x11ab,0x11ac,0x11ad,0x11ae,0x11af, + 0x11b0,0x11b1,0x11b2,0x11b3,0x11b4,0x11b5,0x11b6,0x11b7, + 0x11b8,0x11b9,0x11ba,0x11bb,0x11bc,0x11bd,0x11be,0x11bf, + 0x11c0,0x11c1,0x11c2,0x11c3,0x11c4,0x11c5,0x11c6,0x11c7, + 0x11c8,0x11c9,0x11ca,0x11cb,0x11cc,0x11cd,0x11ce,0x11cf, + 0x11d0,0x11d1,0x11d2,0x11d3,0x11d4,0x11d5,0x11d6,0x11d7, + 0x11d8,0x11d9,0x11da,0x11db,0x11dc,0x11dd,0x11de,0x11df, + 0x11e0,0x11e1,0x11e2,0x11e3,0x11e4,0x11e5,0x11e6,0x11e7, + 0x11e8,0x11e9,0x11ea,0x11eb,0x11ec,0x11ed,0x11ee,0x11ef, + 0x11f0,0x11f1,0x11f2,0x11f3,0x11f4,0x11f5,0x11f6,0x11f7, + 0x11f8,0x11f9,0x11fa,0x11fb,0x11fc,0x11fd,0x11fe,0x11ff, + 0x1200,0x1201,0x1202,0x1203,0x1204,0x1205,0x1206,0x1207, + 0x1208,0x1209,0x120a,0x120b,0x120c,0x120d,0x120e,0x120f, + 0x1210,0x1211,0x1212,0x1213,0x1214,0x1215,0x1216,0x1217, + 0x1218,0x1219,0x121a,0x121b,0x121c,0x121d,0x121e,0x121f, + 0x1220,0x1221,0x1222,0x1223,0x1224,0x1225,0x1226,0x1227, + 0x1228,0x1229,0x122a,0x122b,0x122c,0x122d,0x122e,0x122f, + 0x1230,0x1231,0x1232,0x1233,0x1234,0x1235,0x1236,0x1237, + 0x1238,0x1239,0x123a,0x123b,0x123c,0x123d,0x123e,0x123f, + 0x1240,0x1241,0x1242,0x1243,0x1244,0x1245,0x1246,0x1247, + 0x1248,0x1249,0x124a,0x124b,0x124c,0x124d,0x124e,0x124f, + 0x1250,0x1251,0x1252,0x1253,0x1254,0x1255,0x1256,0x1257, + 0x1258,0x1259,0x125a,0x125b,0x125c,0x125d,0x125e,0x125f, + 0x1260,0x1261,0x1262,0x1263,0x1264,0x1265,0x1266,0x1267, + 0x1268,0x1269,0x126a,0x126b,0x126c,0x126d,0x126e,0x126f, + 0x1270,0x1271,0x1272,0x1273,0x1274,0x1275,0x1276,0x1277, + 0x1278,0x1279,0x127a,0x127b,0x127c,0x127d,0x127e,0x127f, + 0x1280,0x1281,0x1282,0x1283,0x1284,0x1285,0x1286,0x1287, + 0x1288,0x1289,0x128a,0x128b,0x128c,0x128d,0x128e,0x128f, + 0x1290,0x1291,0x1292,0x1293,0x1294,0x1295,0x1296,0x1297, + 0x1298,0x1299,0x129a,0x129b,0x129c,0x129d,0x129e,0x129f, + 0x12a0,0x12a1,0x12a2,0x12a3,0x12a4,0x12a5,0x12a6,0x12a7, + 0x12a8,0x12a9,0x12aa,0x12ab,0x12ac,0x12ad,0x12ae,0x12af, + 0x12b0,0x12b1,0x12b2,0x12b3,0x12b4,0x12b5,0x12b6,0x12b7, + 0x12b8,0x12b9,0x12ba,0x12bb,0x12bc,0x12bd,0x12be,0x12bf, + 0x12c0,0x12c1,0x12c2,0x12c3,0x12c4,0x12c5,0x12c6,0x12c7, + 0x12c8,0x12c9,0x12ca,0x12cb,0x12cc,0x12cd,0x12ce,0x12cf, + 0x12d0,0x12d1,0x12d2,0x12d3,0x12d4,0x12d5,0x12d6,0x12d7, + 0x12d8,0x12d9,0x12da,0x12db,0x12dc,0x12dd,0x12de,0x12df, + 0x12e0,0x12e1,0x12e2,0x12e3,0x12e4,0x12e5,0x12e6,0x12e7, + 0x12e8,0x12e9,0x12ea,0x12eb,0x12ec,0x12ed,0x12ee,0x12ef, + 0x12f0,0x12f1,0x12f2,0x12f3,0x12f4,0x12f5,0x12f6,0x12f7, + 0x12f8,0x12f9,0x12fa,0x12fb,0x12fc,0x12fd,0x12fe,0x12ff, + 0x1300,0x1301,0x1302,0x1303,0x1304,0x1305,0x1306,0x1307, + 0x1308,0x1309,0x130a,0x130b,0x130c,0x130d,0x130e,0x130f, + 0x1310,0x1311,0x1312,0x1313,0x1314,0x1315,0x1316,0x1317, + 0x1318,0x1319,0x131a,0x131b,0x131c,0x131d,0x131e,0x131f, + 0x1320,0x1321,0x1322,0x1323,0x1324,0x1325,0x1326,0x1327, + 0x1328,0x1329,0x132a,0x132b,0x132c,0x132d,0x132e,0x132f, + 0x1330,0x1331,0x1332,0x1333,0x1334,0x1335,0x1336,0x1337, + 0x1338,0x1339,0x133a,0x133b,0x133c,0x133d,0x133e,0x133f, + 0x1340,0x1341,0x1342,0x1343,0x1344,0x1345,0x1346,0x1347, + 0x1348,0x1349,0x134a,0x134b,0x134c,0x134d,0x134e,0x134f, + 0x1350,0x1351,0x1352,0x1353,0x1354,0x1355,0x1356,0x1357, + 0x1358,0x1359,0x135a,0x135b,0x135c,0x135d,0x135e,0x135f, + 0x1360,0x1361,0x1362,0x1363,0x1364,0x1365,0x1366,0x1367, + 0x1368,0x1369,0x136a,0x136b,0x136c,0x136d,0x136e,0x136f, + 0x1370,0x1371,0x1372,0x1373,0x1374,0x1375,0x1376,0x1377, + 0x1378,0x1379,0x137a,0x137b,0x137c,0x137d,0x137e,0x137f, + 0x1380,0x1381,0x1382,0x1383,0x1384,0x1385,0x1386,0x1387, + 0x1388,0x1389,0x138a,0x138b,0x138c,0x138d,0x138e,0x138f, + 0x1390,0x1391,0x1392,0x1393,0x1394,0x1395,0x1396,0x1397, + 0x1398,0x1399,0x139a,0x139b,0x139c,0x139d,0x139e,0x139f, + 0x13a0,0x13a1,0x13a2,0x13a3,0x13a4,0x13a5,0x13a6,0x13a7, + 0x13a8,0x13a9,0x13aa,0x13ab,0x13ac,0x13ad,0x13ae,0x13af, + 0x13b0,0x13b1,0x13b2,0x13b3,0x13b4,0x13b5,0x13b6,0x13b7, + 0x13b8,0x13b9,0x13ba,0x13bb,0x13bc,0x13bd,0x13be,0x13bf, + 0x13c0,0x13c1,0x13c2,0x13c3,0x13c4,0x13c5,0x13c6,0x13c7, + 0x13c8,0x13c9,0x13ca,0x13cb,0x13cc,0x13cd,0x13ce,0x13cf, + 0x13d0,0x13d1,0x13d2,0x13d3,0x13d4,0x13d5,0x13d6,0x13d7, + 0x13d8,0x13d9,0x13da,0x13db,0x13dc,0x13dd,0x13de,0x13df, + 0x13e0,0x13e1,0x13e2,0x13e3,0x13e4,0x13e5,0x13e6,0x13e7, + 0x13e8,0x13e9,0x13ea,0x13eb,0x13ec,0x13ed,0x13ee,0x13ef, + 0x13f0,0x13f1,0x13f2,0x13f3,0x13f4,0x13f5,0x13f6,0x13f7, + 0x13f8,0x13f9,0x13fa,0x13fb,0x13fc,0x13fd,0x13fe,0x13ff, + 0x1400,0x1401,0x1402,0x1403,0x1404,0x1405,0x1406,0x1407, + 0x1408,0x1409,0x140a,0x140b,0x140c,0x140d,0x140e,0x140f, + 0x1410,0x1411,0x1412,0x1413,0x1414,0x1415,0x1416,0x1417, + 0x1418,0x1419,0x141a,0x141b,0x141c,0x141d,0x141e,0x141f, + 0x1420,0x1421,0x1422,0x1423,0x1424,0x1425,0x1426,0x1427, + 0x1428,0x1429,0x142a,0x142b,0x142c,0x142d,0x142e,0x142f, + 0x1430,0x1431,0x1432,0x1433,0x1434,0x1435,0x1436,0x1437, + 0x1438,0x1439,0x143a,0x143b,0x143c,0x143d,0x143e,0x143f, + 0x1440,0x1441,0x1442,0x1443,0x1444,0x1445,0x1446,0x1447, + 0x1448,0x1449,0x144a,0x144b,0x144c,0x144d,0x144e,0x144f, + 0x1450,0x1451,0x1452,0x1453,0x1454,0x1455,0x1456,0x1457, + 0x1458,0x1459,0x145a,0x145b,0x145c,0x145d,0x145e,0x145f, + 0x1460,0x1461,0x1462,0x1463,0x1464,0x1465,0x1466,0x1467, + 0x1468,0x1469,0x146a,0x146b,0x146c,0x146d,0x146e,0x146f, + 0x1470,0x1471,0x1472,0x1473,0x1474,0x1475,0x1476,0x1477, + 0x1478,0x1479,0x147a,0x147b,0x147c,0x147d,0x147e,0x147f, + 0x1480,0x1481,0x1482,0x1483,0x1484,0x1485,0x1486,0x1487, + 0x1488,0x1489,0x148a,0x148b,0x148c,0x148d,0x148e,0x148f, + 0x1490,0x1491,0x1492,0x1493,0x1494,0x1495,0x1496,0x1497, + 0x1498,0x1499,0x149a,0x149b,0x149c,0x149d,0x149e,0x149f, + 0x14a0,0x14a1,0x14a2,0x14a3,0x14a4,0x14a5,0x14a6,0x14a7, + 0x14a8,0x14a9,0x14aa,0x14ab,0x14ac,0x14ad,0x14ae,0x14af, + 0x14b0,0x14b1,0x14b2,0x14b3,0x14b4,0x14b5,0x14b6,0x14b7, + 0x14b8,0x14b9,0x14ba,0x14bb,0x14bc,0x14bd,0x14be,0x14bf, + 0x14c0,0x14c1,0x14c2,0x14c3,0x14c4,0x14c5,0x14c6,0x14c7, + 0x14c8,0x14c9,0x14ca,0x14cb,0x14cc,0x14cd,0x14ce,0x14cf, + 0x14d0,0x14d1,0x14d2,0x14d3,0x14d4,0x14d5,0x14d6,0x14d7, + 0x14d8,0x14d9,0x14da,0x14db,0x14dc,0x14dd,0x14de,0x14df, + 0x14e0,0x14e1,0x14e2,0x14e3,0x14e4,0x14e5,0x14e6,0x14e7, + 0x14e8,0x14e9,0x14ea,0x14eb,0x14ec,0x14ed,0x14ee,0x14ef, + 0x14f0,0x14f1,0x14f2,0x14f3,0x14f4,0x14f5,0x14f6,0x14f7, + 0x14f8,0x14f9,0x14fa,0x14fb,0x14fc,0x14fd,0x14fe,0x14ff, + 0x1500,0x1501,0x1502,0x1503,0x1504,0x1505,0x1506,0x1507, + 0x1508,0x1509,0x150a,0x150b,0x150c,0x150d,0x150e,0x150f, + 0x1510,0x1511,0x1512,0x1513,0x1514,0x1515,0x1516,0x1517, + 0x1518,0x1519,0x151a,0x151b,0x151c,0x151d,0x151e,0x151f, + 0x1520,0x1521,0x1522,0x1523,0x1524,0x1525,0x1526,0x1527, + 0x1528,0x1529,0x152a,0x152b,0x152c,0x152d,0x152e,0x152f, + 0x1530,0x1531,0x1532,0x1533,0x1534,0x1535,0x1536,0x1537, + 0x1538,0x1539,0x153a,0x153b,0x153c,0x153d,0x153e,0x153f, + 0x1540,0x1541,0x1542,0x1543,0x1544,0x1545,0x1546,0x1547, + 0x1548,0x1549,0x154a,0x154b,0x154c,0x154d,0x154e,0x154f, + 0x1550,0x1551,0x1552,0x1553,0x1554,0x1555,0x1556,0x1557, + 0x1558,0x1559,0x155a,0x155b,0x155c,0x155d,0x155e,0x155f, + 0x1560,0x1561,0x1562,0x1563,0x1564,0x1565,0x1566,0x1567, + 0x1568,0x1569,0x156a,0x156b,0x156c,0x156d,0x156e,0x156f, + 0x1570,0x1571,0x1572,0x1573,0x1574,0x1575,0x1576,0x1577, + 0x1578,0x1579,0x157a,0x157b,0x157c,0x157d,0x157e,0x157f, + 0x1580,0x1581,0x1582,0x1583,0x1584,0x1585,0x1586,0x1587, + 0x1588,0x1589,0x158a,0x158b,0x158c,0x158d,0x158e,0x158f, + 0x1590,0x1591,0x1592,0x1593,0x1594,0x1595,0x1596,0x1597, + 0x1598,0x1599,0x159a,0x159b,0x159c,0x159d,0x159e,0x159f, + 0x15a0,0x15a1,0x15a2,0x15a3,0x15a4,0x15a5,0x15a6,0x15a7, + 0x15a8,0x15a9,0x15aa,0x15ab,0x15ac,0x15ad,0x15ae,0x15af, + 0x15b0,0x15b1,0x15b2,0x15b3,0x15b4,0x15b5,0x15b6,0x15b7, + 0x15b8,0x15b9,0x15ba,0x15bb,0x15bc,0x15bd,0x15be,0x15bf, + 0x15c0,0x15c1,0x15c2,0x15c3,0x15c4,0x15c5,0x15c6,0x15c7, + 0x15c8,0x15c9,0x15ca,0x15cb,0x15cc,0x15cd,0x15ce,0x15cf, + 0x15d0,0x15d1,0x15d2,0x15d3,0x15d4,0x15d5,0x15d6,0x15d7, + 0x15d8,0x15d9,0x15da,0x15db,0x15dc,0x15dd,0x15de,0x15df, + 0x15e0,0x15e1,0x15e2,0x15e3,0x15e4,0x15e5,0x15e6,0x15e7, + 0x15e8,0x15e9,0x15ea,0x15eb,0x15ec,0x15ed,0x15ee,0x15ef, + 0x15f0,0x15f1,0x15f2,0x15f3,0x15f4,0x15f5,0x15f6,0x15f7, + 0x15f8,0x15f9,0x15fa,0x15fb,0x15fc,0x15fd,0x15fe,0x15ff, + 0x1600,0x1601,0x1602,0x1603,0x1604,0x1605,0x1606,0x1607, + 0x1608,0x1609,0x160a,0x160b,0x160c,0x160d,0x160e,0x160f, + 0x1610,0x1611,0x1612,0x1613,0x1614,0x1615,0x1616,0x1617, + 0x1618,0x1619,0x161a,0x161b,0x161c,0x161d,0x161e,0x161f, + 0x1620,0x1621,0x1622,0x1623,0x1624,0x1625,0x1626,0x1627, + 0x1628,0x1629,0x162a,0x162b,0x162c,0x162d,0x162e,0x162f, + 0x1630,0x1631,0x1632,0x1633,0x1634,0x1635,0x1636,0x1637, + 0x1638,0x1639,0x163a,0x163b,0x163c,0x163d,0x163e,0x163f, + 0x1640,0x1641,0x1642,0x1643,0x1644,0x1645,0x1646,0x1647, + 0x1648,0x1649,0x164a,0x164b,0x164c,0x164d,0x164e,0x164f, + 0x1650,0x1651,0x1652,0x1653,0x1654,0x1655,0x1656,0x1657, + 0x1658,0x1659,0x165a,0x165b,0x165c,0x165d,0x165e,0x165f, + 0x1660,0x1661,0x1662,0x1663,0x1664,0x1665,0x1666,0x1667, + 0x1668,0x1669,0x166a,0x166b,0x166c,0x166d,0x166e,0x166f, + 0x1670,0x1671,0x1672,0x1673,0x1674,0x1675,0x1676,0x1677, + 0x1678,0x1679,0x167a,0x167b,0x167c,0x167d,0x167e,0x167f, + 0x1680,0x1681,0x1682,0x1683,0x1684,0x1685,0x1686,0x1687, + 0x1688,0x1689,0x168a,0x168b,0x168c,0x168d,0x168e,0x168f, + 0x1690,0x1691,0x1692,0x1693,0x1694,0x1695,0x1696,0x1697, + 0x1698,0x1699,0x169a,0x169b,0x169c,0x169d,0x169e,0x169f, + 0x16a0,0x16a1,0x16a2,0x16a3,0x16a4,0x16a5,0x16a6,0x16a7, + 0x16a8,0x16a9,0x16aa,0x16ab,0x16ac,0x16ad,0x16ae,0x16af, + 0x16b0,0x16b1,0x16b2,0x16b3,0x16b4,0x16b5,0x16b6,0x16b7, + 0x16b8,0x16b9,0x16ba,0x16bb,0x16bc,0x16bd,0x16be,0x16bf, + 0x16c0,0x16c1,0x16c2,0x16c3,0x16c4,0x16c5,0x16c6,0x16c7, + 0x16c8,0x16c9,0x16ca,0x16cb,0x16cc,0x16cd,0x16ce,0x16cf, + 0x16d0,0x16d1,0x16d2,0x16d3,0x16d4,0x16d5,0x16d6,0x16d7, + 0x16d8,0x16d9,0x16da,0x16db,0x16dc,0x16dd,0x16de,0x16df, + 0x16e0,0x16e1,0x16e2,0x16e3,0x16e4,0x16e5,0x16e6,0x16e7, + 0x16e8,0x16e9,0x16ea,0x16eb,0x16ec,0x16ed,0x16ee,0x16ef, + 0x16f0,0x16f1,0x16f2,0x16f3,0x16f4,0x16f5,0x16f6,0x16f7, + 0x16f8,0x16f9,0x16fa,0x16fb,0x16fc,0x16fd,0x16fe,0x16ff, + 0x1700,0x1701,0x1702,0x1703,0x1704,0x1705,0x1706,0x1707, + 0x1708,0x1709,0x170a,0x170b,0x170c,0x170d,0x170e,0x170f, + 0x1710,0x1711,0x1712,0x1713,0x1714,0x1715,0x1716,0x1717, + 0x1718,0x1719,0x171a,0x171b,0x171c,0x171d,0x171e,0x171f, + 0x1720,0x1721,0x1722,0x1723,0x1724,0x1725,0x1726,0x1727, + 0x1728,0x1729,0x172a,0x172b,0x172c,0x172d,0x172e,0x172f, + 0x1730,0x1731,0x1732,0x1733,0x1734,0x1735,0x1736,0x1737, + 0x1738,0x1739,0x173a,0x173b,0x173c,0x173d,0x173e,0x173f, + 0x1740,0x1741,0x1742,0x1743,0x1744,0x1745,0x1746,0x1747, + 0x1748,0x1749,0x174a,0x174b,0x174c,0x174d,0x174e,0x174f, + 0x1750,0x1751,0x1752,0x1753,0x1754,0x1755,0x1756,0x1757, + 0x1758,0x1759,0x175a,0x175b,0x175c,0x175d,0x175e,0x175f, + 0x1760,0x1761,0x1762,0x1763,0x1764,0x1765,0x1766,0x1767, + 0x1768,0x1769,0x176a,0x176b,0x176c,0x176d,0x176e,0x176f, + 0x1770,0x1771,0x1772,0x1773,0x1774,0x1775,0x1776,0x1777, + 0x1778,0x1779,0x177a,0x177b,0x177c,0x177d,0x177e,0x177f, + 0x1780,0x1781,0x1782,0x1783,0x1784,0x1785,0x1786,0x1787, + 0x1788,0x1789,0x178a,0x178b,0x178c,0x178d,0x178e,0x178f, + 0x1790,0x1791,0x1792,0x1793,0x1794,0x1795,0x1796,0x1797, + 0x1798,0x1799,0x179a,0x179b,0x179c,0x179d,0x179e,0x179f, + 0x17a0,0x17a1,0x17a2,0x17a3,0x17a4,0x17a5,0x17a6,0x17a7, + 0x17a8,0x17a9,0x17aa,0x17ab,0x17ac,0x17ad,0x17ae,0x17af, + 0x17b0,0x17b1,0x17b2,0x17b3,0x17b4,0x17b5,0x17b6,0x17b7, + 0x17b8,0x17b9,0x17ba,0x17bb,0x17bc,0x17bd,0x17be,0x17bf, + 0x17c0,0x17c1,0x17c2,0x17c3,0x17c4,0x17c5,0x17c6,0x17c7, + 0x17c8,0x17c9,0x17ca,0x17cb,0x17cc,0x17cd,0x17ce,0x17cf, + 0x17d0,0x17d1,0x17d2,0x17d3,0x17d4,0x17d5,0x17d6,0x17d7, + 0x17d8,0x17d9,0x17da,0x17db,0x17dc,0x17dd,0x17de,0x17df, + 0x17e0,0x17e1,0x17e2,0x17e3,0x17e4,0x17e5,0x17e6,0x17e7, + 0x17e8,0x17e9,0x17ea,0x17eb,0x17ec,0x17ed,0x17ee,0x17ef, + 0x17f0,0x17f1,0x17f2,0x17f3,0x17f4,0x17f5,0x17f6,0x17f7, + 0x17f8,0x17f9,0x17fa,0x17fb,0x17fc,0x17fd,0x17fe,0x17ff, + 0x1800,0x1801,0x1802,0x1803,0x1804,0x1805,0x1806,0x1807, + 0x1808,0x1809,0x180a,0x180b,0x180c,0x180d,0x180e,0x180f, + 0x1810,0x1811,0x1812,0x1813,0x1814,0x1815,0x1816,0x1817, + 0x1818,0x1819,0x181a,0x181b,0x181c,0x181d,0x181e,0x181f, + 0x1820,0x1821,0x1822,0x1823,0x1824,0x1825,0x1826,0x1827, + 0x1828,0x1829,0x182a,0x182b,0x182c,0x182d,0x182e,0x182f, + 0x1830,0x1831,0x1832,0x1833,0x1834,0x1835,0x1836,0x1837, + 0x1838,0x1839,0x183a,0x183b,0x183c,0x183d,0x183e,0x183f, + 0x1840,0x1841,0x1842,0x1843,0x1844,0x1845,0x1846,0x1847, + 0x1848,0x1849,0x184a,0x184b,0x184c,0x184d,0x184e,0x184f, + 0x1850,0x1851,0x1852,0x1853,0x1854,0x1855,0x1856,0x1857, + 0x1858,0x1859,0x185a,0x185b,0x185c,0x185d,0x185e,0x185f, + 0x1860,0x1861,0x1862,0x1863,0x1864,0x1865,0x1866,0x1867, + 0x1868,0x1869,0x186a,0x186b,0x186c,0x186d,0x186e,0x186f, + 0x1870,0x1871,0x1872,0x1873,0x1874,0x1875,0x1876,0x1877, + 0x1878,0x1879,0x187a,0x187b,0x187c,0x187d,0x187e,0x187f, + 0x1880,0x1881,0x1882,0x1883,0x1884,0x1885,0x1886,0x1887, + 0x1888,0x1889,0x188a,0x188b,0x188c,0x188d,0x188e,0x188f, + 0x1890,0x1891,0x1892,0x1893,0x1894,0x1895,0x1896,0x1897, + 0x1898,0x1899,0x189a,0x189b,0x189c,0x189d,0x189e,0x189f, + 0x18a0,0x18a1,0x18a2,0x18a3,0x18a4,0x18a5,0x18a6,0x18a7, + 0x18a8,0x18a9,0x18aa,0x18ab,0x18ac,0x18ad,0x18ae,0x18af, + 0x18b0,0x18b1,0x18b2,0x18b3,0x18b4,0x18b5,0x18b6,0x18b7, + 0x18b8,0x18b9,0x18ba,0x18bb,0x18bc,0x18bd,0x18be,0x18bf, + 0x18c0,0x18c1,0x18c2,0x18c3,0x18c4,0x18c5,0x18c6,0x18c7, + 0x18c8,0x18c9,0x18ca,0x18cb,0x18cc,0x18cd,0x18ce,0x18cf, + 0x18d0,0x18d1,0x18d2,0x18d3,0x18d4,0x18d5,0x18d6,0x18d7, + 0x18d8,0x18d9,0x18da,0x18db,0x18dc,0x18dd,0x18de,0x18df, + 0x18e0,0x18e1,0x18e2,0x18e3,0x18e4,0x18e5,0x18e6,0x18e7, + 0x18e8,0x18e9,0x18ea,0x18eb,0x18ec,0x18ed,0x18ee,0x18ef, + 0x18f0,0x18f1,0x18f2,0x18f3,0x18f4,0x18f5,0x18f6,0x18f7, + 0x18f8,0x18f9,0x18fa,0x18fb,0x18fc,0x18fd,0x18fe,0x18ff, + 0x1900,0x1901,0x1902,0x1903,0x1904,0x1905,0x1906,0x1907, + 0x1908,0x1909,0x190a,0x190b,0x190c,0x190d,0x190e,0x190f, + 0x1910,0x1911,0x1912,0x1913,0x1914,0x1915,0x1916,0x1917, + 0x1918,0x1919,0x191a,0x191b,0x191c,0x191d,0x191e,0x191f, + 0x1920,0x1921,0x1922,0x1923,0x1924,0x1925,0x1926,0x1927, + 0x1928,0x1929,0x192a,0x192b,0x192c,0x192d,0x192e,0x192f, + 0x1930,0x1931,0x1932,0x1933,0x1934,0x1935,0x1936,0x1937, + 0x1938,0x1939,0x193a,0x193b,0x193c,0x193d,0x193e,0x193f, + 0x1940,0x1941,0x1942,0x1943,0x1944,0x1945,0x1946,0x1947, + 0x1948,0x1949,0x194a,0x194b,0x194c,0x194d,0x194e,0x194f, + 0x1950,0x1951,0x1952,0x1953,0x1954,0x1955,0x1956,0x1957, + 0x1958,0x1959,0x195a,0x195b,0x195c,0x195d,0x195e,0x195f, + 0x1960,0x1961,0x1962,0x1963,0x1964,0x1965,0x1966,0x1967, + 0x1968,0x1969,0x196a,0x196b,0x196c,0x196d,0x196e,0x196f, + 0x1970,0x1971,0x1972,0x1973,0x1974,0x1975,0x1976,0x1977, + 0x1978,0x1979,0x197a,0x197b,0x197c,0x197d,0x197e,0x197f, + 0x1980,0x1981,0x1982,0x1983,0x1984,0x1985,0x1986,0x1987, + 0x1988,0x1989,0x198a,0x198b,0x198c,0x198d,0x198e,0x198f, + 0x1990,0x1991,0x1992,0x1993,0x1994,0x1995,0x1996,0x1997, + 0x1998,0x1999,0x199a,0x199b,0x199c,0x199d,0x199e,0x199f, + 0x19a0,0x19a1,0x19a2,0x19a3,0x19a4,0x19a5,0x19a6,0x19a7, + 0x19a8,0x19a9,0x19aa,0x19ab,0x19ac,0x19ad,0x19ae,0x19af, + 0x19b0,0x19b1,0x19b2,0x19b3,0x19b4,0x19b5,0x19b6,0x19b7, + 0x19b8,0x19b9,0x19ba,0x19bb,0x19bc,0x19bd,0x19be,0x19bf, + 0x19c0,0x19c1,0x19c2,0x19c3,0x19c4,0x19c5,0x19c6,0x19c7, + 0x19c8,0x19c9,0x19ca,0x19cb,0x19cc,0x19cd,0x19ce,0x19cf, + 0x19d0,0x19d1,0x19d2,0x19d3,0x19d4,0x19d5,0x19d6,0x19d7, + 0x19d8,0x19d9,0x19da,0x19db,0x19dc,0x19dd,0x19de,0x19df, + 0x19e0,0x19e1,0x19e2,0x19e3,0x19e4,0x19e5,0x19e6,0x19e7, + 0x19e8,0x19e9,0x19ea,0x19eb,0x19ec,0x19ed,0x19ee,0x19ef, + 0x19f0,0x19f1,0x19f2,0x19f3,0x19f4,0x19f5,0x19f6,0x19f7, + 0x19f8,0x19f9,0x19fa,0x19fb,0x19fc,0x19fd,0x19fe,0x19ff, + 0x1a00,0x1a01,0x1a02,0x1a03,0x1a04,0x1a05,0x1a06,0x1a07, + 0x1a08,0x1a09,0x1a0a,0x1a0b,0x1a0c,0x1a0d,0x1a0e,0x1a0f, + 0x1a10,0x1a11,0x1a12,0x1a13,0x1a14,0x1a15,0x1a16,0x1a17, + 0x1a18,0x1a19,0x1a1a,0x1a1b,0x1a1c,0x1a1d,0x1a1e,0x1a1f, + 0x1a20,0x1a21,0x1a22,0x1a23,0x1a24,0x1a25,0x1a26,0x1a27, + 0x1a28,0x1a29,0x1a2a,0x1a2b,0x1a2c,0x1a2d,0x1a2e,0x1a2f, + 0x1a30,0x1a31,0x1a32,0x1a33,0x1a34,0x1a35,0x1a36,0x1a37, + 0x1a38,0x1a39,0x1a3a,0x1a3b,0x1a3c,0x1a3d,0x1a3e,0x1a3f, + 0x1a40,0x1a41,0x1a42,0x1a43,0x1a44,0x1a45,0x1a46,0x1a47, + 0x1a48,0x1a49,0x1a4a,0x1a4b,0x1a4c,0x1a4d,0x1a4e,0x1a4f, + 0x1a50,0x1a51,0x1a52,0x1a53,0x1a54,0x1a55,0x1a56,0x1a57, + 0x1a58,0x1a59,0x1a5a,0x1a5b,0x1a5c,0x1a5d,0x1a5e,0x1a5f, + 0x1a60,0x1a61,0x1a62,0x1a63,0x1a64,0x1a65,0x1a66,0x1a67, + 0x1a68,0x1a69,0x1a6a,0x1a6b,0x1a6c,0x1a6d,0x1a6e,0x1a6f, + 0x1a70,0x1a71,0x1a72,0x1a73,0x1a74,0x1a75,0x1a76,0x1a77, + 0x1a78,0x1a79,0x1a7a,0x1a7b,0x1a7c,0x1a7d,0x1a7e,0x1a7f, + 0x1a80,0x1a81,0x1a82,0x1a83,0x1a84,0x1a85,0x1a86,0x1a87, + 0x1a88,0x1a89,0x1a8a,0x1a8b,0x1a8c,0x1a8d,0x1a8e,0x1a8f, + 0x1a90,0x1a91,0x1a92,0x1a93,0x1a94,0x1a95,0x1a96,0x1a97, + 0x1a98,0x1a99,0x1a9a,0x1a9b,0x1a9c,0x1a9d,0x1a9e,0x1a9f, + 0x1aa0,0x1aa1,0x1aa2,0x1aa3,0x1aa4,0x1aa5,0x1aa6,0x1aa7, + 0x1aa8,0x1aa9,0x1aaa,0x1aab,0x1aac,0x1aad,0x1aae,0x1aaf, + 0x1ab0,0x1ab1,0x1ab2,0x1ab3,0x1ab4,0x1ab5,0x1ab6,0x1ab7, + 0x1ab8,0x1ab9,0x1aba,0x1abb,0x1abc,0x1abd,0x1abe,0x1abf, + 0x1ac0,0x1ac1,0x1ac2,0x1ac3,0x1ac4,0x1ac5,0x1ac6,0x1ac7, + 0x1ac8,0x1ac9,0x1aca,0x1acb,0x1acc,0x1acd,0x1ace,0x1acf, + 0x1ad0,0x1ad1,0x1ad2,0x1ad3,0x1ad4,0x1ad5,0x1ad6,0x1ad7, + 0x1ad8,0x1ad9,0x1ada,0x1adb,0x1adc,0x1add,0x1ade,0x1adf, + 0x1ae0,0x1ae1,0x1ae2,0x1ae3,0x1ae4,0x1ae5,0x1ae6,0x1ae7, + 0x1ae8,0x1ae9,0x1aea,0x1aeb,0x1aec,0x1aed,0x1aee,0x1aef, + 0x1af0,0x1af1,0x1af2,0x1af3,0x1af4,0x1af5,0x1af6,0x1af7, + 0x1af8,0x1af9,0x1afa,0x1afb,0x1afc,0x1afd,0x1afe,0x1aff, + 0x1b00,0x1b01,0x1b02,0x1b03,0x1b04,0x1b05,0x1b06,0x1b07, + 0x1b08,0x1b09,0x1b0a,0x1b0b,0x1b0c,0x1b0d,0x1b0e,0x1b0f, + 0x1b10,0x1b11,0x1b12,0x1b13,0x1b14,0x1b15,0x1b16,0x1b17, + 0x1b18,0x1b19,0x1b1a,0x1b1b,0x1b1c,0x1b1d,0x1b1e,0x1b1f, + 0x1b20,0x1b21,0x1b22,0x1b23,0x1b24,0x1b25,0x1b26,0x1b27, + 0x1b28,0x1b29,0x1b2a,0x1b2b,0x1b2c,0x1b2d,0x1b2e,0x1b2f, + 0x1b30,0x1b31,0x1b32,0x1b33,0x1b34,0x1b35,0x1b36,0x1b37, + 0x1b38,0x1b39,0x1b3a,0x1b3b,0x1b3c,0x1b3d,0x1b3e,0x1b3f, + 0x1b40,0x1b41,0x1b42,0x1b43,0x1b44,0x1b45,0x1b46,0x1b47, + 0x1b48,0x1b49,0x1b4a,0x1b4b,0x1b4c,0x1b4d,0x1b4e,0x1b4f, + 0x1b50,0x1b51,0x1b52,0x1b53,0x1b54,0x1b55,0x1b56,0x1b57, + 0x1b58,0x1b59,0x1b5a,0x1b5b,0x1b5c,0x1b5d,0x1b5e,0x1b5f, + 0x1b60,0x1b61,0x1b62,0x1b63,0x1b64,0x1b65,0x1b66,0x1b67, + 0x1b68,0x1b69,0x1b6a,0x1b6b,0x1b6c,0x1b6d,0x1b6e,0x1b6f, + 0x1b70,0x1b71,0x1b72,0x1b73,0x1b74,0x1b75,0x1b76,0x1b77, + 0x1b78,0x1b79,0x1b7a,0x1b7b,0x1b7c,0x1b7d,0x1b7e,0x1b7f, + 0x1b80,0x1b81,0x1b82,0x1b83,0x1b84,0x1b85,0x1b86,0x1b87, + 0x1b88,0x1b89,0x1b8a,0x1b8b,0x1b8c,0x1b8d,0x1b8e,0x1b8f, + 0x1b90,0x1b91,0x1b92,0x1b93,0x1b94,0x1b95,0x1b96,0x1b97, + 0x1b98,0x1b99,0x1b9a,0x1b9b,0x1b9c,0x1b9d,0x1b9e,0x1b9f, + 0x1ba0,0x1ba1,0x1ba2,0x1ba3,0x1ba4,0x1ba5,0x1ba6,0x1ba7, + 0x1ba8,0x1ba9,0x1baa,0x1bab,0x1bac,0x1bad,0x1bae,0x1baf, + 0x1bb0,0x1bb1,0x1bb2,0x1bb3,0x1bb4,0x1bb5,0x1bb6,0x1bb7, + 0x1bb8,0x1bb9,0x1bba,0x1bbb,0x1bbc,0x1bbd,0x1bbe,0x1bbf, + 0x1bc0,0x1bc1,0x1bc2,0x1bc3,0x1bc4,0x1bc5,0x1bc6,0x1bc7, + 0x1bc8,0x1bc9,0x1bca,0x1bcb,0x1bcc,0x1bcd,0x1bce,0x1bcf, + 0x1bd0,0x1bd1,0x1bd2,0x1bd3,0x1bd4,0x1bd5,0x1bd6,0x1bd7, + 0x1bd8,0x1bd9,0x1bda,0x1bdb,0x1bdc,0x1bdd,0x1bde,0x1bdf, + 0x1be0,0x1be1,0x1be2,0x1be3,0x1be4,0x1be5,0x1be6,0x1be7, + 0x1be8,0x1be9,0x1bea,0x1beb,0x1bec,0x1bed,0x1bee,0x1bef, + 0x1bf0,0x1bf1,0x1bf2,0x1bf3,0x1bf4,0x1bf5,0x1bf6,0x1bf7, + 0x1bf8,0x1bf9,0x1bfa,0x1bfb,0x1bfc,0x1bfd,0x1bfe,0x1bff, + 0x1c00,0x1c01,0x1c02,0x1c03,0x1c04,0x1c05,0x1c06,0x1c07, + 0x1c08,0x1c09,0x1c0a,0x1c0b,0x1c0c,0x1c0d,0x1c0e,0x1c0f, + 0x1c10,0x1c11,0x1c12,0x1c13,0x1c14,0x1c15,0x1c16,0x1c17, + 0x1c18,0x1c19,0x1c1a,0x1c1b,0x1c1c,0x1c1d,0x1c1e,0x1c1f, + 0x1c20,0x1c21,0x1c22,0x1c23,0x1c24,0x1c25,0x1c26,0x1c27, + 0x1c28,0x1c29,0x1c2a,0x1c2b,0x1c2c,0x1c2d,0x1c2e,0x1c2f, + 0x1c30,0x1c31,0x1c32,0x1c33,0x1c34,0x1c35,0x1c36,0x1c37, + 0x1c38,0x1c39,0x1c3a,0x1c3b,0x1c3c,0x1c3d,0x1c3e,0x1c3f, + 0x1c40,0x1c41,0x1c42,0x1c43,0x1c44,0x1c45,0x1c46,0x1c47, + 0x1c48,0x1c49,0x1c4a,0x1c4b,0x1c4c,0x1c4d,0x1c4e,0x1c4f, + 0x1c50,0x1c51,0x1c52,0x1c53,0x1c54,0x1c55,0x1c56,0x1c57, + 0x1c58,0x1c59,0x1c5a,0x1c5b,0x1c5c,0x1c5d,0x1c5e,0x1c5f, + 0x1c60,0x1c61,0x1c62,0x1c63,0x1c64,0x1c65,0x1c66,0x1c67, + 0x1c68,0x1c69,0x1c6a,0x1c6b,0x1c6c,0x1c6d,0x1c6e,0x1c6f, + 0x1c70,0x1c71,0x1c72,0x1c73,0x1c74,0x1c75,0x1c76,0x1c77, + 0x1c78,0x1c79,0x1c7a,0x1c7b,0x1c7c,0x1c7d,0x1c7e,0x1c7f, + 0x1c80,0x1c81,0x1c82,0x1c83,0x1c84,0x1c85,0x1c86,0x1c87, + 0x1c88,0x1c89,0x1c8a,0x1c8b,0x1c8c,0x1c8d,0x1c8e,0x1c8f, + 0x1c90,0x1c91,0x1c92,0x1c93,0x1c94,0x1c95,0x1c96,0x1c97, + 0x1c98,0x1c99,0x1c9a,0x1c9b,0x1c9c,0x1c9d,0x1c9e,0x1c9f, + 0x1ca0,0x1ca1,0x1ca2,0x1ca3,0x1ca4,0x1ca5,0x1ca6,0x1ca7, + 0x1ca8,0x1ca9,0x1caa,0x1cab,0x1cac,0x1cad,0x1cae,0x1caf, + 0x1cb0,0x1cb1,0x1cb2,0x1cb3,0x1cb4,0x1cb5,0x1cb6,0x1cb7, + 0x1cb8,0x1cb9,0x1cba,0x1cbb,0x1cbc,0x1cbd,0x1cbe,0x1cbf, + 0x1cc0,0x1cc1,0x1cc2,0x1cc3,0x1cc4,0x1cc5,0x1cc6,0x1cc7, + 0x1cc8,0x1cc9,0x1cca,0x1ccb,0x1ccc,0x1ccd,0x1cce,0x1ccf, + 0x1cd0,0x1cd1,0x1cd2,0x1cd3,0x1cd4,0x1cd5,0x1cd6,0x1cd7, + 0x1cd8,0x1cd9,0x1cda,0x1cdb,0x1cdc,0x1cdd,0x1cde,0x1cdf, + 0x1ce0,0x1ce1,0x1ce2,0x1ce3,0x1ce4,0x1ce5,0x1ce6,0x1ce7, + 0x1ce8,0x1ce9,0x1cea,0x1ceb,0x1cec,0x1ced,0x1cee,0x1cef, + 0x1cf0,0x1cf1,0x1cf2,0x1cf3,0x1cf4,0x1cf5,0x1cf6,0x1cf7, + 0x1cf8,0x1cf9,0x1cfa,0x1cfb,0x1cfc,0x1cfd,0x1cfe,0x1cff, + 0x1d00,0x1d01,0x1d02,0x1d03,0x1d04,0x1d05,0x1d06,0x1d07, + 0x1d08,0x1d09,0x1d0a,0x1d0b,0x1d0c,0x1d0d,0x1d0e,0x1d0f, + 0x1d10,0x1d11,0x1d12,0x1d13,0x1d14,0x1d15,0x1d16,0x1d17, + 0x1d18,0x1d19,0x1d1a,0x1d1b,0x1d1c,0x1d1d,0x1d1e,0x1d1f, + 0x1d20,0x1d21,0x1d22,0x1d23,0x1d24,0x1d25,0x1d26,0x1d27, + 0x1d28,0x1d29,0x1d2a,0x1d2b,0x1d2c,0x1d2d,0x1d2e,0x1d2f, + 0x1d30,0x1d31,0x1d32,0x1d33,0x1d34,0x1d35,0x1d36,0x1d37, + 0x1d38,0x1d39,0x1d3a,0x1d3b,0x1d3c,0x1d3d,0x1d3e,0x1d3f, + 0x1d40,0x1d41,0x1d42,0x1d43,0x1d44,0x1d45,0x1d46,0x1d47, + 0x1d48,0x1d49,0x1d4a,0x1d4b,0x1d4c,0x1d4d,0x1d4e,0x1d4f, + 0x1d50,0x1d51,0x1d52,0x1d53,0x1d54,0x1d55,0x1d56,0x1d57, + 0x1d58,0x1d59,0x1d5a,0x1d5b,0x1d5c,0x1d5d,0x1d5e,0x1d5f, + 0x1d60,0x1d61,0x1d62,0x1d63,0x1d64,0x1d65,0x1d66,0x1d67, + 0x1d68,0x1d69,0x1d6a,0x1d6b,0x1d6c,0x1d6d,0x1d6e,0x1d6f, + 0x1d70,0x1d71,0x1d72,0x1d73,0x1d74,0x1d75,0x1d76,0x1d77, + 0x1d78,0x1d79,0x1d7a,0x1d7b,0x1d7c,0x1d7d,0x1d7e,0x1d7f, + 0x1d80,0x1d81,0x1d82,0x1d83,0x1d84,0x1d85,0x1d86,0x1d87, + 0x1d88,0x1d89,0x1d8a,0x1d8b,0x1d8c,0x1d8d,0x1d8e,0x1d8f, + 0x1d90,0x1d91,0x1d92,0x1d93,0x1d94,0x1d95,0x1d96,0x1d97, + 0x1d98,0x1d99,0x1d9a,0x1d9b,0x1d9c,0x1d9d,0x1d9e,0x1d9f, + 0x1da0,0x1da1,0x1da2,0x1da3,0x1da4,0x1da5,0x1da6,0x1da7, + 0x1da8,0x1da9,0x1daa,0x1dab,0x1dac,0x1dad,0x1dae,0x1daf, + 0x1db0,0x1db1,0x1db2,0x1db3,0x1db4,0x1db5,0x1db6,0x1db7, + 0x1db8,0x1db9,0x1dba,0x1dbb,0x1dbc,0x1dbd,0x1dbe,0x1dbf, + 0x1dc0,0x1dc1,0x1dc2,0x1dc3,0x1dc4,0x1dc5,0x1dc6,0x1dc7, + 0x1dc8,0x1dc9,0x1dca,0x1dcb,0x1dcc,0x1dcd,0x1dce,0x1dcf, + 0x1dd0,0x1dd1,0x1dd2,0x1dd3,0x1dd4,0x1dd5,0x1dd6,0x1dd7, + 0x1dd8,0x1dd9,0x1dda,0x1ddb,0x1ddc,0x1ddd,0x1dde,0x1ddf, + 0x1de0,0x1de1,0x1de2,0x1de3,0x1de4,0x1de5,0x1de6,0x1de7, + 0x1de8,0x1de9,0x1dea,0x1deb,0x1dec,0x1ded,0x1dee,0x1def, + 0x1df0,0x1df1,0x1df2,0x1df3,0x1df4,0x1df5,0x1df6,0x1df7, + 0x1df8,0x1df9,0x1dfa,0x1dfb,0x1dfc,0x1dfd,0x1dfe,0x1dff, + 0x1e00,0x1e00,0x1e02,0x1e02,0x1e04,0x1e04,0x1e06,0x1e06, + 0x1e08,0x1e08,0x1e0a,0x1e0a,0x1e0c,0x1e0c,0x1e0e,0x1e0e, + 0x1e10,0x1e10,0x1e12,0x1e12,0x1e14,0x1e14,0x1e16,0x1e16, + 0x1e18,0x1e18,0x1e1a,0x1e1a,0x1e1c,0x1e1c,0x1e1e,0x1e1e, + 0x1e20,0x1e20,0x1e22,0x1e22,0x1e24,0x1e24,0x1e26,0x1e26, + 0x1e28,0x1e28,0x1e2a,0x1e2a,0x1e2c,0x1e2c,0x1e2e,0x1e2e, + 0x1e30,0x1e30,0x1e32,0x1e32,0x1e34,0x1e34,0x1e36,0x1e36, + 0x1e38,0x1e38,0x1e3a,0x1e3a,0x1e3c,0x1e3c,0x1e3e,0x1e3e, + 0x1e40,0x1e40,0x1e42,0x1e42,0x1e44,0x1e44,0x1e46,0x1e46, + 0x1e48,0x1e48,0x1e4a,0x1e4a,0x1e4c,0x1e4c,0x1e4e,0x1e4e, + 0x1e50,0x1e50,0x1e52,0x1e52,0x1e54,0x1e54,0x1e56,0x1e56, + 0x1e58,0x1e58,0x1e5a,0x1e5a,0x1e5c,0x1e5c,0x1e5e,0x1e5e, + 0x1e60,0x1e60,0x1e62,0x1e62,0x1e64,0x1e64,0x1e66,0x1e66, + 0x1e68,0x1e68,0x1e6a,0x1e6a,0x1e6c,0x1e6c,0x1e6e,0x1e6e, + 0x1e70,0x1e70,0x1e72,0x1e72,0x1e74,0x1e74,0x1e76,0x1e76, + 0x1e78,0x1e78,0x1e7a,0x1e7a,0x1e7c,0x1e7c,0x1e7e,0x1e7e, + 0x1e80,0x1e80,0x1e82,0x1e82,0x1e84,0x1e84,0x1e86,0x1e86, + 0x1e88,0x1e88,0x1e8a,0x1e8a,0x1e8c,0x1e8c,0x1e8e,0x1e8e, + 0x1e90,0x1e90,0x1e92,0x1e92,0x1e94,0x1e94,0x1e96,0x1e97, + 0x1e98,0x1e99,0x1e9a,0x1e9b,0x1e9c,0x1e9d,0x1e9e,0x1e9f, + 0x1ea0,0x1ea0,0x1ea2,0x1ea2,0x1ea4,0x1ea4,0x1ea6,0x1ea6, + 0x1ea8,0x1ea8,0x1eaa,0x1eaa,0x1eac,0x1eac,0x1eae,0x1eae, + 0x1eb0,0x1eb0,0x1eb2,0x1eb2,0x1eb4,0x1eb4,0x1eb6,0x1eb6, + 0x1eb8,0x1eb8,0x1eba,0x1eba,0x1ebc,0x1ebc,0x1ebe,0x1ebe, + 0x1ec0,0x1ec0,0x1ec2,0x1ec2,0x1ec4,0x1ec4,0x1ec6,0x1ec6, + 0x1ec8,0x1ec8,0x1eca,0x1eca,0x1ecc,0x1ecc,0x1ece,0x1ece, + 0x1ed0,0x1ed0,0x1ed2,0x1ed2,0x1ed4,0x1ed4,0x1ed6,0x1ed6, + 0x1ed8,0x1ed8,0x1eda,0x1eda,0x1edc,0x1edc,0x1ede,0x1ede, + 0x1ee0,0x1ee0,0x1ee2,0x1ee2,0x1ee4,0x1ee4,0x1ee6,0x1ee6, + 0x1ee8,0x1ee8,0x1eea,0x1eea,0x1eec,0x1eec,0x1eee,0x1eee, + 0x1ef0,0x1ef0,0x1ef2,0x1ef2,0x1ef4,0x1ef4,0x1ef6,0x1ef6, + 0x1ef8,0x1ef8,0x1efa,0x1efb,0x1efc,0x1efd,0x1efe,0x1eff, + 0x1f08,0x1f09,0x1f0a,0x1f0b,0x1f0c,0x1f0d,0x1f0e,0x1f0f, + 0x1f08,0x1f09,0x1f0a,0x1f0b,0x1f0c,0x1f0d,0x1f0e,0x1f0f, + 0x1f18,0x1f19,0x1f1a,0x1f1b,0x1f1c,0x1f1d,0x1f16,0x1f17, + 0x1f18,0x1f19,0x1f1a,0x1f1b,0x1f1c,0x1f1d,0x1f1e,0x1f1f, + 0x1f28,0x1f29,0x1f2a,0x1f2b,0x1f2c,0x1f2d,0x1f2e,0x1f2f, + 0x1f28,0x1f29,0x1f2a,0x1f2b,0x1f2c,0x1f2d,0x1f2e,0x1f2f, + 0x1f38,0x1f39,0x1f3a,0x1f3b,0x1f3c,0x1f3d,0x1f3e,0x1f3f, + 0x1f38,0x1f39,0x1f3a,0x1f3b,0x1f3c,0x1f3d,0x1f3e,0x1f3f, + 0x1f48,0x1f49,0x1f4a,0x1f4b,0x1f4c,0x1f4d,0x1f46,0x1f47, + 0x1f48,0x1f49,0x1f4a,0x1f4b,0x1f4c,0x1f4d,0x1f4e,0x1f4f, + 0x1f50,0x1f59,0x1f52,0x1f5b,0x1f54,0x1f5d,0x1f56,0x1f5f, + 0x1f58,0x1f59,0x1f5a,0x1f5b,0x1f5c,0x1f5d,0x1f5e,0x1f5f, + 0x1f68,0x1f69,0x1f6a,0x1f6b,0x1f6c,0x1f6d,0x1f6e,0x1f6f, + 0x1f68,0x1f69,0x1f6a,0x1f6b,0x1f6c,0x1f6d,0x1f6e,0x1f6f, + 0x1fba,0x1fbb,0x1fc8,0x1fc9,0x1fca,0x1fcb,0x1fda,0x1fdb, + 0x1ff8,0x1ff9,0x1fea,0x1feb,0x1ffa,0x1ffb,0x1f7e,0x1f7f, + 0x1f80,0x1f81,0x1f82,0x1f83,0x1f84,0x1f85,0x1f86,0x1f87, + 0x1f88,0x1f89,0x1f8a,0x1f8b,0x1f8c,0x1f8d,0x1f8e,0x1f8f, + 0x1f90,0x1f91,0x1f92,0x1f93,0x1f94,0x1f95,0x1f96,0x1f97, + 0x1f98,0x1f99,0x1f9a,0x1f9b,0x1f9c,0x1f9d,0x1f9e,0x1f9f, + 0x1fa0,0x1fa1,0x1fa2,0x1fa3,0x1fa4,0x1fa5,0x1fa6,0x1fa7, + 0x1fa8,0x1fa9,0x1faa,0x1fab,0x1fac,0x1fad,0x1fae,0x1faf, + 0x1fb8,0x1fb9,0x1fb2,0x1fb3,0x1fb4,0x1fb5,0x1fb6,0x1fb7, + 0x1fb8,0x1fb9,0x1fba,0x1fbb,0x1fbc,0x1fbd,0x1fbe,0x1fbf, + 0x1fc0,0x1fc1,0x1fc2,0x1fc3,0x1fc4,0x1fc5,0x1fc6,0x1fc7, + 0x1fc8,0x1fc9,0x1fca,0x1fcb,0x1fcc,0x1fcd,0x1fce,0x1fcf, + 0x1fd8,0x1fd9,0x1fd2,0x1fd3,0x1fd4,0x1fd5,0x1fd6,0x1fd7, + 0x1fd8,0x1fd9,0x1fda,0x1fdb,0x1fdc,0x1fdd,0x1fde,0x1fdf, + 0x1fe8,0x1fe9,0x1fe2,0x1fe3,0x1fe4,0x1fec,0x1fe6,0x1fe7, + 0x1fe8,0x1fe9,0x1fea,0x1feb,0x1fec,0x1fed,0x1fee,0x1fef, + 0x1ff0,0x1ff1,0x1ff2,0x1ff3,0x1ff4,0x1ff5,0x1ff6,0x1ff7, + 0x1ff8,0x1ff9,0x1ffa,0x1ffb,0x1ffc,0x1ffd,0x1ffe,0x1fff, + 0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007, + 0x2008,0x2009,0x200a,0x200b,0x200c,0x200d,0x200e,0x200f, + 0x2010,0x2011,0x2012,0x2013,0x2014,0x2015,0x2016,0x2017, + 0x2018,0x2019,0x201a,0x201b,0x201c,0x201d,0x201e,0x201f, + 0x2020,0x2021,0x2022,0x2023,0x2024,0x2025,0x2026,0x2027, + 0x2028,0x2029,0x202a,0x202b,0x202c,0x202d,0x202e,0x202f, + 0x2030,0x2031,0x2032,0x2033,0x2034,0x2035,0x2036,0x2037, + 0x2038,0x2039,0x203a,0x203b,0x203c,0x203d,0x203e,0x203f, + 0x2040,0x2041,0x2042,0x2043,0x2044,0x2045,0x2046,0x2047, + 0x2048,0x2049,0x204a,0x204b,0x204c,0x204d,0x204e,0x204f, + 0x2050,0x2051,0x2052,0x2053,0x2054,0x2055,0x2056,0x2057, + 0x2058,0x2059,0x205a,0x205b,0x205c,0x205d,0x205e,0x205f, + 0x2060,0x2061,0x2062,0x2063,0x2064,0x2065,0x2066,0x2067, + 0x2068,0x2069,0x206a,0x206b,0x206c,0x206d,0x206e,0x206f, + 0x2070,0x2071,0x2072,0x2073,0x2074,0x2075,0x2076,0x2077, + 0x2078,0x2079,0x207a,0x207b,0x207c,0x207d,0x207e,0x207f, + 0x2080,0x2081,0x2082,0x2083,0x2084,0x2085,0x2086,0x2087, + 0x2088,0x2089,0x208a,0x208b,0x208c,0x208d,0x208e,0x208f, + 0x2090,0x2091,0x2092,0x2093,0x2094,0x2095,0x2096,0x2097, + 0x2098,0x2099,0x209a,0x209b,0x209c,0x209d,0x209e,0x209f, + 0x20a0,0x20a1,0x20a2,0x20a3,0x20a4,0x20a5,0x20a6,0x20a7, + 0x20a8,0x20a9,0x20aa,0x20ab,0x20ac,0x20ad,0x20ae,0x20af, + 0x20b0,0x20b1,0x20b2,0x20b3,0x20b4,0x20b5,0x20b6,0x20b7, + 0x20b8,0x20b9,0x20ba,0x20bb,0x20bc,0x20bd,0x20be,0x20bf, + 0x20c0,0x20c1,0x20c2,0x20c3,0x20c4,0x20c5,0x20c6,0x20c7, + 0x20c8,0x20c9,0x20ca,0x20cb,0x20cc,0x20cd,0x20ce,0x20cf, + 0x20d0,0x20d1,0x20d2,0x20d3,0x20d4,0x20d5,0x20d6,0x20d7, + 0x20d8,0x20d9,0x20da,0x20db,0x20dc,0x20dd,0x20de,0x20df, + 0x20e0,0x20e1,0x20e2,0x20e3,0x20e4,0x20e5,0x20e6,0x20e7, + 0x20e8,0x20e9,0x20ea,0x20eb,0x20ec,0x20ed,0x20ee,0x20ef, + 0x20f0,0x20f1,0x20f2,0x20f3,0x20f4,0x20f5,0x20f6,0x20f7, + 0x20f8,0x20f9,0x20fa,0x20fb,0x20fc,0x20fd,0x20fe,0x20ff, + 0x2100,0x2101,0x2102,0x2103,0x2104,0x2105,0x2106,0x2107, + 0x2108,0x2109,0x210a,0x210b,0x210c,0x210d,0x210e,0x210f, + 0x2110,0x2111,0x2112,0x2113,0x2114,0x2115,0x2116,0x2117, + 0x2118,0x2119,0x211a,0x211b,0x211c,0x211d,0x211e,0x211f, + 0x2120,0x2121,0x2122,0x2123,0x2124,0x2125,0x2126,0x2127, + 0x2128,0x2129,0x212a,0x212b,0x212c,0x212d,0x212e,0x212f, + 0x2130,0x2131,0x2132,0x2133,0x2134,0x2135,0x2136,0x2137, + 0x2138,0x2139,0x213a,0x213b,0x213c,0x213d,0x213e,0x213f, + 0x2140,0x2141,0x2142,0x2143,0x2144,0x2145,0x2146,0x2147, + 0x2148,0x2149,0x214a,0x214b,0x214c,0x214d,0x214e,0x214f, + 0x2150,0x2151,0x2152,0x2153,0x2154,0x2155,0x2156,0x2157, + 0x2158,0x2159,0x215a,0x215b,0x215c,0x215d,0x215e,0x215f, + 0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,0x2167, + 0x2168,0x2169,0x216a,0x216b,0x216c,0x216d,0x216e,0x216f, + 0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,0x2167, + 0x2168,0x2169,0x216a,0x216b,0x216c,0x216d,0x216e,0x216f, + 0x2180,0x2181,0x2182,0x2183,0x2184,0x2185,0x2186,0x2187, + 0x2188,0x2189,0x218a,0x218b,0x218c,0x218d,0x218e,0x218f, + 0x2190,0x2191,0x2192,0x2193,0x2194,0x2195,0x2196,0x2197, + 0x2198,0x2199,0x219a,0x219b,0x219c,0x219d,0x219e,0x219f, + 0x21a0,0x21a1,0x21a2,0x21a3,0x21a4,0x21a5,0x21a6,0x21a7, + 0x21a8,0x21a9,0x21aa,0x21ab,0x21ac,0x21ad,0x21ae,0x21af, + 0x21b0,0x21b1,0x21b2,0x21b3,0x21b4,0x21b5,0x21b6,0x21b7, + 0x21b8,0x21b9,0x21ba,0x21bb,0x21bc,0x21bd,0x21be,0x21bf, + 0x21c0,0x21c1,0x21c2,0x21c3,0x21c4,0x21c5,0x21c6,0x21c7, + 0x21c8,0x21c9,0x21ca,0x21cb,0x21cc,0x21cd,0x21ce,0x21cf, + 0x21d0,0x21d1,0x21d2,0x21d3,0x21d4,0x21d5,0x21d6,0x21d7, + 0x21d8,0x21d9,0x21da,0x21db,0x21dc,0x21dd,0x21de,0x21df, + 0x21e0,0x21e1,0x21e2,0x21e3,0x21e4,0x21e5,0x21e6,0x21e7, + 0x21e8,0x21e9,0x21ea,0x21eb,0x21ec,0x21ed,0x21ee,0x21ef, + 0x21f0,0x21f1,0x21f2,0x21f3,0x21f4,0x21f5,0x21f6,0x21f7, + 0x21f8,0x21f9,0x21fa,0x21fb,0x21fc,0x21fd,0x21fe,0x21ff, + 0x2200,0x2201,0x2202,0x2203,0x2204,0x2205,0x2206,0x2207, + 0x2208,0x2209,0x220a,0x220b,0x220c,0x220d,0x220e,0x220f, + 0x2210,0x2211,0x2212,0x2213,0x2214,0x2215,0x2216,0x2217, + 0x2218,0x2219,0x221a,0x221b,0x221c,0x221d,0x221e,0x221f, + 0x2220,0x2221,0x2222,0x2223,0x2224,0x2225,0x2226,0x2227, + 0x2228,0x2229,0x222a,0x222b,0x222c,0x222d,0x222e,0x222f, + 0x2230,0x2231,0x2232,0x2233,0x2234,0x2235,0x2236,0x2237, + 0x2238,0x2239,0x223a,0x223b,0x223c,0x223d,0x223e,0x223f, + 0x2240,0x2241,0x2242,0x2243,0x2244,0x2245,0x2246,0x2247, + 0x2248,0x2249,0x224a,0x224b,0x224c,0x224d,0x224e,0x224f, + 0x2250,0x2251,0x2252,0x2253,0x2254,0x2255,0x2256,0x2257, + 0x2258,0x2259,0x225a,0x225b,0x225c,0x225d,0x225e,0x225f, + 0x2260,0x2261,0x2262,0x2263,0x2264,0x2265,0x2266,0x2267, + 0x2268,0x2269,0x226a,0x226b,0x226c,0x226d,0x226e,0x226f, + 0x2270,0x2271,0x2272,0x2273,0x2274,0x2275,0x2276,0x2277, + 0x2278,0x2279,0x227a,0x227b,0x227c,0x227d,0x227e,0x227f, + 0x2280,0x2281,0x2282,0x2283,0x2284,0x2285,0x2286,0x2287, + 0x2288,0x2289,0x228a,0x228b,0x228c,0x228d,0x228e,0x228f, + 0x2290,0x2291,0x2292,0x2293,0x2294,0x2295,0x2296,0x2297, + 0x2298,0x2299,0x229a,0x229b,0x229c,0x229d,0x229e,0x229f, + 0x22a0,0x22a1,0x22a2,0x22a3,0x22a4,0x22a5,0x22a6,0x22a7, + 0x22a8,0x22a9,0x22aa,0x22ab,0x22ac,0x22ad,0x22ae,0x22af, + 0x22b0,0x22b1,0x22b2,0x22b3,0x22b4,0x22b5,0x22b6,0x22b7, + 0x22b8,0x22b9,0x22ba,0x22bb,0x22bc,0x22bd,0x22be,0x22bf, + 0x22c0,0x22c1,0x22c2,0x22c3,0x22c4,0x22c5,0x22c6,0x22c7, + 0x22c8,0x22c9,0x22ca,0x22cb,0x22cc,0x22cd,0x22ce,0x22cf, + 0x22d0,0x22d1,0x22d2,0x22d3,0x22d4,0x22d5,0x22d6,0x22d7, + 0x22d8,0x22d9,0x22da,0x22db,0x22dc,0x22dd,0x22de,0x22df, + 0x22e0,0x22e1,0x22e2,0x22e3,0x22e4,0x22e5,0x22e6,0x22e7, + 0x22e8,0x22e9,0x22ea,0x22eb,0x22ec,0x22ed,0x22ee,0x22ef, + 0x22f0,0x22f1,0x22f2,0x22f3,0x22f4,0x22f5,0x22f6,0x22f7, + 0x22f8,0x22f9,0x22fa,0x22fb,0x22fc,0x22fd,0x22fe,0x22ff, + 0x2300,0x2301,0x2302,0x2303,0x2304,0x2305,0x2306,0x2307, + 0x2308,0x2309,0x230a,0x230b,0x230c,0x230d,0x230e,0x230f, + 0x2310,0x2311,0x2312,0x2313,0x2314,0x2315,0x2316,0x2317, + 0x2318,0x2319,0x231a,0x231b,0x231c,0x231d,0x231e,0x231f, + 0x2320,0x2321,0x2322,0x2323,0x2324,0x2325,0x2326,0x2327, + 0x2328,0x2329,0x232a,0x232b,0x232c,0x232d,0x232e,0x232f, + 0x2330,0x2331,0x2332,0x2333,0x2334,0x2335,0x2336,0x2337, + 0x2338,0x2339,0x233a,0x233b,0x233c,0x233d,0x233e,0x233f, + 0x2340,0x2341,0x2342,0x2343,0x2344,0x2345,0x2346,0x2347, + 0x2348,0x2349,0x234a,0x234b,0x234c,0x234d,0x234e,0x234f, + 0x2350,0x2351,0x2352,0x2353,0x2354,0x2355,0x2356,0x2357, + 0x2358,0x2359,0x235a,0x235b,0x235c,0x235d,0x235e,0x235f, + 0x2360,0x2361,0x2362,0x2363,0x2364,0x2365,0x2366,0x2367, + 0x2368,0x2369,0x236a,0x236b,0x236c,0x236d,0x236e,0x236f, + 0x2370,0x2371,0x2372,0x2373,0x2374,0x2375,0x2376,0x2377, + 0x2378,0x2379,0x237a,0x237b,0x237c,0x237d,0x237e,0x237f, + 0x2380,0x2381,0x2382,0x2383,0x2384,0x2385,0x2386,0x2387, + 0x2388,0x2389,0x238a,0x238b,0x238c,0x238d,0x238e,0x238f, + 0x2390,0x2391,0x2392,0x2393,0x2394,0x2395,0x2396,0x2397, + 0x2398,0x2399,0x239a,0x239b,0x239c,0x239d,0x239e,0x239f, + 0x23a0,0x23a1,0x23a2,0x23a3,0x23a4,0x23a5,0x23a6,0x23a7, + 0x23a8,0x23a9,0x23aa,0x23ab,0x23ac,0x23ad,0x23ae,0x23af, + 0x23b0,0x23b1,0x23b2,0x23b3,0x23b4,0x23b5,0x23b6,0x23b7, + 0x23b8,0x23b9,0x23ba,0x23bb,0x23bc,0x23bd,0x23be,0x23bf, + 0x23c0,0x23c1,0x23c2,0x23c3,0x23c4,0x23c5,0x23c6,0x23c7, + 0x23c8,0x23c9,0x23ca,0x23cb,0x23cc,0x23cd,0x23ce,0x23cf, + 0x23d0,0x23d1,0x23d2,0x23d3,0x23d4,0x23d5,0x23d6,0x23d7, + 0x23d8,0x23d9,0x23da,0x23db,0x23dc,0x23dd,0x23de,0x23df, + 0x23e0,0x23e1,0x23e2,0x23e3,0x23e4,0x23e5,0x23e6,0x23e7, + 0x23e8,0x23e9,0x23ea,0x23eb,0x23ec,0x23ed,0x23ee,0x23ef, + 0x23f0,0x23f1,0x23f2,0x23f3,0x23f4,0x23f5,0x23f6,0x23f7, + 0x23f8,0x23f9,0x23fa,0x23fb,0x23fc,0x23fd,0x23fe,0x23ff, + 0x2400,0x2401,0x2402,0x2403,0x2404,0x2405,0x2406,0x2407, + 0x2408,0x2409,0x240a,0x240b,0x240c,0x240d,0x240e,0x240f, + 0x2410,0x2411,0x2412,0x2413,0x2414,0x2415,0x2416,0x2417, + 0x2418,0x2419,0x241a,0x241b,0x241c,0x241d,0x241e,0x241f, + 0x2420,0x2421,0x2422,0x2423,0x2424,0x2425,0x2426,0x2427, + 0x2428,0x2429,0x242a,0x242b,0x242c,0x242d,0x242e,0x242f, + 0x2430,0x2431,0x2432,0x2433,0x2434,0x2435,0x2436,0x2437, + 0x2438,0x2439,0x243a,0x243b,0x243c,0x243d,0x243e,0x243f, + 0x2440,0x2441,0x2442,0x2443,0x2444,0x2445,0x2446,0x2447, + 0x2448,0x2449,0x244a,0x244b,0x244c,0x244d,0x244e,0x244f, + 0x2450,0x2451,0x2452,0x2453,0x2454,0x2455,0x2456,0x2457, + 0x2458,0x2459,0x245a,0x245b,0x245c,0x245d,0x245e,0x245f, + 0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467, + 0x2468,0x2469,0x246a,0x246b,0x246c,0x246d,0x246e,0x246f, + 0x2470,0x2471,0x2472,0x2473,0x2474,0x2475,0x2476,0x2477, + 0x2478,0x2479,0x247a,0x247b,0x247c,0x247d,0x247e,0x247f, + 0x2480,0x2481,0x2482,0x2483,0x2484,0x2485,0x2486,0x2487, + 0x2488,0x2489,0x248a,0x248b,0x248c,0x248d,0x248e,0x248f, + 0x2490,0x2491,0x2492,0x2493,0x2494,0x2495,0x2496,0x2497, + 0x2498,0x2499,0x249a,0x249b,0x249c,0x249d,0x249e,0x249f, + 0x24a0,0x24a1,0x24a2,0x24a3,0x24a4,0x24a5,0x24a6,0x24a7, + 0x24a8,0x24a9,0x24aa,0x24ab,0x24ac,0x24ad,0x24ae,0x24af, + 0x24b0,0x24b1,0x24b2,0x24b3,0x24b4,0x24b5,0x24b6,0x24b7, + 0x24b8,0x24b9,0x24ba,0x24bb,0x24bc,0x24bd,0x24be,0x24bf, + 0x24c0,0x24c1,0x24c2,0x24c3,0x24c4,0x24c5,0x24c6,0x24c7, + 0x24c8,0x24c9,0x24ca,0x24cb,0x24cc,0x24cd,0x24ce,0x24cf, + 0x24b6,0x24b7,0x24b8,0x24b9,0x24ba,0x24bb,0x24bc,0x24bd, + 0x24be,0x24bf,0x24c0,0x24c1,0x24c2,0x24c3,0x24c4,0x24c5, + 0x24c6,0x24c7,0x24c8,0x24c9,0x24ca,0x24cb,0x24cc,0x24cd, + 0x24ce,0x24cf,0x24ea,0x24eb,0x24ec,0x24ed,0x24ee,0x24ef, + 0x24f0,0x24f1,0x24f2,0x24f3,0x24f4,0x24f5,0x24f6,0x24f7, + 0x24f8,0x24f9,0x24fa,0x24fb,0x24fc,0x24fd,0x24fe,0x24ff, + 0x2500,0x2501,0x2502,0x2503,0x2504,0x2505,0x2506,0x2507, + 0x2508,0x2509,0x250a,0x250b,0x250c,0x250d,0x250e,0x250f, + 0x2510,0x2511,0x2512,0x2513,0x2514,0x2515,0x2516,0x2517, + 0x2518,0x2519,0x251a,0x251b,0x251c,0x251d,0x251e,0x251f, + 0x2520,0x2521,0x2522,0x2523,0x2524,0x2525,0x2526,0x2527, + 0x2528,0x2529,0x252a,0x252b,0x252c,0x252d,0x252e,0x252f, + 0x2530,0x2531,0x2532,0x2533,0x2534,0x2535,0x2536,0x2537, + 0x2538,0x2539,0x253a,0x253b,0x253c,0x253d,0x253e,0x253f, + 0x2540,0x2541,0x2542,0x2543,0x2544,0x2545,0x2546,0x2547, + 0x2548,0x2549,0x254a,0x254b,0x254c,0x254d,0x254e,0x254f, + 0x2550,0x2551,0x2552,0x2553,0x2554,0x2555,0x2556,0x2557, + 0x2558,0x2559,0x255a,0x255b,0x255c,0x255d,0x255e,0x255f, + 0x2560,0x2561,0x2562,0x2563,0x2564,0x2565,0x2566,0x2567, + 0x2568,0x2569,0x256a,0x256b,0x256c,0x256d,0x256e,0x256f, + 0x2570,0x2571,0x2572,0x2573,0x2574,0x2575,0x2576,0x2577, + 0x2578,0x2579,0x257a,0x257b,0x257c,0x257d,0x257e,0x257f, + 0x2580,0x2581,0x2582,0x2583,0x2584,0x2585,0x2586,0x2587, + 0x2588,0x2589,0x258a,0x258b,0x258c,0x258d,0x258e,0x258f, + 0x2590,0x2591,0x2592,0x2593,0x2594,0x2595,0x2596,0x2597, + 0x2598,0x2599,0x259a,0x259b,0x259c,0x259d,0x259e,0x259f, + 0x25a0,0x25a1,0x25a2,0x25a3,0x25a4,0x25a5,0x25a6,0x25a7, + 0x25a8,0x25a9,0x25aa,0x25ab,0x25ac,0x25ad,0x25ae,0x25af, + 0x25b0,0x25b1,0x25b2,0x25b3,0x25b4,0x25b5,0x25b6,0x25b7, + 0x25b8,0x25b9,0x25ba,0x25bb,0x25bc,0x25bd,0x25be,0x25bf, + 0x25c0,0x25c1,0x25c2,0x25c3,0x25c4,0x25c5,0x25c6,0x25c7, + 0x25c8,0x25c9,0x25ca,0x25cb,0x25cc,0x25cd,0x25ce,0x25cf, + 0x25d0,0x25d1,0x25d2,0x25d3,0x25d4,0x25d5,0x25d6,0x25d7, + 0x25d8,0x25d9,0x25da,0x25db,0x25dc,0x25dd,0x25de,0x25df, + 0x25e0,0x25e1,0x25e2,0x25e3,0x25e4,0x25e5,0x25e6,0x25e7, + 0x25e8,0x25e9,0x25ea,0x25eb,0x25ec,0x25ed,0x25ee,0x25ef, + 0x25f0,0x25f1,0x25f2,0x25f3,0x25f4,0x25f5,0x25f6,0x25f7, + 0x25f8,0x25f9,0x25fa,0x25fb,0x25fc,0x25fd,0x25fe,0x25ff, + 0x2600,0x2601,0x2602,0x2603,0x2604,0x2605,0x2606,0x2607, + 0x2608,0x2609,0x260a,0x260b,0x260c,0x260d,0x260e,0x260f, + 0x2610,0x2611,0x2612,0x2613,0x2614,0x2615,0x2616,0x2617, + 0x2618,0x2619,0x261a,0x261b,0x261c,0x261d,0x261e,0x261f, + 0x2620,0x2621,0x2622,0x2623,0x2624,0x2625,0x2626,0x2627, + 0x2628,0x2629,0x262a,0x262b,0x262c,0x262d,0x262e,0x262f, + 0x2630,0x2631,0x2632,0x2633,0x2634,0x2635,0x2636,0x2637, + 0x2638,0x2639,0x263a,0x263b,0x263c,0x263d,0x263e,0x263f, + 0x2640,0x2641,0x2642,0x2643,0x2644,0x2645,0x2646,0x2647, + 0x2648,0x2649,0x264a,0x264b,0x264c,0x264d,0x264e,0x264f, + 0x2650,0x2651,0x2652,0x2653,0x2654,0x2655,0x2656,0x2657, + 0x2658,0x2659,0x265a,0x265b,0x265c,0x265d,0x265e,0x265f, + 0x2660,0x2661,0x2662,0x2663,0x2664,0x2665,0x2666,0x2667, + 0x2668,0x2669,0x266a,0x266b,0x266c,0x266d,0x266e,0x266f, + 0x2670,0x2671,0x2672,0x2673,0x2674,0x2675,0x2676,0x2677, + 0x2678,0x2679,0x267a,0x267b,0x267c,0x267d,0x267e,0x267f, + 0x2680,0x2681,0x2682,0x2683,0x2684,0x2685,0x2686,0x2687, + 0x2688,0x2689,0x268a,0x268b,0x268c,0x268d,0x268e,0x268f, + 0x2690,0x2691,0x2692,0x2693,0x2694,0x2695,0x2696,0x2697, + 0x2698,0x2699,0x269a,0x269b,0x269c,0x269d,0x269e,0x269f, + 0x26a0,0x26a1,0x26a2,0x26a3,0x26a4,0x26a5,0x26a6,0x26a7, + 0x26a8,0x26a9,0x26aa,0x26ab,0x26ac,0x26ad,0x26ae,0x26af, + 0x26b0,0x26b1,0x26b2,0x26b3,0x26b4,0x26b5,0x26b6,0x26b7, + 0x26b8,0x26b9,0x26ba,0x26bb,0x26bc,0x26bd,0x26be,0x26bf, + 0x26c0,0x26c1,0x26c2,0x26c3,0x26c4,0x26c5,0x26c6,0x26c7, + 0x26c8,0x26c9,0x26ca,0x26cb,0x26cc,0x26cd,0x26ce,0x26cf, + 0x26d0,0x26d1,0x26d2,0x26d3,0x26d4,0x26d5,0x26d6,0x26d7, + 0x26d8,0x26d9,0x26da,0x26db,0x26dc,0x26dd,0x26de,0x26df, + 0x26e0,0x26e1,0x26e2,0x26e3,0x26e4,0x26e5,0x26e6,0x26e7, + 0x26e8,0x26e9,0x26ea,0x26eb,0x26ec,0x26ed,0x26ee,0x26ef, + 0x26f0,0x26f1,0x26f2,0x26f3,0x26f4,0x26f5,0x26f6,0x26f7, + 0x26f8,0x26f9,0x26fa,0x26fb,0x26fc,0x26fd,0x26fe,0x26ff, + 0x2700,0x2701,0x2702,0x2703,0x2704,0x2705,0x2706,0x2707, + 0x2708,0x2709,0x270a,0x270b,0x270c,0x270d,0x270e,0x270f, + 0x2710,0x2711,0x2712,0x2713,0x2714,0x2715,0x2716,0x2717, + 0x2718,0x2719,0x271a,0x271b,0x271c,0x271d,0x271e,0x271f, + 0x2720,0x2721,0x2722,0x2723,0x2724,0x2725,0x2726,0x2727, + 0x2728,0x2729,0x272a,0x272b,0x272c,0x272d,0x272e,0x272f, + 0x2730,0x2731,0x2732,0x2733,0x2734,0x2735,0x2736,0x2737, + 0x2738,0x2739,0x273a,0x273b,0x273c,0x273d,0x273e,0x273f, + 0x2740,0x2741,0x2742,0x2743,0x2744,0x2745,0x2746,0x2747, + 0x2748,0x2749,0x274a,0x274b,0x274c,0x274d,0x274e,0x274f, + 0x2750,0x2751,0x2752,0x2753,0x2754,0x2755,0x2756,0x2757, + 0x2758,0x2759,0x275a,0x275b,0x275c,0x275d,0x275e,0x275f, + 0x2760,0x2761,0x2762,0x2763,0x2764,0x2765,0x2766,0x2767, + 0x2768,0x2769,0x276a,0x276b,0x276c,0x276d,0x276e,0x276f, + 0x2770,0x2771,0x2772,0x2773,0x2774,0x2775,0x2776,0x2777, + 0x2778,0x2779,0x277a,0x277b,0x277c,0x277d,0x277e,0x277f, + 0x2780,0x2781,0x2782,0x2783,0x2784,0x2785,0x2786,0x2787, + 0x2788,0x2789,0x278a,0x278b,0x278c,0x278d,0x278e,0x278f, + 0x2790,0x2791,0x2792,0x2793,0x2794,0x2795,0x2796,0x2797, + 0x2798,0x2799,0x279a,0x279b,0x279c,0x279d,0x279e,0x279f, + 0x27a0,0x27a1,0x27a2,0x27a3,0x27a4,0x27a5,0x27a6,0x27a7, + 0x27a8,0x27a9,0x27aa,0x27ab,0x27ac,0x27ad,0x27ae,0x27af, + 0x27b0,0x27b1,0x27b2,0x27b3,0x27b4,0x27b5,0x27b6,0x27b7, + 0x27b8,0x27b9,0x27ba,0x27bb,0x27bc,0x27bd,0x27be,0x27bf, + 0x27c0,0x27c1,0x27c2,0x27c3,0x27c4,0x27c5,0x27c6,0x27c7, + 0x27c8,0x27c9,0x27ca,0x27cb,0x27cc,0x27cd,0x27ce,0x27cf, + 0x27d0,0x27d1,0x27d2,0x27d3,0x27d4,0x27d5,0x27d6,0x27d7, + 0x27d8,0x27d9,0x27da,0x27db,0x27dc,0x27dd,0x27de,0x27df, + 0x27e0,0x27e1,0x27e2,0x27e3,0x27e4,0x27e5,0x27e6,0x27e7, + 0x27e8,0x27e9,0x27ea,0x27eb,0x27ec,0x27ed,0x27ee,0x27ef, + 0x27f0,0x27f1,0x27f2,0x27f3,0x27f4,0x27f5,0x27f6,0x27f7, + 0x27f8,0x27f9,0x27fa,0x27fb,0x27fc,0x27fd,0x27fe,0x27ff, + 0x2800,0x2801,0x2802,0x2803,0x2804,0x2805,0x2806,0x2807, + 0x2808,0x2809,0x280a,0x280b,0x280c,0x280d,0x280e,0x280f, + 0x2810,0x2811,0x2812,0x2813,0x2814,0x2815,0x2816,0x2817, + 0x2818,0x2819,0x281a,0x281b,0x281c,0x281d,0x281e,0x281f, + 0x2820,0x2821,0x2822,0x2823,0x2824,0x2825,0x2826,0x2827, + 0x2828,0x2829,0x282a,0x282b,0x282c,0x282d,0x282e,0x282f, + 0x2830,0x2831,0x2832,0x2833,0x2834,0x2835,0x2836,0x2837, + 0x2838,0x2839,0x283a,0x283b,0x283c,0x283d,0x283e,0x283f, + 0x2840,0x2841,0x2842,0x2843,0x2844,0x2845,0x2846,0x2847, + 0x2848,0x2849,0x284a,0x284b,0x284c,0x284d,0x284e,0x284f, + 0x2850,0x2851,0x2852,0x2853,0x2854,0x2855,0x2856,0x2857, + 0x2858,0x2859,0x285a,0x285b,0x285c,0x285d,0x285e,0x285f, + 0x2860,0x2861,0x2862,0x2863,0x2864,0x2865,0x2866,0x2867, + 0x2868,0x2869,0x286a,0x286b,0x286c,0x286d,0x286e,0x286f, + 0x2870,0x2871,0x2872,0x2873,0x2874,0x2875,0x2876,0x2877, + 0x2878,0x2879,0x287a,0x287b,0x287c,0x287d,0x287e,0x287f, + 0x2880,0x2881,0x2882,0x2883,0x2884,0x2885,0x2886,0x2887, + 0x2888,0x2889,0x288a,0x288b,0x288c,0x288d,0x288e,0x288f, + 0x2890,0x2891,0x2892,0x2893,0x2894,0x2895,0x2896,0x2897, + 0x2898,0x2899,0x289a,0x289b,0x289c,0x289d,0x289e,0x289f, + 0x28a0,0x28a1,0x28a2,0x28a3,0x28a4,0x28a5,0x28a6,0x28a7, + 0x28a8,0x28a9,0x28aa,0x28ab,0x28ac,0x28ad,0x28ae,0x28af, + 0x28b0,0x28b1,0x28b2,0x28b3,0x28b4,0x28b5,0x28b6,0x28b7, + 0x28b8,0x28b9,0x28ba,0x28bb,0x28bc,0x28bd,0x28be,0x28bf, + 0x28c0,0x28c1,0x28c2,0x28c3,0x28c4,0x28c5,0x28c6,0x28c7, + 0x28c8,0x28c9,0x28ca,0x28cb,0x28cc,0x28cd,0x28ce,0x28cf, + 0x28d0,0x28d1,0x28d2,0x28d3,0x28d4,0x28d5,0x28d6,0x28d7, + 0x28d8,0x28d9,0x28da,0x28db,0x28dc,0x28dd,0x28de,0x28df, + 0x28e0,0x28e1,0x28e2,0x28e3,0x28e4,0x28e5,0x28e6,0x28e7, + 0x28e8,0x28e9,0x28ea,0x28eb,0x28ec,0x28ed,0x28ee,0x28ef, + 0x28f0,0x28f1,0x28f2,0x28f3,0x28f4,0x28f5,0x28f6,0x28f7, + 0x28f8,0x28f9,0x28fa,0x28fb,0x28fc,0x28fd,0x28fe,0x28ff, + 0x2900,0x2901,0x2902,0x2903,0x2904,0x2905,0x2906,0x2907, + 0x2908,0x2909,0x290a,0x290b,0x290c,0x290d,0x290e,0x290f, + 0x2910,0x2911,0x2912,0x2913,0x2914,0x2915,0x2916,0x2917, + 0x2918,0x2919,0x291a,0x291b,0x291c,0x291d,0x291e,0x291f, + 0x2920,0x2921,0x2922,0x2923,0x2924,0x2925,0x2926,0x2927, + 0x2928,0x2929,0x292a,0x292b,0x292c,0x292d,0x292e,0x292f, + 0x2930,0x2931,0x2932,0x2933,0x2934,0x2935,0x2936,0x2937, + 0x2938,0x2939,0x293a,0x293b,0x293c,0x293d,0x293e,0x293f, + 0x2940,0x2941,0x2942,0x2943,0x2944,0x2945,0x2946,0x2947, + 0x2948,0x2949,0x294a,0x294b,0x294c,0x294d,0x294e,0x294f, + 0x2950,0x2951,0x2952,0x2953,0x2954,0x2955,0x2956,0x2957, + 0x2958,0x2959,0x295a,0x295b,0x295c,0x295d,0x295e,0x295f, + 0x2960,0x2961,0x2962,0x2963,0x2964,0x2965,0x2966,0x2967, + 0x2968,0x2969,0x296a,0x296b,0x296c,0x296d,0x296e,0x296f, + 0x2970,0x2971,0x2972,0x2973,0x2974,0x2975,0x2976,0x2977, + 0x2978,0x2979,0x297a,0x297b,0x297c,0x297d,0x297e,0x297f, + 0x2980,0x2981,0x2982,0x2983,0x2984,0x2985,0x2986,0x2987, + 0x2988,0x2989,0x298a,0x298b,0x298c,0x298d,0x298e,0x298f, + 0x2990,0x2991,0x2992,0x2993,0x2994,0x2995,0x2996,0x2997, + 0x2998,0x2999,0x299a,0x299b,0x299c,0x299d,0x299e,0x299f, + 0x29a0,0x29a1,0x29a2,0x29a3,0x29a4,0x29a5,0x29a6,0x29a7, + 0x29a8,0x29a9,0x29aa,0x29ab,0x29ac,0x29ad,0x29ae,0x29af, + 0x29b0,0x29b1,0x29b2,0x29b3,0x29b4,0x29b5,0x29b6,0x29b7, + 0x29b8,0x29b9,0x29ba,0x29bb,0x29bc,0x29bd,0x29be,0x29bf, + 0x29c0,0x29c1,0x29c2,0x29c3,0x29c4,0x29c5,0x29c6,0x29c7, + 0x29c8,0x29c9,0x29ca,0x29cb,0x29cc,0x29cd,0x29ce,0x29cf, + 0x29d0,0x29d1,0x29d2,0x29d3,0x29d4,0x29d5,0x29d6,0x29d7, + 0x29d8,0x29d9,0x29da,0x29db,0x29dc,0x29dd,0x29de,0x29df, + 0x29e0,0x29e1,0x29e2,0x29e3,0x29e4,0x29e5,0x29e6,0x29e7, + 0x29e8,0x29e9,0x29ea,0x29eb,0x29ec,0x29ed,0x29ee,0x29ef, + 0x29f0,0x29f1,0x29f2,0x29f3,0x29f4,0x29f5,0x29f6,0x29f7, + 0x29f8,0x29f9,0x29fa,0x29fb,0x29fc,0x29fd,0x29fe,0x29ff, + 0x2a00,0x2a01,0x2a02,0x2a03,0x2a04,0x2a05,0x2a06,0x2a07, + 0x2a08,0x2a09,0x2a0a,0x2a0b,0x2a0c,0x2a0d,0x2a0e,0x2a0f, + 0x2a10,0x2a11,0x2a12,0x2a13,0x2a14,0x2a15,0x2a16,0x2a17, + 0x2a18,0x2a19,0x2a1a,0x2a1b,0x2a1c,0x2a1d,0x2a1e,0x2a1f, + 0x2a20,0x2a21,0x2a22,0x2a23,0x2a24,0x2a25,0x2a26,0x2a27, + 0x2a28,0x2a29,0x2a2a,0x2a2b,0x2a2c,0x2a2d,0x2a2e,0x2a2f, + 0x2a30,0x2a31,0x2a32,0x2a33,0x2a34,0x2a35,0x2a36,0x2a37, + 0x2a38,0x2a39,0x2a3a,0x2a3b,0x2a3c,0x2a3d,0x2a3e,0x2a3f, + 0x2a40,0x2a41,0x2a42,0x2a43,0x2a44,0x2a45,0x2a46,0x2a47, + 0x2a48,0x2a49,0x2a4a,0x2a4b,0x2a4c,0x2a4d,0x2a4e,0x2a4f, + 0x2a50,0x2a51,0x2a52,0x2a53,0x2a54,0x2a55,0x2a56,0x2a57, + 0x2a58,0x2a59,0x2a5a,0x2a5b,0x2a5c,0x2a5d,0x2a5e,0x2a5f, + 0x2a60,0x2a61,0x2a62,0x2a63,0x2a64,0x2a65,0x2a66,0x2a67, + 0x2a68,0x2a69,0x2a6a,0x2a6b,0x2a6c,0x2a6d,0x2a6e,0x2a6f, + 0x2a70,0x2a71,0x2a72,0x2a73,0x2a74,0x2a75,0x2a76,0x2a77, + 0x2a78,0x2a79,0x2a7a,0x2a7b,0x2a7c,0x2a7d,0x2a7e,0x2a7f, + 0x2a80,0x2a81,0x2a82,0x2a83,0x2a84,0x2a85,0x2a86,0x2a87, + 0x2a88,0x2a89,0x2a8a,0x2a8b,0x2a8c,0x2a8d,0x2a8e,0x2a8f, + 0x2a90,0x2a91,0x2a92,0x2a93,0x2a94,0x2a95,0x2a96,0x2a97, + 0x2a98,0x2a99,0x2a9a,0x2a9b,0x2a9c,0x2a9d,0x2a9e,0x2a9f, + 0x2aa0,0x2aa1,0x2aa2,0x2aa3,0x2aa4,0x2aa5,0x2aa6,0x2aa7, + 0x2aa8,0x2aa9,0x2aaa,0x2aab,0x2aac,0x2aad,0x2aae,0x2aaf, + 0x2ab0,0x2ab1,0x2ab2,0x2ab3,0x2ab4,0x2ab5,0x2ab6,0x2ab7, + 0x2ab8,0x2ab9,0x2aba,0x2abb,0x2abc,0x2abd,0x2abe,0x2abf, + 0x2ac0,0x2ac1,0x2ac2,0x2ac3,0x2ac4,0x2ac5,0x2ac6,0x2ac7, + 0x2ac8,0x2ac9,0x2aca,0x2acb,0x2acc,0x2acd,0x2ace,0x2acf, + 0x2ad0,0x2ad1,0x2ad2,0x2ad3,0x2ad4,0x2ad5,0x2ad6,0x2ad7, + 0x2ad8,0x2ad9,0x2ada,0x2adb,0x2adc,0x2add,0x2ade,0x2adf, + 0x2ae0,0x2ae1,0x2ae2,0x2ae3,0x2ae4,0x2ae5,0x2ae6,0x2ae7, + 0x2ae8,0x2ae9,0x2aea,0x2aeb,0x2aec,0x2aed,0x2aee,0x2aef, + 0x2af0,0x2af1,0x2af2,0x2af3,0x2af4,0x2af5,0x2af6,0x2af7, + 0x2af8,0x2af9,0x2afa,0x2afb,0x2afc,0x2afd,0x2afe,0x2aff, + 0x2b00,0x2b01,0x2b02,0x2b03,0x2b04,0x2b05,0x2b06,0x2b07, + 0x2b08,0x2b09,0x2b0a,0x2b0b,0x2b0c,0x2b0d,0x2b0e,0x2b0f, + 0x2b10,0x2b11,0x2b12,0x2b13,0x2b14,0x2b15,0x2b16,0x2b17, + 0x2b18,0x2b19,0x2b1a,0x2b1b,0x2b1c,0x2b1d,0x2b1e,0x2b1f, + 0x2b20,0x2b21,0x2b22,0x2b23,0x2b24,0x2b25,0x2b26,0x2b27, + 0x2b28,0x2b29,0x2b2a,0x2b2b,0x2b2c,0x2b2d,0x2b2e,0x2b2f, + 0x2b30,0x2b31,0x2b32,0x2b33,0x2b34,0x2b35,0x2b36,0x2b37, + 0x2b38,0x2b39,0x2b3a,0x2b3b,0x2b3c,0x2b3d,0x2b3e,0x2b3f, + 0x2b40,0x2b41,0x2b42,0x2b43,0x2b44,0x2b45,0x2b46,0x2b47, + 0x2b48,0x2b49,0x2b4a,0x2b4b,0x2b4c,0x2b4d,0x2b4e,0x2b4f, + 0x2b50,0x2b51,0x2b52,0x2b53,0x2b54,0x2b55,0x2b56,0x2b57, + 0x2b58,0x2b59,0x2b5a,0x2b5b,0x2b5c,0x2b5d,0x2b5e,0x2b5f, + 0x2b60,0x2b61,0x2b62,0x2b63,0x2b64,0x2b65,0x2b66,0x2b67, + 0x2b68,0x2b69,0x2b6a,0x2b6b,0x2b6c,0x2b6d,0x2b6e,0x2b6f, + 0x2b70,0x2b71,0x2b72,0x2b73,0x2b74,0x2b75,0x2b76,0x2b77, + 0x2b78,0x2b79,0x2b7a,0x2b7b,0x2b7c,0x2b7d,0x2b7e,0x2b7f, + 0x2b80,0x2b81,0x2b82,0x2b83,0x2b84,0x2b85,0x2b86,0x2b87, + 0x2b88,0x2b89,0x2b8a,0x2b8b,0x2b8c,0x2b8d,0x2b8e,0x2b8f, + 0x2b90,0x2b91,0x2b92,0x2b93,0x2b94,0x2b95,0x2b96,0x2b97, + 0x2b98,0x2b99,0x2b9a,0x2b9b,0x2b9c,0x2b9d,0x2b9e,0x2b9f, + 0x2ba0,0x2ba1,0x2ba2,0x2ba3,0x2ba4,0x2ba5,0x2ba6,0x2ba7, + 0x2ba8,0x2ba9,0x2baa,0x2bab,0x2bac,0x2bad,0x2bae,0x2baf, + 0x2bb0,0x2bb1,0x2bb2,0x2bb3,0x2bb4,0x2bb5,0x2bb6,0x2bb7, + 0x2bb8,0x2bb9,0x2bba,0x2bbb,0x2bbc,0x2bbd,0x2bbe,0x2bbf, + 0x2bc0,0x2bc1,0x2bc2,0x2bc3,0x2bc4,0x2bc5,0x2bc6,0x2bc7, + 0x2bc8,0x2bc9,0x2bca,0x2bcb,0x2bcc,0x2bcd,0x2bce,0x2bcf, + 0x2bd0,0x2bd1,0x2bd2,0x2bd3,0x2bd4,0x2bd5,0x2bd6,0x2bd7, + 0x2bd8,0x2bd9,0x2bda,0x2bdb,0x2bdc,0x2bdd,0x2bde,0x2bdf, + 0x2be0,0x2be1,0x2be2,0x2be3,0x2be4,0x2be5,0x2be6,0x2be7, + 0x2be8,0x2be9,0x2bea,0x2beb,0x2bec,0x2bed,0x2bee,0x2bef, + 0x2bf0,0x2bf1,0x2bf2,0x2bf3,0x2bf4,0x2bf5,0x2bf6,0x2bf7, + 0x2bf8,0x2bf9,0x2bfa,0x2bfb,0x2bfc,0x2bfd,0x2bfe,0x2bff, + 0x2c00,0x2c01,0x2c02,0x2c03,0x2c04,0x2c05,0x2c06,0x2c07, + 0x2c08,0x2c09,0x2c0a,0x2c0b,0x2c0c,0x2c0d,0x2c0e,0x2c0f, + 0x2c10,0x2c11,0x2c12,0x2c13,0x2c14,0x2c15,0x2c16,0x2c17, + 0x2c18,0x2c19,0x2c1a,0x2c1b,0x2c1c,0x2c1d,0x2c1e,0x2c1f, + 0x2c20,0x2c21,0x2c22,0x2c23,0x2c24,0x2c25,0x2c26,0x2c27, + 0x2c28,0x2c29,0x2c2a,0x2c2b,0x2c2c,0x2c2d,0x2c2e,0x2c2f, + 0x2c30,0x2c31,0x2c32,0x2c33,0x2c34,0x2c35,0x2c36,0x2c37, + 0x2c38,0x2c39,0x2c3a,0x2c3b,0x2c3c,0x2c3d,0x2c3e,0x2c3f, + 0x2c40,0x2c41,0x2c42,0x2c43,0x2c44,0x2c45,0x2c46,0x2c47, + 0x2c48,0x2c49,0x2c4a,0x2c4b,0x2c4c,0x2c4d,0x2c4e,0x2c4f, + 0x2c50,0x2c51,0x2c52,0x2c53,0x2c54,0x2c55,0x2c56,0x2c57, + 0x2c58,0x2c59,0x2c5a,0x2c5b,0x2c5c,0x2c5d,0x2c5e,0x2c5f, + 0x2c60,0x2c61,0x2c62,0x2c63,0x2c64,0x2c65,0x2c66,0x2c67, + 0x2c68,0x2c69,0x2c6a,0x2c6b,0x2c6c,0x2c6d,0x2c6e,0x2c6f, + 0x2c70,0x2c71,0x2c72,0x2c73,0x2c74,0x2c75,0x2c76,0x2c77, + 0x2c78,0x2c79,0x2c7a,0x2c7b,0x2c7c,0x2c7d,0x2c7e,0x2c7f, + 0x2c80,0x2c81,0x2c82,0x2c83,0x2c84,0x2c85,0x2c86,0x2c87, + 0x2c88,0x2c89,0x2c8a,0x2c8b,0x2c8c,0x2c8d,0x2c8e,0x2c8f, + 0x2c90,0x2c91,0x2c92,0x2c93,0x2c94,0x2c95,0x2c96,0x2c97, + 0x2c98,0x2c99,0x2c9a,0x2c9b,0x2c9c,0x2c9d,0x2c9e,0x2c9f, + 0x2ca0,0x2ca1,0x2ca2,0x2ca3,0x2ca4,0x2ca5,0x2ca6,0x2ca7, + 0x2ca8,0x2ca9,0x2caa,0x2cab,0x2cac,0x2cad,0x2cae,0x2caf, + 0x2cb0,0x2cb1,0x2cb2,0x2cb3,0x2cb4,0x2cb5,0x2cb6,0x2cb7, + 0x2cb8,0x2cb9,0x2cba,0x2cbb,0x2cbc,0x2cbd,0x2cbe,0x2cbf, + 0x2cc0,0x2cc1,0x2cc2,0x2cc3,0x2cc4,0x2cc5,0x2cc6,0x2cc7, + 0x2cc8,0x2cc9,0x2cca,0x2ccb,0x2ccc,0x2ccd,0x2cce,0x2ccf, + 0x2cd0,0x2cd1,0x2cd2,0x2cd3,0x2cd4,0x2cd5,0x2cd6,0x2cd7, + 0x2cd8,0x2cd9,0x2cda,0x2cdb,0x2cdc,0x2cdd,0x2cde,0x2cdf, + 0x2ce0,0x2ce1,0x2ce2,0x2ce3,0x2ce4,0x2ce5,0x2ce6,0x2ce7, + 0x2ce8,0x2ce9,0x2cea,0x2ceb,0x2cec,0x2ced,0x2cee,0x2cef, + 0x2cf0,0x2cf1,0x2cf2,0x2cf3,0x2cf4,0x2cf5,0x2cf6,0x2cf7, + 0x2cf8,0x2cf9,0x2cfa,0x2cfb,0x2cfc,0x2cfd,0x2cfe,0x2cff, + 0x2d00,0x2d01,0x2d02,0x2d03,0x2d04,0x2d05,0x2d06,0x2d07, + 0x2d08,0x2d09,0x2d0a,0x2d0b,0x2d0c,0x2d0d,0x2d0e,0x2d0f, + 0x2d10,0x2d11,0x2d12,0x2d13,0x2d14,0x2d15,0x2d16,0x2d17, + 0x2d18,0x2d19,0x2d1a,0x2d1b,0x2d1c,0x2d1d,0x2d1e,0x2d1f, + 0x2d20,0x2d21,0x2d22,0x2d23,0x2d24,0x2d25,0x2d26,0x2d27, + 0x2d28,0x2d29,0x2d2a,0x2d2b,0x2d2c,0x2d2d,0x2d2e,0x2d2f, + 0x2d30,0x2d31,0x2d32,0x2d33,0x2d34,0x2d35,0x2d36,0x2d37, + 0x2d38,0x2d39,0x2d3a,0x2d3b,0x2d3c,0x2d3d,0x2d3e,0x2d3f, + 0x2d40,0x2d41,0x2d42,0x2d43,0x2d44,0x2d45,0x2d46,0x2d47, + 0x2d48,0x2d49,0x2d4a,0x2d4b,0x2d4c,0x2d4d,0x2d4e,0x2d4f, + 0x2d50,0x2d51,0x2d52,0x2d53,0x2d54,0x2d55,0x2d56,0x2d57, + 0x2d58,0x2d59,0x2d5a,0x2d5b,0x2d5c,0x2d5d,0x2d5e,0x2d5f, + 0x2d60,0x2d61,0x2d62,0x2d63,0x2d64,0x2d65,0x2d66,0x2d67, + 0x2d68,0x2d69,0x2d6a,0x2d6b,0x2d6c,0x2d6d,0x2d6e,0x2d6f, + 0x2d70,0x2d71,0x2d72,0x2d73,0x2d74,0x2d75,0x2d76,0x2d77, + 0x2d78,0x2d79,0x2d7a,0x2d7b,0x2d7c,0x2d7d,0x2d7e,0x2d7f, + 0x2d80,0x2d81,0x2d82,0x2d83,0x2d84,0x2d85,0x2d86,0x2d87, + 0x2d88,0x2d89,0x2d8a,0x2d8b,0x2d8c,0x2d8d,0x2d8e,0x2d8f, + 0x2d90,0x2d91,0x2d92,0x2d93,0x2d94,0x2d95,0x2d96,0x2d97, + 0x2d98,0x2d99,0x2d9a,0x2d9b,0x2d9c,0x2d9d,0x2d9e,0x2d9f, + 0x2da0,0x2da1,0x2da2,0x2da3,0x2da4,0x2da5,0x2da6,0x2da7, + 0x2da8,0x2da9,0x2daa,0x2dab,0x2dac,0x2dad,0x2dae,0x2daf, + 0x2db0,0x2db1,0x2db2,0x2db3,0x2db4,0x2db5,0x2db6,0x2db7, + 0x2db8,0x2db9,0x2dba,0x2dbb,0x2dbc,0x2dbd,0x2dbe,0x2dbf, + 0x2dc0,0x2dc1,0x2dc2,0x2dc3,0x2dc4,0x2dc5,0x2dc6,0x2dc7, + 0x2dc8,0x2dc9,0x2dca,0x2dcb,0x2dcc,0x2dcd,0x2dce,0x2dcf, + 0x2dd0,0x2dd1,0x2dd2,0x2dd3,0x2dd4,0x2dd5,0x2dd6,0x2dd7, + 0x2dd8,0x2dd9,0x2dda,0x2ddb,0x2ddc,0x2ddd,0x2dde,0x2ddf, + 0x2de0,0x2de1,0x2de2,0x2de3,0x2de4,0x2de5,0x2de6,0x2de7, + 0x2de8,0x2de9,0x2dea,0x2deb,0x2dec,0x2ded,0x2dee,0x2def, + 0x2df0,0x2df1,0x2df2,0x2df3,0x2df4,0x2df5,0x2df6,0x2df7, + 0x2df8,0x2df9,0x2dfa,0x2dfb,0x2dfc,0x2dfd,0x2dfe,0x2dff, + 0x2e00,0x2e01,0x2e02,0x2e03,0x2e04,0x2e05,0x2e06,0x2e07, + 0x2e08,0x2e09,0x2e0a,0x2e0b,0x2e0c,0x2e0d,0x2e0e,0x2e0f, + 0x2e10,0x2e11,0x2e12,0x2e13,0x2e14,0x2e15,0x2e16,0x2e17, + 0x2e18,0x2e19,0x2e1a,0x2e1b,0x2e1c,0x2e1d,0x2e1e,0x2e1f, + 0x2e20,0x2e21,0x2e22,0x2e23,0x2e24,0x2e25,0x2e26,0x2e27, + 0x2e28,0x2e29,0x2e2a,0x2e2b,0x2e2c,0x2e2d,0x2e2e,0x2e2f, + 0x2e30,0x2e31,0x2e32,0x2e33,0x2e34,0x2e35,0x2e36,0x2e37, + 0x2e38,0x2e39,0x2e3a,0x2e3b,0x2e3c,0x2e3d,0x2e3e,0x2e3f, + 0x2e40,0x2e41,0x2e42,0x2e43,0x2e44,0x2e45,0x2e46,0x2e47, + 0x2e48,0x2e49,0x2e4a,0x2e4b,0x2e4c,0x2e4d,0x2e4e,0x2e4f, + 0x2e50,0x2e51,0x2e52,0x2e53,0x2e54,0x2e55,0x2e56,0x2e57, + 0x2e58,0x2e59,0x2e5a,0x2e5b,0x2e5c,0x2e5d,0x2e5e,0x2e5f, + 0x2e60,0x2e61,0x2e62,0x2e63,0x2e64,0x2e65,0x2e66,0x2e67, + 0x2e68,0x2e69,0x2e6a,0x2e6b,0x2e6c,0x2e6d,0x2e6e,0x2e6f, + 0x2e70,0x2e71,0x2e72,0x2e73,0x2e74,0x2e75,0x2e76,0x2e77, + 0x2e78,0x2e79,0x2e7a,0x2e7b,0x2e7c,0x2e7d,0x2e7e,0x2e7f, + 0x2e80,0x2e81,0x2e82,0x2e83,0x2e84,0x2e85,0x2e86,0x2e87, + 0x2e88,0x2e89,0x2e8a,0x2e8b,0x2e8c,0x2e8d,0x2e8e,0x2e8f, + 0x2e90,0x2e91,0x2e92,0x2e93,0x2e94,0x2e95,0x2e96,0x2e97, + 0x2e98,0x2e99,0x2e9a,0x2e9b,0x2e9c,0x2e9d,0x2e9e,0x2e9f, + 0x2ea0,0x2ea1,0x2ea2,0x2ea3,0x2ea4,0x2ea5,0x2ea6,0x2ea7, + 0x2ea8,0x2ea9,0x2eaa,0x2eab,0x2eac,0x2ead,0x2eae,0x2eaf, + 0x2eb0,0x2eb1,0x2eb2,0x2eb3,0x2eb4,0x2eb5,0x2eb6,0x2eb7, + 0x2eb8,0x2eb9,0x2eba,0x2ebb,0x2ebc,0x2ebd,0x2ebe,0x2ebf, + 0x2ec0,0x2ec1,0x2ec2,0x2ec3,0x2ec4,0x2ec5,0x2ec6,0x2ec7, + 0x2ec8,0x2ec9,0x2eca,0x2ecb,0x2ecc,0x2ecd,0x2ece,0x2ecf, + 0x2ed0,0x2ed1,0x2ed2,0x2ed3,0x2ed4,0x2ed5,0x2ed6,0x2ed7, + 0x2ed8,0x2ed9,0x2eda,0x2edb,0x2edc,0x2edd,0x2ede,0x2edf, + 0x2ee0,0x2ee1,0x2ee2,0x2ee3,0x2ee4,0x2ee5,0x2ee6,0x2ee7, + 0x2ee8,0x2ee9,0x2eea,0x2eeb,0x2eec,0x2eed,0x2eee,0x2eef, + 0x2ef0,0x2ef1,0x2ef2,0x2ef3,0x2ef4,0x2ef5,0x2ef6,0x2ef7, + 0x2ef8,0x2ef9,0x2efa,0x2efb,0x2efc,0x2efd,0x2efe,0x2eff, + 0x2f00,0x2f01,0x2f02,0x2f03,0x2f04,0x2f05,0x2f06,0x2f07, + 0x2f08,0x2f09,0x2f0a,0x2f0b,0x2f0c,0x2f0d,0x2f0e,0x2f0f, + 0x2f10,0x2f11,0x2f12,0x2f13,0x2f14,0x2f15,0x2f16,0x2f17, + 0x2f18,0x2f19,0x2f1a,0x2f1b,0x2f1c,0x2f1d,0x2f1e,0x2f1f, + 0x2f20,0x2f21,0x2f22,0x2f23,0x2f24,0x2f25,0x2f26,0x2f27, + 0x2f28,0x2f29,0x2f2a,0x2f2b,0x2f2c,0x2f2d,0x2f2e,0x2f2f, + 0x2f30,0x2f31,0x2f32,0x2f33,0x2f34,0x2f35,0x2f36,0x2f37, + 0x2f38,0x2f39,0x2f3a,0x2f3b,0x2f3c,0x2f3d,0x2f3e,0x2f3f, + 0x2f40,0x2f41,0x2f42,0x2f43,0x2f44,0x2f45,0x2f46,0x2f47, + 0x2f48,0x2f49,0x2f4a,0x2f4b,0x2f4c,0x2f4d,0x2f4e,0x2f4f, + 0x2f50,0x2f51,0x2f52,0x2f53,0x2f54,0x2f55,0x2f56,0x2f57, + 0x2f58,0x2f59,0x2f5a,0x2f5b,0x2f5c,0x2f5d,0x2f5e,0x2f5f, + 0x2f60,0x2f61,0x2f62,0x2f63,0x2f64,0x2f65,0x2f66,0x2f67, + 0x2f68,0x2f69,0x2f6a,0x2f6b,0x2f6c,0x2f6d,0x2f6e,0x2f6f, + 0x2f70,0x2f71,0x2f72,0x2f73,0x2f74,0x2f75,0x2f76,0x2f77, + 0x2f78,0x2f79,0x2f7a,0x2f7b,0x2f7c,0x2f7d,0x2f7e,0x2f7f, + 0x2f80,0x2f81,0x2f82,0x2f83,0x2f84,0x2f85,0x2f86,0x2f87, + 0x2f88,0x2f89,0x2f8a,0x2f8b,0x2f8c,0x2f8d,0x2f8e,0x2f8f, + 0x2f90,0x2f91,0x2f92,0x2f93,0x2f94,0x2f95,0x2f96,0x2f97, + 0x2f98,0x2f99,0x2f9a,0x2f9b,0x2f9c,0x2f9d,0x2f9e,0x2f9f, + 0x2fa0,0x2fa1,0x2fa2,0x2fa3,0x2fa4,0x2fa5,0x2fa6,0x2fa7, + 0x2fa8,0x2fa9,0x2faa,0x2fab,0x2fac,0x2fad,0x2fae,0x2faf, + 0x2fb0,0x2fb1,0x2fb2,0x2fb3,0x2fb4,0x2fb5,0x2fb6,0x2fb7, + 0x2fb8,0x2fb9,0x2fba,0x2fbb,0x2fbc,0x2fbd,0x2fbe,0x2fbf, + 0x2fc0,0x2fc1,0x2fc2,0x2fc3,0x2fc4,0x2fc5,0x2fc6,0x2fc7, + 0x2fc8,0x2fc9,0x2fca,0x2fcb,0x2fcc,0x2fcd,0x2fce,0x2fcf, + 0x2fd0,0x2fd1,0x2fd2,0x2fd3,0x2fd4,0x2fd5,0x2fd6,0x2fd7, + 0x2fd8,0x2fd9,0x2fda,0x2fdb,0x2fdc,0x2fdd,0x2fde,0x2fdf, + 0x2fe0,0x2fe1,0x2fe2,0x2fe3,0x2fe4,0x2fe5,0x2fe6,0x2fe7, + 0x2fe8,0x2fe9,0x2fea,0x2feb,0x2fec,0x2fed,0x2fee,0x2fef, + 0x2ff0,0x2ff1,0x2ff2,0x2ff3,0x2ff4,0x2ff5,0x2ff6,0x2ff7, + 0x2ff8,0x2ff9,0x2ffa,0x2ffb,0x2ffc,0x2ffd,0x2ffe,0x2fff, + 0x3000,0x3001,0x3002,0x3003,0x3004,0x3005,0x3006,0x3007, + 0x3008,0x3009,0x300a,0x300b,0x300c,0x300d,0x300e,0x300f, + 0x3010,0x3011,0x3012,0x3013,0x3014,0x3015,0x3016,0x3017, + 0x3018,0x3019,0x301a,0x301b,0x301c,0x301d,0x301e,0x301f, + 0x3020,0x3021,0x3022,0x3023,0x3024,0x3025,0x3026,0x3027, + 0x3028,0x3029,0x302a,0x302b,0x302c,0x302d,0x302e,0x302f, + 0x3030,0x3031,0x3032,0x3033,0x3034,0x3035,0x3036,0x3037, + 0x3038,0x3039,0x303a,0x303b,0x303c,0x303d,0x303e,0x303f, + 0x3040,0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047, + 0x3048,0x3049,0x304a,0x304b,0x304c,0x304d,0x304e,0x304f, + 0x3050,0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057, + 0x3058,0x3059,0x305a,0x305b,0x305c,0x305d,0x305e,0x305f, + 0x3060,0x3061,0x3062,0x3063,0x3064,0x3065,0x3066,0x3067, + 0x3068,0x3069,0x306a,0x306b,0x306c,0x306d,0x306e,0x306f, + 0x3070,0x3071,0x3072,0x3073,0x3074,0x3075,0x3076,0x3077, + 0x3078,0x3079,0x307a,0x307b,0x307c,0x307d,0x307e,0x307f, + 0x3080,0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087, + 0x3088,0x3089,0x308a,0x308b,0x308c,0x308d,0x308e,0x308f, + 0x3090,0x3091,0x3092,0x3093,0x3094,0x3095,0x3096,0x3097, + 0x3098,0x3099,0x309a,0x309b,0x309c,0x309d,0x309e,0x309f, + 0x30a0,0x30a1,0x30a2,0x30a3,0x30a4,0x30a5,0x30a6,0x30a7, + 0x30a8,0x30a9,0x30aa,0x30ab,0x30ac,0x30ad,0x30ae,0x30af, + 0x30b0,0x30b1,0x30b2,0x30b3,0x30b4,0x30b5,0x30b6,0x30b7, + 0x30b8,0x30b9,0x30ba,0x30bb,0x30bc,0x30bd,0x30be,0x30bf, + 0x30c0,0x30c1,0x30c2,0x30c3,0x30c4,0x30c5,0x30c6,0x30c7, + 0x30c8,0x30c9,0x30ca,0x30cb,0x30cc,0x30cd,0x30ce,0x30cf, + 0x30d0,0x30d1,0x30d2,0x30d3,0x30d4,0x30d5,0x30d6,0x30d7, + 0x30d8,0x30d9,0x30da,0x30db,0x30dc,0x30dd,0x30de,0x30df, + 0x30e0,0x30e1,0x30e2,0x30e3,0x30e4,0x30e5,0x30e6,0x30e7, + 0x30e8,0x30e9,0x30ea,0x30eb,0x30ec,0x30ed,0x30ee,0x30ef, + 0x30f0,0x30f1,0x30f2,0x30f3,0x30f4,0x30f5,0x30f6,0x30f7, + 0x30f8,0x30f9,0x30fa,0x30fb,0x30fc,0x30fd,0x30fe,0x30ff, + 0x3100,0x3101,0x3102,0x3103,0x3104,0x3105,0x3106,0x3107, + 0x3108,0x3109,0x310a,0x310b,0x310c,0x310d,0x310e,0x310f, + 0x3110,0x3111,0x3112,0x3113,0x3114,0x3115,0x3116,0x3117, + 0x3118,0x3119,0x311a,0x311b,0x311c,0x311d,0x311e,0x311f, + 0x3120,0x3121,0x3122,0x3123,0x3124,0x3125,0x3126,0x3127, + 0x3128,0x3129,0x312a,0x312b,0x312c,0x312d,0x312e,0x312f, + 0x3130,0x3131,0x3132,0x3133,0x3134,0x3135,0x3136,0x3137, + 0x3138,0x3139,0x313a,0x313b,0x313c,0x313d,0x313e,0x313f, + 0x3140,0x3141,0x3142,0x3143,0x3144,0x3145,0x3146,0x3147, + 0x3148,0x3149,0x314a,0x314b,0x314c,0x314d,0x314e,0x314f, + 0x3150,0x3151,0x3152,0x3153,0x3154,0x3155,0x3156,0x3157, + 0x3158,0x3159,0x315a,0x315b,0x315c,0x315d,0x315e,0x315f, + 0x3160,0x3161,0x3162,0x3163,0x3164,0x3165,0x3166,0x3167, + 0x3168,0x3169,0x316a,0x316b,0x316c,0x316d,0x316e,0x316f, + 0x3170,0x3171,0x3172,0x3173,0x3174,0x3175,0x3176,0x3177, + 0x3178,0x3179,0x317a,0x317b,0x317c,0x317d,0x317e,0x317f, + 0x3180,0x3181,0x3182,0x3183,0x3184,0x3185,0x3186,0x3187, + 0x3188,0x3189,0x318a,0x318b,0x318c,0x318d,0x318e,0x318f, + 0x3190,0x3191,0x3192,0x3193,0x3194,0x3195,0x3196,0x3197, + 0x3198,0x3199,0x319a,0x319b,0x319c,0x319d,0x319e,0x319f, + 0x31a0,0x31a1,0x31a2,0x31a3,0x31a4,0x31a5,0x31a6,0x31a7, + 0x31a8,0x31a9,0x31aa,0x31ab,0x31ac,0x31ad,0x31ae,0x31af, + 0x31b0,0x31b1,0x31b2,0x31b3,0x31b4,0x31b5,0x31b6,0x31b7, + 0x31b8,0x31b9,0x31ba,0x31bb,0x31bc,0x31bd,0x31be,0x31bf, + 0x31c0,0x31c1,0x31c2,0x31c3,0x31c4,0x31c5,0x31c6,0x31c7, + 0x31c8,0x31c9,0x31ca,0x31cb,0x31cc,0x31cd,0x31ce,0x31cf, + 0x31d0,0x31d1,0x31d2,0x31d3,0x31d4,0x31d5,0x31d6,0x31d7, + 0x31d8,0x31d9,0x31da,0x31db,0x31dc,0x31dd,0x31de,0x31df, + 0x31e0,0x31e1,0x31e2,0x31e3,0x31e4,0x31e5,0x31e6,0x31e7, + 0x31e8,0x31e9,0x31ea,0x31eb,0x31ec,0x31ed,0x31ee,0x31ef, + 0x31f0,0x31f1,0x31f2,0x31f3,0x31f4,0x31f5,0x31f6,0x31f7, + 0x31f8,0x31f9,0x31fa,0x31fb,0x31fc,0x31fd,0x31fe,0x31ff, + 0x3200,0x3201,0x3202,0x3203,0x3204,0x3205,0x3206,0x3207, + 0x3208,0x3209,0x320a,0x320b,0x320c,0x320d,0x320e,0x320f, + 0x3210,0x3211,0x3212,0x3213,0x3214,0x3215,0x3216,0x3217, + 0x3218,0x3219,0x321a,0x321b,0x321c,0x321d,0x321e,0x321f, + 0x3220,0x3221,0x3222,0x3223,0x3224,0x3225,0x3226,0x3227, + 0x3228,0x3229,0x322a,0x322b,0x322c,0x322d,0x322e,0x322f, + 0x3230,0x3231,0x3232,0x3233,0x3234,0x3235,0x3236,0x3237, + 0x3238,0x3239,0x323a,0x323b,0x323c,0x323d,0x323e,0x323f, + 0x3240,0x3241,0x3242,0x3243,0x3244,0x3245,0x3246,0x3247, + 0x3248,0x3249,0x324a,0x324b,0x324c,0x324d,0x324e,0x324f, + 0x3250,0x3251,0x3252,0x3253,0x3254,0x3255,0x3256,0x3257, + 0x3258,0x3259,0x325a,0x325b,0x325c,0x325d,0x325e,0x325f, + 0x3260,0x3261,0x3262,0x3263,0x3264,0x3265,0x3266,0x3267, + 0x3268,0x3269,0x326a,0x326b,0x326c,0x326d,0x326e,0x326f, + 0x3270,0x3271,0x3272,0x3273,0x3274,0x3275,0x3276,0x3277, + 0x3278,0x3279,0x327a,0x327b,0x327c,0x327d,0x327e,0x327f, + 0x3280,0x3281,0x3282,0x3283,0x3284,0x3285,0x3286,0x3287, + 0x3288,0x3289,0x328a,0x328b,0x328c,0x328d,0x328e,0x328f, + 0x3290,0x3291,0x3292,0x3293,0x3294,0x3295,0x3296,0x3297, + 0x3298,0x3299,0x329a,0x329b,0x329c,0x329d,0x329e,0x329f, + 0x32a0,0x32a1,0x32a2,0x32a3,0x32a4,0x32a5,0x32a6,0x32a7, + 0x32a8,0x32a9,0x32aa,0x32ab,0x32ac,0x32ad,0x32ae,0x32af, + 0x32b0,0x32b1,0x32b2,0x32b3,0x32b4,0x32b5,0x32b6,0x32b7, + 0x32b8,0x32b9,0x32ba,0x32bb,0x32bc,0x32bd,0x32be,0x32bf, + 0x32c0,0x32c1,0x32c2,0x32c3,0x32c4,0x32c5,0x32c6,0x32c7, + 0x32c8,0x32c9,0x32ca,0x32cb,0x32cc,0x32cd,0x32ce,0x32cf, + 0x32d0,0x32d1,0x32d2,0x32d3,0x32d4,0x32d5,0x32d6,0x32d7, + 0x32d8,0x32d9,0x32da,0x32db,0x32dc,0x32dd,0x32de,0x32df, + 0x32e0,0x32e1,0x32e2,0x32e3,0x32e4,0x32e5,0x32e6,0x32e7, + 0x32e8,0x32e9,0x32ea,0x32eb,0x32ec,0x32ed,0x32ee,0x32ef, + 0x32f0,0x32f1,0x32f2,0x32f3,0x32f4,0x32f5,0x32f6,0x32f7, + 0x32f8,0x32f9,0x32fa,0x32fb,0x32fc,0x32fd,0x32fe,0x32ff, + 0x3300,0x3301,0x3302,0x3303,0x3304,0x3305,0x3306,0x3307, + 0x3308,0x3309,0x330a,0x330b,0x330c,0x330d,0x330e,0x330f, + 0x3310,0x3311,0x3312,0x3313,0x3314,0x3315,0x3316,0x3317, + 0x3318,0x3319,0x331a,0x331b,0x331c,0x331d,0x331e,0x331f, + 0x3320,0x3321,0x3322,0x3323,0x3324,0x3325,0x3326,0x3327, + 0x3328,0x3329,0x332a,0x332b,0x332c,0x332d,0x332e,0x332f, + 0x3330,0x3331,0x3332,0x3333,0x3334,0x3335,0x3336,0x3337, + 0x3338,0x3339,0x333a,0x333b,0x333c,0x333d,0x333e,0x333f, + 0x3340,0x3341,0x3342,0x3343,0x3344,0x3345,0x3346,0x3347, + 0x3348,0x3349,0x334a,0x334b,0x334c,0x334d,0x334e,0x334f, + 0x3350,0x3351,0x3352,0x3353,0x3354,0x3355,0x3356,0x3357, + 0x3358,0x3359,0x335a,0x335b,0x335c,0x335d,0x335e,0x335f, + 0x3360,0x3361,0x3362,0x3363,0x3364,0x3365,0x3366,0x3367, + 0x3368,0x3369,0x336a,0x336b,0x336c,0x336d,0x336e,0x336f, + 0x3370,0x3371,0x3372,0x3373,0x3374,0x3375,0x3376,0x3377, + 0x3378,0x3379,0x337a,0x337b,0x337c,0x337d,0x337e,0x337f, + 0x3380,0x3381,0x3382,0x3383,0x3384,0x3385,0x3386,0x3387, + 0x3388,0x3389,0x338a,0x338b,0x338c,0x338d,0x338e,0x338f, + 0x3390,0x3391,0x3392,0x3393,0x3394,0x3395,0x3396,0x3397, + 0x3398,0x3399,0x339a,0x339b,0x339c,0x339d,0x339e,0x339f, + 0x33a0,0x33a1,0x33a2,0x33a3,0x33a4,0x33a5,0x33a6,0x33a7, + 0x33a8,0x33a9,0x33aa,0x33ab,0x33ac,0x33ad,0x33ae,0x33af, + 0x33b0,0x33b1,0x33b2,0x33b3,0x33b4,0x33b5,0x33b6,0x33b7, + 0x33b8,0x33b9,0x33ba,0x33bb,0x33bc,0x33bd,0x33be,0x33bf, + 0x33c0,0x33c1,0x33c2,0x33c3,0x33c4,0x33c5,0x33c6,0x33c7, + 0x33c8,0x33c9,0x33ca,0x33cb,0x33cc,0x33cd,0x33ce,0x33cf, + 0x33d0,0x33d1,0x33d2,0x33d3,0x33d4,0x33d5,0x33d6,0x33d7, + 0x33d8,0x33d9,0x33da,0x33db,0x33dc,0x33dd,0x33de,0x33df, + 0x33e0,0x33e1,0x33e2,0x33e3,0x33e4,0x33e5,0x33e6,0x33e7, + 0x33e8,0x33e9,0x33ea,0x33eb,0x33ec,0x33ed,0x33ee,0x33ef, + 0x33f0,0x33f1,0x33f2,0x33f3,0x33f4,0x33f5,0x33f6,0x33f7, + 0x33f8,0x33f9,0x33fa,0x33fb,0x33fc,0x33fd,0x33fe,0x33ff, + 0x3400,0x3401,0x3402,0x3403,0x3404,0x3405,0x3406,0x3407, + 0x3408,0x3409,0x340a,0x340b,0x340c,0x340d,0x340e,0x340f, + 0x3410,0x3411,0x3412,0x3413,0x3414,0x3415,0x3416,0x3417, + 0x3418,0x3419,0x341a,0x341b,0x341c,0x341d,0x341e,0x341f, + 0x3420,0x3421,0x3422,0x3423,0x3424,0x3425,0x3426,0x3427, + 0x3428,0x3429,0x342a,0x342b,0x342c,0x342d,0x342e,0x342f, + 0x3430,0x3431,0x3432,0x3433,0x3434,0x3435,0x3436,0x3437, + 0x3438,0x3439,0x343a,0x343b,0x343c,0x343d,0x343e,0x343f, + 0x3440,0x3441,0x3442,0x3443,0x3444,0x3445,0x3446,0x3447, + 0x3448,0x3449,0x344a,0x344b,0x344c,0x344d,0x344e,0x344f, + 0x3450,0x3451,0x3452,0x3453,0x3454,0x3455,0x3456,0x3457, + 0x3458,0x3459,0x345a,0x345b,0x345c,0x345d,0x345e,0x345f, + 0x3460,0x3461,0x3462,0x3463,0x3464,0x3465,0x3466,0x3467, + 0x3468,0x3469,0x346a,0x346b,0x346c,0x346d,0x346e,0x346f, + 0x3470,0x3471,0x3472,0x3473,0x3474,0x3475,0x3476,0x3477, + 0x3478,0x3479,0x347a,0x347b,0x347c,0x347d,0x347e,0x347f, + 0x3480,0x3481,0x3482,0x3483,0x3484,0x3485,0x3486,0x3487, + 0x3488,0x3489,0x348a,0x348b,0x348c,0x348d,0x348e,0x348f, + 0x3490,0x3491,0x3492,0x3493,0x3494,0x3495,0x3496,0x3497, + 0x3498,0x3499,0x349a,0x349b,0x349c,0x349d,0x349e,0x349f, + 0x34a0,0x34a1,0x34a2,0x34a3,0x34a4,0x34a5,0x34a6,0x34a7, + 0x34a8,0x34a9,0x34aa,0x34ab,0x34ac,0x34ad,0x34ae,0x34af, + 0x34b0,0x34b1,0x34b2,0x34b3,0x34b4,0x34b5,0x34b6,0x34b7, + 0x34b8,0x34b9,0x34ba,0x34bb,0x34bc,0x34bd,0x34be,0x34bf, + 0x34c0,0x34c1,0x34c2,0x34c3,0x34c4,0x34c5,0x34c6,0x34c7, + 0x34c8,0x34c9,0x34ca,0x34cb,0x34cc,0x34cd,0x34ce,0x34cf, + 0x34d0,0x34d1,0x34d2,0x34d3,0x34d4,0x34d5,0x34d6,0x34d7, + 0x34d8,0x34d9,0x34da,0x34db,0x34dc,0x34dd,0x34de,0x34df, + 0x34e0,0x34e1,0x34e2,0x34e3,0x34e4,0x34e5,0x34e6,0x34e7, + 0x34e8,0x34e9,0x34ea,0x34eb,0x34ec,0x34ed,0x34ee,0x34ef, + 0x34f0,0x34f1,0x34f2,0x34f3,0x34f4,0x34f5,0x34f6,0x34f7, + 0x34f8,0x34f9,0x34fa,0x34fb,0x34fc,0x34fd,0x34fe,0x34ff, + 0x3500,0x3501,0x3502,0x3503,0x3504,0x3505,0x3506,0x3507, + 0x3508,0x3509,0x350a,0x350b,0x350c,0x350d,0x350e,0x350f, + 0x3510,0x3511,0x3512,0x3513,0x3514,0x3515,0x3516,0x3517, + 0x3518,0x3519,0x351a,0x351b,0x351c,0x351d,0x351e,0x351f, + 0x3520,0x3521,0x3522,0x3523,0x3524,0x3525,0x3526,0x3527, + 0x3528,0x3529,0x352a,0x352b,0x352c,0x352d,0x352e,0x352f, + 0x3530,0x3531,0x3532,0x3533,0x3534,0x3535,0x3536,0x3537, + 0x3538,0x3539,0x353a,0x353b,0x353c,0x353d,0x353e,0x353f, + 0x3540,0x3541,0x3542,0x3543,0x3544,0x3545,0x3546,0x3547, + 0x3548,0x3549,0x354a,0x354b,0x354c,0x354d,0x354e,0x354f, + 0x3550,0x3551,0x3552,0x3553,0x3554,0x3555,0x3556,0x3557, + 0x3558,0x3559,0x355a,0x355b,0x355c,0x355d,0x355e,0x355f, + 0x3560,0x3561,0x3562,0x3563,0x3564,0x3565,0x3566,0x3567, + 0x3568,0x3569,0x356a,0x356b,0x356c,0x356d,0x356e,0x356f, + 0x3570,0x3571,0x3572,0x3573,0x3574,0x3575,0x3576,0x3577, + 0x3578,0x3579,0x357a,0x357b,0x357c,0x357d,0x357e,0x357f, + 0x3580,0x3581,0x3582,0x3583,0x3584,0x3585,0x3586,0x3587, + 0x3588,0x3589,0x358a,0x358b,0x358c,0x358d,0x358e,0x358f, + 0x3590,0x3591,0x3592,0x3593,0x3594,0x3595,0x3596,0x3597, + 0x3598,0x3599,0x359a,0x359b,0x359c,0x359d,0x359e,0x359f, + 0x35a0,0x35a1,0x35a2,0x35a3,0x35a4,0x35a5,0x35a6,0x35a7, + 0x35a8,0x35a9,0x35aa,0x35ab,0x35ac,0x35ad,0x35ae,0x35af, + 0x35b0,0x35b1,0x35b2,0x35b3,0x35b4,0x35b5,0x35b6,0x35b7, + 0x35b8,0x35b9,0x35ba,0x35bb,0x35bc,0x35bd,0x35be,0x35bf, + 0x35c0,0x35c1,0x35c2,0x35c3,0x35c4,0x35c5,0x35c6,0x35c7, + 0x35c8,0x35c9,0x35ca,0x35cb,0x35cc,0x35cd,0x35ce,0x35cf, + 0x35d0,0x35d1,0x35d2,0x35d3,0x35d4,0x35d5,0x35d6,0x35d7, + 0x35d8,0x35d9,0x35da,0x35db,0x35dc,0x35dd,0x35de,0x35df, + 0x35e0,0x35e1,0x35e2,0x35e3,0x35e4,0x35e5,0x35e6,0x35e7, + 0x35e8,0x35e9,0x35ea,0x35eb,0x35ec,0x35ed,0x35ee,0x35ef, + 0x35f0,0x35f1,0x35f2,0x35f3,0x35f4,0x35f5,0x35f6,0x35f7, + 0x35f8,0x35f9,0x35fa,0x35fb,0x35fc,0x35fd,0x35fe,0x35ff, + 0x3600,0x3601,0x3602,0x3603,0x3604,0x3605,0x3606,0x3607, + 0x3608,0x3609,0x360a,0x360b,0x360c,0x360d,0x360e,0x360f, + 0x3610,0x3611,0x3612,0x3613,0x3614,0x3615,0x3616,0x3617, + 0x3618,0x3619,0x361a,0x361b,0x361c,0x361d,0x361e,0x361f, + 0x3620,0x3621,0x3622,0x3623,0x3624,0x3625,0x3626,0x3627, + 0x3628,0x3629,0x362a,0x362b,0x362c,0x362d,0x362e,0x362f, + 0x3630,0x3631,0x3632,0x3633,0x3634,0x3635,0x3636,0x3637, + 0x3638,0x3639,0x363a,0x363b,0x363c,0x363d,0x363e,0x363f, + 0x3640,0x3641,0x3642,0x3643,0x3644,0x3645,0x3646,0x3647, + 0x3648,0x3649,0x364a,0x364b,0x364c,0x364d,0x364e,0x364f, + 0x3650,0x3651,0x3652,0x3653,0x3654,0x3655,0x3656,0x3657, + 0x3658,0x3659,0x365a,0x365b,0x365c,0x365d,0x365e,0x365f, + 0x3660,0x3661,0x3662,0x3663,0x3664,0x3665,0x3666,0x3667, + 0x3668,0x3669,0x366a,0x366b,0x366c,0x366d,0x366e,0x366f, + 0x3670,0x3671,0x3672,0x3673,0x3674,0x3675,0x3676,0x3677, + 0x3678,0x3679,0x367a,0x367b,0x367c,0x367d,0x367e,0x367f, + 0x3680,0x3681,0x3682,0x3683,0x3684,0x3685,0x3686,0x3687, + 0x3688,0x3689,0x368a,0x368b,0x368c,0x368d,0x368e,0x368f, + 0x3690,0x3691,0x3692,0x3693,0x3694,0x3695,0x3696,0x3697, + 0x3698,0x3699,0x369a,0x369b,0x369c,0x369d,0x369e,0x369f, + 0x36a0,0x36a1,0x36a2,0x36a3,0x36a4,0x36a5,0x36a6,0x36a7, + 0x36a8,0x36a9,0x36aa,0x36ab,0x36ac,0x36ad,0x36ae,0x36af, + 0x36b0,0x36b1,0x36b2,0x36b3,0x36b4,0x36b5,0x36b6,0x36b7, + 0x36b8,0x36b9,0x36ba,0x36bb,0x36bc,0x36bd,0x36be,0x36bf, + 0x36c0,0x36c1,0x36c2,0x36c3,0x36c4,0x36c5,0x36c6,0x36c7, + 0x36c8,0x36c9,0x36ca,0x36cb,0x36cc,0x36cd,0x36ce,0x36cf, + 0x36d0,0x36d1,0x36d2,0x36d3,0x36d4,0x36d5,0x36d6,0x36d7, + 0x36d8,0x36d9,0x36da,0x36db,0x36dc,0x36dd,0x36de,0x36df, + 0x36e0,0x36e1,0x36e2,0x36e3,0x36e4,0x36e5,0x36e6,0x36e7, + 0x36e8,0x36e9,0x36ea,0x36eb,0x36ec,0x36ed,0x36ee,0x36ef, + 0x36f0,0x36f1,0x36f2,0x36f3,0x36f4,0x36f5,0x36f6,0x36f7, + 0x36f8,0x36f9,0x36fa,0x36fb,0x36fc,0x36fd,0x36fe,0x36ff, + 0x3700,0x3701,0x3702,0x3703,0x3704,0x3705,0x3706,0x3707, + 0x3708,0x3709,0x370a,0x370b,0x370c,0x370d,0x370e,0x370f, + 0x3710,0x3711,0x3712,0x3713,0x3714,0x3715,0x3716,0x3717, + 0x3718,0x3719,0x371a,0x371b,0x371c,0x371d,0x371e,0x371f, + 0x3720,0x3721,0x3722,0x3723,0x3724,0x3725,0x3726,0x3727, + 0x3728,0x3729,0x372a,0x372b,0x372c,0x372d,0x372e,0x372f, + 0x3730,0x3731,0x3732,0x3733,0x3734,0x3735,0x3736,0x3737, + 0x3738,0x3739,0x373a,0x373b,0x373c,0x373d,0x373e,0x373f, + 0x3740,0x3741,0x3742,0x3743,0x3744,0x3745,0x3746,0x3747, + 0x3748,0x3749,0x374a,0x374b,0x374c,0x374d,0x374e,0x374f, + 0x3750,0x3751,0x3752,0x3753,0x3754,0x3755,0x3756,0x3757, + 0x3758,0x3759,0x375a,0x375b,0x375c,0x375d,0x375e,0x375f, + 0x3760,0x3761,0x3762,0x3763,0x3764,0x3765,0x3766,0x3767, + 0x3768,0x3769,0x376a,0x376b,0x376c,0x376d,0x376e,0x376f, + 0x3770,0x3771,0x3772,0x3773,0x3774,0x3775,0x3776,0x3777, + 0x3778,0x3779,0x377a,0x377b,0x377c,0x377d,0x377e,0x377f, + 0x3780,0x3781,0x3782,0x3783,0x3784,0x3785,0x3786,0x3787, + 0x3788,0x3789,0x378a,0x378b,0x378c,0x378d,0x378e,0x378f, + 0x3790,0x3791,0x3792,0x3793,0x3794,0x3795,0x3796,0x3797, + 0x3798,0x3799,0x379a,0x379b,0x379c,0x379d,0x379e,0x379f, + 0x37a0,0x37a1,0x37a2,0x37a3,0x37a4,0x37a5,0x37a6,0x37a7, + 0x37a8,0x37a9,0x37aa,0x37ab,0x37ac,0x37ad,0x37ae,0x37af, + 0x37b0,0x37b1,0x37b2,0x37b3,0x37b4,0x37b5,0x37b6,0x37b7, + 0x37b8,0x37b9,0x37ba,0x37bb,0x37bc,0x37bd,0x37be,0x37bf, + 0x37c0,0x37c1,0x37c2,0x37c3,0x37c4,0x37c5,0x37c6,0x37c7, + 0x37c8,0x37c9,0x37ca,0x37cb,0x37cc,0x37cd,0x37ce,0x37cf, + 0x37d0,0x37d1,0x37d2,0x37d3,0x37d4,0x37d5,0x37d6,0x37d7, + 0x37d8,0x37d9,0x37da,0x37db,0x37dc,0x37dd,0x37de,0x37df, + 0x37e0,0x37e1,0x37e2,0x37e3,0x37e4,0x37e5,0x37e6,0x37e7, + 0x37e8,0x37e9,0x37ea,0x37eb,0x37ec,0x37ed,0x37ee,0x37ef, + 0x37f0,0x37f1,0x37f2,0x37f3,0x37f4,0x37f5,0x37f6,0x37f7, + 0x37f8,0x37f9,0x37fa,0x37fb,0x37fc,0x37fd,0x37fe,0x37ff, + 0x3800,0x3801,0x3802,0x3803,0x3804,0x3805,0x3806,0x3807, + 0x3808,0x3809,0x380a,0x380b,0x380c,0x380d,0x380e,0x380f, + 0x3810,0x3811,0x3812,0x3813,0x3814,0x3815,0x3816,0x3817, + 0x3818,0x3819,0x381a,0x381b,0x381c,0x381d,0x381e,0x381f, + 0x3820,0x3821,0x3822,0x3823,0x3824,0x3825,0x3826,0x3827, + 0x3828,0x3829,0x382a,0x382b,0x382c,0x382d,0x382e,0x382f, + 0x3830,0x3831,0x3832,0x3833,0x3834,0x3835,0x3836,0x3837, + 0x3838,0x3839,0x383a,0x383b,0x383c,0x383d,0x383e,0x383f, + 0x3840,0x3841,0x3842,0x3843,0x3844,0x3845,0x3846,0x3847, + 0x3848,0x3849,0x384a,0x384b,0x384c,0x384d,0x384e,0x384f, + 0x3850,0x3851,0x3852,0x3853,0x3854,0x3855,0x3856,0x3857, + 0x3858,0x3859,0x385a,0x385b,0x385c,0x385d,0x385e,0x385f, + 0x3860,0x3861,0x3862,0x3863,0x3864,0x3865,0x3866,0x3867, + 0x3868,0x3869,0x386a,0x386b,0x386c,0x386d,0x386e,0x386f, + 0x3870,0x3871,0x3872,0x3873,0x3874,0x3875,0x3876,0x3877, + 0x3878,0x3879,0x387a,0x387b,0x387c,0x387d,0x387e,0x387f, + 0x3880,0x3881,0x3882,0x3883,0x3884,0x3885,0x3886,0x3887, + 0x3888,0x3889,0x388a,0x388b,0x388c,0x388d,0x388e,0x388f, + 0x3890,0x3891,0x3892,0x3893,0x3894,0x3895,0x3896,0x3897, + 0x3898,0x3899,0x389a,0x389b,0x389c,0x389d,0x389e,0x389f, + 0x38a0,0x38a1,0x38a2,0x38a3,0x38a4,0x38a5,0x38a6,0x38a7, + 0x38a8,0x38a9,0x38aa,0x38ab,0x38ac,0x38ad,0x38ae,0x38af, + 0x38b0,0x38b1,0x38b2,0x38b3,0x38b4,0x38b5,0x38b6,0x38b7, + 0x38b8,0x38b9,0x38ba,0x38bb,0x38bc,0x38bd,0x38be,0x38bf, + 0x38c0,0x38c1,0x38c2,0x38c3,0x38c4,0x38c5,0x38c6,0x38c7, + 0x38c8,0x38c9,0x38ca,0x38cb,0x38cc,0x38cd,0x38ce,0x38cf, + 0x38d0,0x38d1,0x38d2,0x38d3,0x38d4,0x38d5,0x38d6,0x38d7, + 0x38d8,0x38d9,0x38da,0x38db,0x38dc,0x38dd,0x38de,0x38df, + 0x38e0,0x38e1,0x38e2,0x38e3,0x38e4,0x38e5,0x38e6,0x38e7, + 0x38e8,0x38e9,0x38ea,0x38eb,0x38ec,0x38ed,0x38ee,0x38ef, + 0x38f0,0x38f1,0x38f2,0x38f3,0x38f4,0x38f5,0x38f6,0x38f7, + 0x38f8,0x38f9,0x38fa,0x38fb,0x38fc,0x38fd,0x38fe,0x38ff, + 0x3900,0x3901,0x3902,0x3903,0x3904,0x3905,0x3906,0x3907, + 0x3908,0x3909,0x390a,0x390b,0x390c,0x390d,0x390e,0x390f, + 0x3910,0x3911,0x3912,0x3913,0x3914,0x3915,0x3916,0x3917, + 0x3918,0x3919,0x391a,0x391b,0x391c,0x391d,0x391e,0x391f, + 0x3920,0x3921,0x3922,0x3923,0x3924,0x3925,0x3926,0x3927, + 0x3928,0x3929,0x392a,0x392b,0x392c,0x392d,0x392e,0x392f, + 0x3930,0x3931,0x3932,0x3933,0x3934,0x3935,0x3936,0x3937, + 0x3938,0x3939,0x393a,0x393b,0x393c,0x393d,0x393e,0x393f, + 0x3940,0x3941,0x3942,0x3943,0x3944,0x3945,0x3946,0x3947, + 0x3948,0x3949,0x394a,0x394b,0x394c,0x394d,0x394e,0x394f, + 0x3950,0x3951,0x3952,0x3953,0x3954,0x3955,0x3956,0x3957, + 0x3958,0x3959,0x395a,0x395b,0x395c,0x395d,0x395e,0x395f, + 0x3960,0x3961,0x3962,0x3963,0x3964,0x3965,0x3966,0x3967, + 0x3968,0x3969,0x396a,0x396b,0x396c,0x396d,0x396e,0x396f, + 0x3970,0x3971,0x3972,0x3973,0x3974,0x3975,0x3976,0x3977, + 0x3978,0x3979,0x397a,0x397b,0x397c,0x397d,0x397e,0x397f, + 0x3980,0x3981,0x3982,0x3983,0x3984,0x3985,0x3986,0x3987, + 0x3988,0x3989,0x398a,0x398b,0x398c,0x398d,0x398e,0x398f, + 0x3990,0x3991,0x3992,0x3993,0x3994,0x3995,0x3996,0x3997, + 0x3998,0x3999,0x399a,0x399b,0x399c,0x399d,0x399e,0x399f, + 0x39a0,0x39a1,0x39a2,0x39a3,0x39a4,0x39a5,0x39a6,0x39a7, + 0x39a8,0x39a9,0x39aa,0x39ab,0x39ac,0x39ad,0x39ae,0x39af, + 0x39b0,0x39b1,0x39b2,0x39b3,0x39b4,0x39b5,0x39b6,0x39b7, + 0x39b8,0x39b9,0x39ba,0x39bb,0x39bc,0x39bd,0x39be,0x39bf, + 0x39c0,0x39c1,0x39c2,0x39c3,0x39c4,0x39c5,0x39c6,0x39c7, + 0x39c8,0x39c9,0x39ca,0x39cb,0x39cc,0x39cd,0x39ce,0x39cf, + 0x39d0,0x39d1,0x39d2,0x39d3,0x39d4,0x39d5,0x39d6,0x39d7, + 0x39d8,0x39d9,0x39da,0x39db,0x39dc,0x39dd,0x39de,0x39df, + 0x39e0,0x39e1,0x39e2,0x39e3,0x39e4,0x39e5,0x39e6,0x39e7, + 0x39e8,0x39e9,0x39ea,0x39eb,0x39ec,0x39ed,0x39ee,0x39ef, + 0x39f0,0x39f1,0x39f2,0x39f3,0x39f4,0x39f5,0x39f6,0x39f7, + 0x39f8,0x39f9,0x39fa,0x39fb,0x39fc,0x39fd,0x39fe,0x39ff, + 0x3a00,0x3a01,0x3a02,0x3a03,0x3a04,0x3a05,0x3a06,0x3a07, + 0x3a08,0x3a09,0x3a0a,0x3a0b,0x3a0c,0x3a0d,0x3a0e,0x3a0f, + 0x3a10,0x3a11,0x3a12,0x3a13,0x3a14,0x3a15,0x3a16,0x3a17, + 0x3a18,0x3a19,0x3a1a,0x3a1b,0x3a1c,0x3a1d,0x3a1e,0x3a1f, + 0x3a20,0x3a21,0x3a22,0x3a23,0x3a24,0x3a25,0x3a26,0x3a27, + 0x3a28,0x3a29,0x3a2a,0x3a2b,0x3a2c,0x3a2d,0x3a2e,0x3a2f, + 0x3a30,0x3a31,0x3a32,0x3a33,0x3a34,0x3a35,0x3a36,0x3a37, + 0x3a38,0x3a39,0x3a3a,0x3a3b,0x3a3c,0x3a3d,0x3a3e,0x3a3f, + 0x3a40,0x3a41,0x3a42,0x3a43,0x3a44,0x3a45,0x3a46,0x3a47, + 0x3a48,0x3a49,0x3a4a,0x3a4b,0x3a4c,0x3a4d,0x3a4e,0x3a4f, + 0x3a50,0x3a51,0x3a52,0x3a53,0x3a54,0x3a55,0x3a56,0x3a57, + 0x3a58,0x3a59,0x3a5a,0x3a5b,0x3a5c,0x3a5d,0x3a5e,0x3a5f, + 0x3a60,0x3a61,0x3a62,0x3a63,0x3a64,0x3a65,0x3a66,0x3a67, + 0x3a68,0x3a69,0x3a6a,0x3a6b,0x3a6c,0x3a6d,0x3a6e,0x3a6f, + 0x3a70,0x3a71,0x3a72,0x3a73,0x3a74,0x3a75,0x3a76,0x3a77, + 0x3a78,0x3a79,0x3a7a,0x3a7b,0x3a7c,0x3a7d,0x3a7e,0x3a7f, + 0x3a80,0x3a81,0x3a82,0x3a83,0x3a84,0x3a85,0x3a86,0x3a87, + 0x3a88,0x3a89,0x3a8a,0x3a8b,0x3a8c,0x3a8d,0x3a8e,0x3a8f, + 0x3a90,0x3a91,0x3a92,0x3a93,0x3a94,0x3a95,0x3a96,0x3a97, + 0x3a98,0x3a99,0x3a9a,0x3a9b,0x3a9c,0x3a9d,0x3a9e,0x3a9f, + 0x3aa0,0x3aa1,0x3aa2,0x3aa3,0x3aa4,0x3aa5,0x3aa6,0x3aa7, + 0x3aa8,0x3aa9,0x3aaa,0x3aab,0x3aac,0x3aad,0x3aae,0x3aaf, + 0x3ab0,0x3ab1,0x3ab2,0x3ab3,0x3ab4,0x3ab5,0x3ab6,0x3ab7, + 0x3ab8,0x3ab9,0x3aba,0x3abb,0x3abc,0x3abd,0x3abe,0x3abf, + 0x3ac0,0x3ac1,0x3ac2,0x3ac3,0x3ac4,0x3ac5,0x3ac6,0x3ac7, + 0x3ac8,0x3ac9,0x3aca,0x3acb,0x3acc,0x3acd,0x3ace,0x3acf, + 0x3ad0,0x3ad1,0x3ad2,0x3ad3,0x3ad4,0x3ad5,0x3ad6,0x3ad7, + 0x3ad8,0x3ad9,0x3ada,0x3adb,0x3adc,0x3add,0x3ade,0x3adf, + 0x3ae0,0x3ae1,0x3ae2,0x3ae3,0x3ae4,0x3ae5,0x3ae6,0x3ae7, + 0x3ae8,0x3ae9,0x3aea,0x3aeb,0x3aec,0x3aed,0x3aee,0x3aef, + 0x3af0,0x3af1,0x3af2,0x3af3,0x3af4,0x3af5,0x3af6,0x3af7, + 0x3af8,0x3af9,0x3afa,0x3afb,0x3afc,0x3afd,0x3afe,0x3aff, + 0x3b00,0x3b01,0x3b02,0x3b03,0x3b04,0x3b05,0x3b06,0x3b07, + 0x3b08,0x3b09,0x3b0a,0x3b0b,0x3b0c,0x3b0d,0x3b0e,0x3b0f, + 0x3b10,0x3b11,0x3b12,0x3b13,0x3b14,0x3b15,0x3b16,0x3b17, + 0x3b18,0x3b19,0x3b1a,0x3b1b,0x3b1c,0x3b1d,0x3b1e,0x3b1f, + 0x3b20,0x3b21,0x3b22,0x3b23,0x3b24,0x3b25,0x3b26,0x3b27, + 0x3b28,0x3b29,0x3b2a,0x3b2b,0x3b2c,0x3b2d,0x3b2e,0x3b2f, + 0x3b30,0x3b31,0x3b32,0x3b33,0x3b34,0x3b35,0x3b36,0x3b37, + 0x3b38,0x3b39,0x3b3a,0x3b3b,0x3b3c,0x3b3d,0x3b3e,0x3b3f, + 0x3b40,0x3b41,0x3b42,0x3b43,0x3b44,0x3b45,0x3b46,0x3b47, + 0x3b48,0x3b49,0x3b4a,0x3b4b,0x3b4c,0x3b4d,0x3b4e,0x3b4f, + 0x3b50,0x3b51,0x3b52,0x3b53,0x3b54,0x3b55,0x3b56,0x3b57, + 0x3b58,0x3b59,0x3b5a,0x3b5b,0x3b5c,0x3b5d,0x3b5e,0x3b5f, + 0x3b60,0x3b61,0x3b62,0x3b63,0x3b64,0x3b65,0x3b66,0x3b67, + 0x3b68,0x3b69,0x3b6a,0x3b6b,0x3b6c,0x3b6d,0x3b6e,0x3b6f, + 0x3b70,0x3b71,0x3b72,0x3b73,0x3b74,0x3b75,0x3b76,0x3b77, + 0x3b78,0x3b79,0x3b7a,0x3b7b,0x3b7c,0x3b7d,0x3b7e,0x3b7f, + 0x3b80,0x3b81,0x3b82,0x3b83,0x3b84,0x3b85,0x3b86,0x3b87, + 0x3b88,0x3b89,0x3b8a,0x3b8b,0x3b8c,0x3b8d,0x3b8e,0x3b8f, + 0x3b90,0x3b91,0x3b92,0x3b93,0x3b94,0x3b95,0x3b96,0x3b97, + 0x3b98,0x3b99,0x3b9a,0x3b9b,0x3b9c,0x3b9d,0x3b9e,0x3b9f, + 0x3ba0,0x3ba1,0x3ba2,0x3ba3,0x3ba4,0x3ba5,0x3ba6,0x3ba7, + 0x3ba8,0x3ba9,0x3baa,0x3bab,0x3bac,0x3bad,0x3bae,0x3baf, + 0x3bb0,0x3bb1,0x3bb2,0x3bb3,0x3bb4,0x3bb5,0x3bb6,0x3bb7, + 0x3bb8,0x3bb9,0x3bba,0x3bbb,0x3bbc,0x3bbd,0x3bbe,0x3bbf, + 0x3bc0,0x3bc1,0x3bc2,0x3bc3,0x3bc4,0x3bc5,0x3bc6,0x3bc7, + 0x3bc8,0x3bc9,0x3bca,0x3bcb,0x3bcc,0x3bcd,0x3bce,0x3bcf, + 0x3bd0,0x3bd1,0x3bd2,0x3bd3,0x3bd4,0x3bd5,0x3bd6,0x3bd7, + 0x3bd8,0x3bd9,0x3bda,0x3bdb,0x3bdc,0x3bdd,0x3bde,0x3bdf, + 0x3be0,0x3be1,0x3be2,0x3be3,0x3be4,0x3be5,0x3be6,0x3be7, + 0x3be8,0x3be9,0x3bea,0x3beb,0x3bec,0x3bed,0x3bee,0x3bef, + 0x3bf0,0x3bf1,0x3bf2,0x3bf3,0x3bf4,0x3bf5,0x3bf6,0x3bf7, + 0x3bf8,0x3bf9,0x3bfa,0x3bfb,0x3bfc,0x3bfd,0x3bfe,0x3bff, + 0x3c00,0x3c01,0x3c02,0x3c03,0x3c04,0x3c05,0x3c06,0x3c07, + 0x3c08,0x3c09,0x3c0a,0x3c0b,0x3c0c,0x3c0d,0x3c0e,0x3c0f, + 0x3c10,0x3c11,0x3c12,0x3c13,0x3c14,0x3c15,0x3c16,0x3c17, + 0x3c18,0x3c19,0x3c1a,0x3c1b,0x3c1c,0x3c1d,0x3c1e,0x3c1f, + 0x3c20,0x3c21,0x3c22,0x3c23,0x3c24,0x3c25,0x3c26,0x3c27, + 0x3c28,0x3c29,0x3c2a,0x3c2b,0x3c2c,0x3c2d,0x3c2e,0x3c2f, + 0x3c30,0x3c31,0x3c32,0x3c33,0x3c34,0x3c35,0x3c36,0x3c37, + 0x3c38,0x3c39,0x3c3a,0x3c3b,0x3c3c,0x3c3d,0x3c3e,0x3c3f, + 0x3c40,0x3c41,0x3c42,0x3c43,0x3c44,0x3c45,0x3c46,0x3c47, + 0x3c48,0x3c49,0x3c4a,0x3c4b,0x3c4c,0x3c4d,0x3c4e,0x3c4f, + 0x3c50,0x3c51,0x3c52,0x3c53,0x3c54,0x3c55,0x3c56,0x3c57, + 0x3c58,0x3c59,0x3c5a,0x3c5b,0x3c5c,0x3c5d,0x3c5e,0x3c5f, + 0x3c60,0x3c61,0x3c62,0x3c63,0x3c64,0x3c65,0x3c66,0x3c67, + 0x3c68,0x3c69,0x3c6a,0x3c6b,0x3c6c,0x3c6d,0x3c6e,0x3c6f, + 0x3c70,0x3c71,0x3c72,0x3c73,0x3c74,0x3c75,0x3c76,0x3c77, + 0x3c78,0x3c79,0x3c7a,0x3c7b,0x3c7c,0x3c7d,0x3c7e,0x3c7f, + 0x3c80,0x3c81,0x3c82,0x3c83,0x3c84,0x3c85,0x3c86,0x3c87, + 0x3c88,0x3c89,0x3c8a,0x3c8b,0x3c8c,0x3c8d,0x3c8e,0x3c8f, + 0x3c90,0x3c91,0x3c92,0x3c93,0x3c94,0x3c95,0x3c96,0x3c97, + 0x3c98,0x3c99,0x3c9a,0x3c9b,0x3c9c,0x3c9d,0x3c9e,0x3c9f, + 0x3ca0,0x3ca1,0x3ca2,0x3ca3,0x3ca4,0x3ca5,0x3ca6,0x3ca7, + 0x3ca8,0x3ca9,0x3caa,0x3cab,0x3cac,0x3cad,0x3cae,0x3caf, + 0x3cb0,0x3cb1,0x3cb2,0x3cb3,0x3cb4,0x3cb5,0x3cb6,0x3cb7, + 0x3cb8,0x3cb9,0x3cba,0x3cbb,0x3cbc,0x3cbd,0x3cbe,0x3cbf, + 0x3cc0,0x3cc1,0x3cc2,0x3cc3,0x3cc4,0x3cc5,0x3cc6,0x3cc7, + 0x3cc8,0x3cc9,0x3cca,0x3ccb,0x3ccc,0x3ccd,0x3cce,0x3ccf, + 0x3cd0,0x3cd1,0x3cd2,0x3cd3,0x3cd4,0x3cd5,0x3cd6,0x3cd7, + 0x3cd8,0x3cd9,0x3cda,0x3cdb,0x3cdc,0x3cdd,0x3cde,0x3cdf, + 0x3ce0,0x3ce1,0x3ce2,0x3ce3,0x3ce4,0x3ce5,0x3ce6,0x3ce7, + 0x3ce8,0x3ce9,0x3cea,0x3ceb,0x3cec,0x3ced,0x3cee,0x3cef, + 0x3cf0,0x3cf1,0x3cf2,0x3cf3,0x3cf4,0x3cf5,0x3cf6,0x3cf7, + 0x3cf8,0x3cf9,0x3cfa,0x3cfb,0x3cfc,0x3cfd,0x3cfe,0x3cff, + 0x3d00,0x3d01,0x3d02,0x3d03,0x3d04,0x3d05,0x3d06,0x3d07, + 0x3d08,0x3d09,0x3d0a,0x3d0b,0x3d0c,0x3d0d,0x3d0e,0x3d0f, + 0x3d10,0x3d11,0x3d12,0x3d13,0x3d14,0x3d15,0x3d16,0x3d17, + 0x3d18,0x3d19,0x3d1a,0x3d1b,0x3d1c,0x3d1d,0x3d1e,0x3d1f, + 0x3d20,0x3d21,0x3d22,0x3d23,0x3d24,0x3d25,0x3d26,0x3d27, + 0x3d28,0x3d29,0x3d2a,0x3d2b,0x3d2c,0x3d2d,0x3d2e,0x3d2f, + 0x3d30,0x3d31,0x3d32,0x3d33,0x3d34,0x3d35,0x3d36,0x3d37, + 0x3d38,0x3d39,0x3d3a,0x3d3b,0x3d3c,0x3d3d,0x3d3e,0x3d3f, + 0x3d40,0x3d41,0x3d42,0x3d43,0x3d44,0x3d45,0x3d46,0x3d47, + 0x3d48,0x3d49,0x3d4a,0x3d4b,0x3d4c,0x3d4d,0x3d4e,0x3d4f, + 0x3d50,0x3d51,0x3d52,0x3d53,0x3d54,0x3d55,0x3d56,0x3d57, + 0x3d58,0x3d59,0x3d5a,0x3d5b,0x3d5c,0x3d5d,0x3d5e,0x3d5f, + 0x3d60,0x3d61,0x3d62,0x3d63,0x3d64,0x3d65,0x3d66,0x3d67, + 0x3d68,0x3d69,0x3d6a,0x3d6b,0x3d6c,0x3d6d,0x3d6e,0x3d6f, + 0x3d70,0x3d71,0x3d72,0x3d73,0x3d74,0x3d75,0x3d76,0x3d77, + 0x3d78,0x3d79,0x3d7a,0x3d7b,0x3d7c,0x3d7d,0x3d7e,0x3d7f, + 0x3d80,0x3d81,0x3d82,0x3d83,0x3d84,0x3d85,0x3d86,0x3d87, + 0x3d88,0x3d89,0x3d8a,0x3d8b,0x3d8c,0x3d8d,0x3d8e,0x3d8f, + 0x3d90,0x3d91,0x3d92,0x3d93,0x3d94,0x3d95,0x3d96,0x3d97, + 0x3d98,0x3d99,0x3d9a,0x3d9b,0x3d9c,0x3d9d,0x3d9e,0x3d9f, + 0x3da0,0x3da1,0x3da2,0x3da3,0x3da4,0x3da5,0x3da6,0x3da7, + 0x3da8,0x3da9,0x3daa,0x3dab,0x3dac,0x3dad,0x3dae,0x3daf, + 0x3db0,0x3db1,0x3db2,0x3db3,0x3db4,0x3db5,0x3db6,0x3db7, + 0x3db8,0x3db9,0x3dba,0x3dbb,0x3dbc,0x3dbd,0x3dbe,0x3dbf, + 0x3dc0,0x3dc1,0x3dc2,0x3dc3,0x3dc4,0x3dc5,0x3dc6,0x3dc7, + 0x3dc8,0x3dc9,0x3dca,0x3dcb,0x3dcc,0x3dcd,0x3dce,0x3dcf, + 0x3dd0,0x3dd1,0x3dd2,0x3dd3,0x3dd4,0x3dd5,0x3dd6,0x3dd7, + 0x3dd8,0x3dd9,0x3dda,0x3ddb,0x3ddc,0x3ddd,0x3dde,0x3ddf, + 0x3de0,0x3de1,0x3de2,0x3de3,0x3de4,0x3de5,0x3de6,0x3de7, + 0x3de8,0x3de9,0x3dea,0x3deb,0x3dec,0x3ded,0x3dee,0x3def, + 0x3df0,0x3df1,0x3df2,0x3df3,0x3df4,0x3df5,0x3df6,0x3df7, + 0x3df8,0x3df9,0x3dfa,0x3dfb,0x3dfc,0x3dfd,0x3dfe,0x3dff, + 0x3e00,0x3e01,0x3e02,0x3e03,0x3e04,0x3e05,0x3e06,0x3e07, + 0x3e08,0x3e09,0x3e0a,0x3e0b,0x3e0c,0x3e0d,0x3e0e,0x3e0f, + 0x3e10,0x3e11,0x3e12,0x3e13,0x3e14,0x3e15,0x3e16,0x3e17, + 0x3e18,0x3e19,0x3e1a,0x3e1b,0x3e1c,0x3e1d,0x3e1e,0x3e1f, + 0x3e20,0x3e21,0x3e22,0x3e23,0x3e24,0x3e25,0x3e26,0x3e27, + 0x3e28,0x3e29,0x3e2a,0x3e2b,0x3e2c,0x3e2d,0x3e2e,0x3e2f, + 0x3e30,0x3e31,0x3e32,0x3e33,0x3e34,0x3e35,0x3e36,0x3e37, + 0x3e38,0x3e39,0x3e3a,0x3e3b,0x3e3c,0x3e3d,0x3e3e,0x3e3f, + 0x3e40,0x3e41,0x3e42,0x3e43,0x3e44,0x3e45,0x3e46,0x3e47, + 0x3e48,0x3e49,0x3e4a,0x3e4b,0x3e4c,0x3e4d,0x3e4e,0x3e4f, + 0x3e50,0x3e51,0x3e52,0x3e53,0x3e54,0x3e55,0x3e56,0x3e57, + 0x3e58,0x3e59,0x3e5a,0x3e5b,0x3e5c,0x3e5d,0x3e5e,0x3e5f, + 0x3e60,0x3e61,0x3e62,0x3e63,0x3e64,0x3e65,0x3e66,0x3e67, + 0x3e68,0x3e69,0x3e6a,0x3e6b,0x3e6c,0x3e6d,0x3e6e,0x3e6f, + 0x3e70,0x3e71,0x3e72,0x3e73,0x3e74,0x3e75,0x3e76,0x3e77, + 0x3e78,0x3e79,0x3e7a,0x3e7b,0x3e7c,0x3e7d,0x3e7e,0x3e7f, + 0x3e80,0x3e81,0x3e82,0x3e83,0x3e84,0x3e85,0x3e86,0x3e87, + 0x3e88,0x3e89,0x3e8a,0x3e8b,0x3e8c,0x3e8d,0x3e8e,0x3e8f, + 0x3e90,0x3e91,0x3e92,0x3e93,0x3e94,0x3e95,0x3e96,0x3e97, + 0x3e98,0x3e99,0x3e9a,0x3e9b,0x3e9c,0x3e9d,0x3e9e,0x3e9f, + 0x3ea0,0x3ea1,0x3ea2,0x3ea3,0x3ea4,0x3ea5,0x3ea6,0x3ea7, + 0x3ea8,0x3ea9,0x3eaa,0x3eab,0x3eac,0x3ead,0x3eae,0x3eaf, + 0x3eb0,0x3eb1,0x3eb2,0x3eb3,0x3eb4,0x3eb5,0x3eb6,0x3eb7, + 0x3eb8,0x3eb9,0x3eba,0x3ebb,0x3ebc,0x3ebd,0x3ebe,0x3ebf, + 0x3ec0,0x3ec1,0x3ec2,0x3ec3,0x3ec4,0x3ec5,0x3ec6,0x3ec7, + 0x3ec8,0x3ec9,0x3eca,0x3ecb,0x3ecc,0x3ecd,0x3ece,0x3ecf, + 0x3ed0,0x3ed1,0x3ed2,0x3ed3,0x3ed4,0x3ed5,0x3ed6,0x3ed7, + 0x3ed8,0x3ed9,0x3eda,0x3edb,0x3edc,0x3edd,0x3ede,0x3edf, + 0x3ee0,0x3ee1,0x3ee2,0x3ee3,0x3ee4,0x3ee5,0x3ee6,0x3ee7, + 0x3ee8,0x3ee9,0x3eea,0x3eeb,0x3eec,0x3eed,0x3eee,0x3eef, + 0x3ef0,0x3ef1,0x3ef2,0x3ef3,0x3ef4,0x3ef5,0x3ef6,0x3ef7, + 0x3ef8,0x3ef9,0x3efa,0x3efb,0x3efc,0x3efd,0x3efe,0x3eff, + 0x3f00,0x3f01,0x3f02,0x3f03,0x3f04,0x3f05,0x3f06,0x3f07, + 0x3f08,0x3f09,0x3f0a,0x3f0b,0x3f0c,0x3f0d,0x3f0e,0x3f0f, + 0x3f10,0x3f11,0x3f12,0x3f13,0x3f14,0x3f15,0x3f16,0x3f17, + 0x3f18,0x3f19,0x3f1a,0x3f1b,0x3f1c,0x3f1d,0x3f1e,0x3f1f, + 0x3f20,0x3f21,0x3f22,0x3f23,0x3f24,0x3f25,0x3f26,0x3f27, + 0x3f28,0x3f29,0x3f2a,0x3f2b,0x3f2c,0x3f2d,0x3f2e,0x3f2f, + 0x3f30,0x3f31,0x3f32,0x3f33,0x3f34,0x3f35,0x3f36,0x3f37, + 0x3f38,0x3f39,0x3f3a,0x3f3b,0x3f3c,0x3f3d,0x3f3e,0x3f3f, + 0x3f40,0x3f41,0x3f42,0x3f43,0x3f44,0x3f45,0x3f46,0x3f47, + 0x3f48,0x3f49,0x3f4a,0x3f4b,0x3f4c,0x3f4d,0x3f4e,0x3f4f, + 0x3f50,0x3f51,0x3f52,0x3f53,0x3f54,0x3f55,0x3f56,0x3f57, + 0x3f58,0x3f59,0x3f5a,0x3f5b,0x3f5c,0x3f5d,0x3f5e,0x3f5f, + 0x3f60,0x3f61,0x3f62,0x3f63,0x3f64,0x3f65,0x3f66,0x3f67, + 0x3f68,0x3f69,0x3f6a,0x3f6b,0x3f6c,0x3f6d,0x3f6e,0x3f6f, + 0x3f70,0x3f71,0x3f72,0x3f73,0x3f74,0x3f75,0x3f76,0x3f77, + 0x3f78,0x3f79,0x3f7a,0x3f7b,0x3f7c,0x3f7d,0x3f7e,0x3f7f, + 0x3f80,0x3f81,0x3f82,0x3f83,0x3f84,0x3f85,0x3f86,0x3f87, + 0x3f88,0x3f89,0x3f8a,0x3f8b,0x3f8c,0x3f8d,0x3f8e,0x3f8f, + 0x3f90,0x3f91,0x3f92,0x3f93,0x3f94,0x3f95,0x3f96,0x3f97, + 0x3f98,0x3f99,0x3f9a,0x3f9b,0x3f9c,0x3f9d,0x3f9e,0x3f9f, + 0x3fa0,0x3fa1,0x3fa2,0x3fa3,0x3fa4,0x3fa5,0x3fa6,0x3fa7, + 0x3fa8,0x3fa9,0x3faa,0x3fab,0x3fac,0x3fad,0x3fae,0x3faf, + 0x3fb0,0x3fb1,0x3fb2,0x3fb3,0x3fb4,0x3fb5,0x3fb6,0x3fb7, + 0x3fb8,0x3fb9,0x3fba,0x3fbb,0x3fbc,0x3fbd,0x3fbe,0x3fbf, + 0x3fc0,0x3fc1,0x3fc2,0x3fc3,0x3fc4,0x3fc5,0x3fc6,0x3fc7, + 0x3fc8,0x3fc9,0x3fca,0x3fcb,0x3fcc,0x3fcd,0x3fce,0x3fcf, + 0x3fd0,0x3fd1,0x3fd2,0x3fd3,0x3fd4,0x3fd5,0x3fd6,0x3fd7, + 0x3fd8,0x3fd9,0x3fda,0x3fdb,0x3fdc,0x3fdd,0x3fde,0x3fdf, + 0x3fe0,0x3fe1,0x3fe2,0x3fe3,0x3fe4,0x3fe5,0x3fe6,0x3fe7, + 0x3fe8,0x3fe9,0x3fea,0x3feb,0x3fec,0x3fed,0x3fee,0x3fef, + 0x3ff0,0x3ff1,0x3ff2,0x3ff3,0x3ff4,0x3ff5,0x3ff6,0x3ff7, + 0x3ff8,0x3ff9,0x3ffa,0x3ffb,0x3ffc,0x3ffd,0x3ffe,0x3fff, + 0x4000,0x4001,0x4002,0x4003,0x4004,0x4005,0x4006,0x4007, + 0x4008,0x4009,0x400a,0x400b,0x400c,0x400d,0x400e,0x400f, + 0x4010,0x4011,0x4012,0x4013,0x4014,0x4015,0x4016,0x4017, + 0x4018,0x4019,0x401a,0x401b,0x401c,0x401d,0x401e,0x401f, + 0x4020,0x4021,0x4022,0x4023,0x4024,0x4025,0x4026,0x4027, + 0x4028,0x4029,0x402a,0x402b,0x402c,0x402d,0x402e,0x402f, + 0x4030,0x4031,0x4032,0x4033,0x4034,0x4035,0x4036,0x4037, + 0x4038,0x4039,0x403a,0x403b,0x403c,0x403d,0x403e,0x403f, + 0x4040,0x4041,0x4042,0x4043,0x4044,0x4045,0x4046,0x4047, + 0x4048,0x4049,0x404a,0x404b,0x404c,0x404d,0x404e,0x404f, + 0x4050,0x4051,0x4052,0x4053,0x4054,0x4055,0x4056,0x4057, + 0x4058,0x4059,0x405a,0x405b,0x405c,0x405d,0x405e,0x405f, + 0x4060,0x4061,0x4062,0x4063,0x4064,0x4065,0x4066,0x4067, + 0x4068,0x4069,0x406a,0x406b,0x406c,0x406d,0x406e,0x406f, + 0x4070,0x4071,0x4072,0x4073,0x4074,0x4075,0x4076,0x4077, + 0x4078,0x4079,0x407a,0x407b,0x407c,0x407d,0x407e,0x407f, + 0x4080,0x4081,0x4082,0x4083,0x4084,0x4085,0x4086,0x4087, + 0x4088,0x4089,0x408a,0x408b,0x408c,0x408d,0x408e,0x408f, + 0x4090,0x4091,0x4092,0x4093,0x4094,0x4095,0x4096,0x4097, + 0x4098,0x4099,0x409a,0x409b,0x409c,0x409d,0x409e,0x409f, + 0x40a0,0x40a1,0x40a2,0x40a3,0x40a4,0x40a5,0x40a6,0x40a7, + 0x40a8,0x40a9,0x40aa,0x40ab,0x40ac,0x40ad,0x40ae,0x40af, + 0x40b0,0x40b1,0x40b2,0x40b3,0x40b4,0x40b5,0x40b6,0x40b7, + 0x40b8,0x40b9,0x40ba,0x40bb,0x40bc,0x40bd,0x40be,0x40bf, + 0x40c0,0x40c1,0x40c2,0x40c3,0x40c4,0x40c5,0x40c6,0x40c7, + 0x40c8,0x40c9,0x40ca,0x40cb,0x40cc,0x40cd,0x40ce,0x40cf, + 0x40d0,0x40d1,0x40d2,0x40d3,0x40d4,0x40d5,0x40d6,0x40d7, + 0x40d8,0x40d9,0x40da,0x40db,0x40dc,0x40dd,0x40de,0x40df, + 0x40e0,0x40e1,0x40e2,0x40e3,0x40e4,0x40e5,0x40e6,0x40e7, + 0x40e8,0x40e9,0x40ea,0x40eb,0x40ec,0x40ed,0x40ee,0x40ef, + 0x40f0,0x40f1,0x40f2,0x40f3,0x40f4,0x40f5,0x40f6,0x40f7, + 0x40f8,0x40f9,0x40fa,0x40fb,0x40fc,0x40fd,0x40fe,0x40ff, + 0x4100,0x4101,0x4102,0x4103,0x4104,0x4105,0x4106,0x4107, + 0x4108,0x4109,0x410a,0x410b,0x410c,0x410d,0x410e,0x410f, + 0x4110,0x4111,0x4112,0x4113,0x4114,0x4115,0x4116,0x4117, + 0x4118,0x4119,0x411a,0x411b,0x411c,0x411d,0x411e,0x411f, + 0x4120,0x4121,0x4122,0x4123,0x4124,0x4125,0x4126,0x4127, + 0x4128,0x4129,0x412a,0x412b,0x412c,0x412d,0x412e,0x412f, + 0x4130,0x4131,0x4132,0x4133,0x4134,0x4135,0x4136,0x4137, + 0x4138,0x4139,0x413a,0x413b,0x413c,0x413d,0x413e,0x413f, + 0x4140,0x4141,0x4142,0x4143,0x4144,0x4145,0x4146,0x4147, + 0x4148,0x4149,0x414a,0x414b,0x414c,0x414d,0x414e,0x414f, + 0x4150,0x4151,0x4152,0x4153,0x4154,0x4155,0x4156,0x4157, + 0x4158,0x4159,0x415a,0x415b,0x415c,0x415d,0x415e,0x415f, + 0x4160,0x4161,0x4162,0x4163,0x4164,0x4165,0x4166,0x4167, + 0x4168,0x4169,0x416a,0x416b,0x416c,0x416d,0x416e,0x416f, + 0x4170,0x4171,0x4172,0x4173,0x4174,0x4175,0x4176,0x4177, + 0x4178,0x4179,0x417a,0x417b,0x417c,0x417d,0x417e,0x417f, + 0x4180,0x4181,0x4182,0x4183,0x4184,0x4185,0x4186,0x4187, + 0x4188,0x4189,0x418a,0x418b,0x418c,0x418d,0x418e,0x418f, + 0x4190,0x4191,0x4192,0x4193,0x4194,0x4195,0x4196,0x4197, + 0x4198,0x4199,0x419a,0x419b,0x419c,0x419d,0x419e,0x419f, + 0x41a0,0x41a1,0x41a2,0x41a3,0x41a4,0x41a5,0x41a6,0x41a7, + 0x41a8,0x41a9,0x41aa,0x41ab,0x41ac,0x41ad,0x41ae,0x41af, + 0x41b0,0x41b1,0x41b2,0x41b3,0x41b4,0x41b5,0x41b6,0x41b7, + 0x41b8,0x41b9,0x41ba,0x41bb,0x41bc,0x41bd,0x41be,0x41bf, + 0x41c0,0x41c1,0x41c2,0x41c3,0x41c4,0x41c5,0x41c6,0x41c7, + 0x41c8,0x41c9,0x41ca,0x41cb,0x41cc,0x41cd,0x41ce,0x41cf, + 0x41d0,0x41d1,0x41d2,0x41d3,0x41d4,0x41d5,0x41d6,0x41d7, + 0x41d8,0x41d9,0x41da,0x41db,0x41dc,0x41dd,0x41de,0x41df, + 0x41e0,0x41e1,0x41e2,0x41e3,0x41e4,0x41e5,0x41e6,0x41e7, + 0x41e8,0x41e9,0x41ea,0x41eb,0x41ec,0x41ed,0x41ee,0x41ef, + 0x41f0,0x41f1,0x41f2,0x41f3,0x41f4,0x41f5,0x41f6,0x41f7, + 0x41f8,0x41f9,0x41fa,0x41fb,0x41fc,0x41fd,0x41fe,0x41ff, + 0x4200,0x4201,0x4202,0x4203,0x4204,0x4205,0x4206,0x4207, + 0x4208,0x4209,0x420a,0x420b,0x420c,0x420d,0x420e,0x420f, + 0x4210,0x4211,0x4212,0x4213,0x4214,0x4215,0x4216,0x4217, + 0x4218,0x4219,0x421a,0x421b,0x421c,0x421d,0x421e,0x421f, + 0x4220,0x4221,0x4222,0x4223,0x4224,0x4225,0x4226,0x4227, + 0x4228,0x4229,0x422a,0x422b,0x422c,0x422d,0x422e,0x422f, + 0x4230,0x4231,0x4232,0x4233,0x4234,0x4235,0x4236,0x4237, + 0x4238,0x4239,0x423a,0x423b,0x423c,0x423d,0x423e,0x423f, + 0x4240,0x4241,0x4242,0x4243,0x4244,0x4245,0x4246,0x4247, + 0x4248,0x4249,0x424a,0x424b,0x424c,0x424d,0x424e,0x424f, + 0x4250,0x4251,0x4252,0x4253,0x4254,0x4255,0x4256,0x4257, + 0x4258,0x4259,0x425a,0x425b,0x425c,0x425d,0x425e,0x425f, + 0x4260,0x4261,0x4262,0x4263,0x4264,0x4265,0x4266,0x4267, + 0x4268,0x4269,0x426a,0x426b,0x426c,0x426d,0x426e,0x426f, + 0x4270,0x4271,0x4272,0x4273,0x4274,0x4275,0x4276,0x4277, + 0x4278,0x4279,0x427a,0x427b,0x427c,0x427d,0x427e,0x427f, + 0x4280,0x4281,0x4282,0x4283,0x4284,0x4285,0x4286,0x4287, + 0x4288,0x4289,0x428a,0x428b,0x428c,0x428d,0x428e,0x428f, + 0x4290,0x4291,0x4292,0x4293,0x4294,0x4295,0x4296,0x4297, + 0x4298,0x4299,0x429a,0x429b,0x429c,0x429d,0x429e,0x429f, + 0x42a0,0x42a1,0x42a2,0x42a3,0x42a4,0x42a5,0x42a6,0x42a7, + 0x42a8,0x42a9,0x42aa,0x42ab,0x42ac,0x42ad,0x42ae,0x42af, + 0x42b0,0x42b1,0x42b2,0x42b3,0x42b4,0x42b5,0x42b6,0x42b7, + 0x42b8,0x42b9,0x42ba,0x42bb,0x42bc,0x42bd,0x42be,0x42bf, + 0x42c0,0x42c1,0x42c2,0x42c3,0x42c4,0x42c5,0x42c6,0x42c7, + 0x42c8,0x42c9,0x42ca,0x42cb,0x42cc,0x42cd,0x42ce,0x42cf, + 0x42d0,0x42d1,0x42d2,0x42d3,0x42d4,0x42d5,0x42d6,0x42d7, + 0x42d8,0x42d9,0x42da,0x42db,0x42dc,0x42dd,0x42de,0x42df, + 0x42e0,0x42e1,0x42e2,0x42e3,0x42e4,0x42e5,0x42e6,0x42e7, + 0x42e8,0x42e9,0x42ea,0x42eb,0x42ec,0x42ed,0x42ee,0x42ef, + 0x42f0,0x42f1,0x42f2,0x42f3,0x42f4,0x42f5,0x42f6,0x42f7, + 0x42f8,0x42f9,0x42fa,0x42fb,0x42fc,0x42fd,0x42fe,0x42ff, + 0x4300,0x4301,0x4302,0x4303,0x4304,0x4305,0x4306,0x4307, + 0x4308,0x4309,0x430a,0x430b,0x430c,0x430d,0x430e,0x430f, + 0x4310,0x4311,0x4312,0x4313,0x4314,0x4315,0x4316,0x4317, + 0x4318,0x4319,0x431a,0x431b,0x431c,0x431d,0x431e,0x431f, + 0x4320,0x4321,0x4322,0x4323,0x4324,0x4325,0x4326,0x4327, + 0x4328,0x4329,0x432a,0x432b,0x432c,0x432d,0x432e,0x432f, + 0x4330,0x4331,0x4332,0x4333,0x4334,0x4335,0x4336,0x4337, + 0x4338,0x4339,0x433a,0x433b,0x433c,0x433d,0x433e,0x433f, + 0x4340,0x4341,0x4342,0x4343,0x4344,0x4345,0x4346,0x4347, + 0x4348,0x4349,0x434a,0x434b,0x434c,0x434d,0x434e,0x434f, + 0x4350,0x4351,0x4352,0x4353,0x4354,0x4355,0x4356,0x4357, + 0x4358,0x4359,0x435a,0x435b,0x435c,0x435d,0x435e,0x435f, + 0x4360,0x4361,0x4362,0x4363,0x4364,0x4365,0x4366,0x4367, + 0x4368,0x4369,0x436a,0x436b,0x436c,0x436d,0x436e,0x436f, + 0x4370,0x4371,0x4372,0x4373,0x4374,0x4375,0x4376,0x4377, + 0x4378,0x4379,0x437a,0x437b,0x437c,0x437d,0x437e,0x437f, + 0x4380,0x4381,0x4382,0x4383,0x4384,0x4385,0x4386,0x4387, + 0x4388,0x4389,0x438a,0x438b,0x438c,0x438d,0x438e,0x438f, + 0x4390,0x4391,0x4392,0x4393,0x4394,0x4395,0x4396,0x4397, + 0x4398,0x4399,0x439a,0x439b,0x439c,0x439d,0x439e,0x439f, + 0x43a0,0x43a1,0x43a2,0x43a3,0x43a4,0x43a5,0x43a6,0x43a7, + 0x43a8,0x43a9,0x43aa,0x43ab,0x43ac,0x43ad,0x43ae,0x43af, + 0x43b0,0x43b1,0x43b2,0x43b3,0x43b4,0x43b5,0x43b6,0x43b7, + 0x43b8,0x43b9,0x43ba,0x43bb,0x43bc,0x43bd,0x43be,0x43bf, + 0x43c0,0x43c1,0x43c2,0x43c3,0x43c4,0x43c5,0x43c6,0x43c7, + 0x43c8,0x43c9,0x43ca,0x43cb,0x43cc,0x43cd,0x43ce,0x43cf, + 0x43d0,0x43d1,0x43d2,0x43d3,0x43d4,0x43d5,0x43d6,0x43d7, + 0x43d8,0x43d9,0x43da,0x43db,0x43dc,0x43dd,0x43de,0x43df, + 0x43e0,0x43e1,0x43e2,0x43e3,0x43e4,0x43e5,0x43e6,0x43e7, + 0x43e8,0x43e9,0x43ea,0x43eb,0x43ec,0x43ed,0x43ee,0x43ef, + 0x43f0,0x43f1,0x43f2,0x43f3,0x43f4,0x43f5,0x43f6,0x43f7, + 0x43f8,0x43f9,0x43fa,0x43fb,0x43fc,0x43fd,0x43fe,0x43ff, + 0x4400,0x4401,0x4402,0x4403,0x4404,0x4405,0x4406,0x4407, + 0x4408,0x4409,0x440a,0x440b,0x440c,0x440d,0x440e,0x440f, + 0x4410,0x4411,0x4412,0x4413,0x4414,0x4415,0x4416,0x4417, + 0x4418,0x4419,0x441a,0x441b,0x441c,0x441d,0x441e,0x441f, + 0x4420,0x4421,0x4422,0x4423,0x4424,0x4425,0x4426,0x4427, + 0x4428,0x4429,0x442a,0x442b,0x442c,0x442d,0x442e,0x442f, + 0x4430,0x4431,0x4432,0x4433,0x4434,0x4435,0x4436,0x4437, + 0x4438,0x4439,0x443a,0x443b,0x443c,0x443d,0x443e,0x443f, + 0x4440,0x4441,0x4442,0x4443,0x4444,0x4445,0x4446,0x4447, + 0x4448,0x4449,0x444a,0x444b,0x444c,0x444d,0x444e,0x444f, + 0x4450,0x4451,0x4452,0x4453,0x4454,0x4455,0x4456,0x4457, + 0x4458,0x4459,0x445a,0x445b,0x445c,0x445d,0x445e,0x445f, + 0x4460,0x4461,0x4462,0x4463,0x4464,0x4465,0x4466,0x4467, + 0x4468,0x4469,0x446a,0x446b,0x446c,0x446d,0x446e,0x446f, + 0x4470,0x4471,0x4472,0x4473,0x4474,0x4475,0x4476,0x4477, + 0x4478,0x4479,0x447a,0x447b,0x447c,0x447d,0x447e,0x447f, + 0x4480,0x4481,0x4482,0x4483,0x4484,0x4485,0x4486,0x4487, + 0x4488,0x4489,0x448a,0x448b,0x448c,0x448d,0x448e,0x448f, + 0x4490,0x4491,0x4492,0x4493,0x4494,0x4495,0x4496,0x4497, + 0x4498,0x4499,0x449a,0x449b,0x449c,0x449d,0x449e,0x449f, + 0x44a0,0x44a1,0x44a2,0x44a3,0x44a4,0x44a5,0x44a6,0x44a7, + 0x44a8,0x44a9,0x44aa,0x44ab,0x44ac,0x44ad,0x44ae,0x44af, + 0x44b0,0x44b1,0x44b2,0x44b3,0x44b4,0x44b5,0x44b6,0x44b7, + 0x44b8,0x44b9,0x44ba,0x44bb,0x44bc,0x44bd,0x44be,0x44bf, + 0x44c0,0x44c1,0x44c2,0x44c3,0x44c4,0x44c5,0x44c6,0x44c7, + 0x44c8,0x44c9,0x44ca,0x44cb,0x44cc,0x44cd,0x44ce,0x44cf, + 0x44d0,0x44d1,0x44d2,0x44d3,0x44d4,0x44d5,0x44d6,0x44d7, + 0x44d8,0x44d9,0x44da,0x44db,0x44dc,0x44dd,0x44de,0x44df, + 0x44e0,0x44e1,0x44e2,0x44e3,0x44e4,0x44e5,0x44e6,0x44e7, + 0x44e8,0x44e9,0x44ea,0x44eb,0x44ec,0x44ed,0x44ee,0x44ef, + 0x44f0,0x44f1,0x44f2,0x44f3,0x44f4,0x44f5,0x44f6,0x44f7, + 0x44f8,0x44f9,0x44fa,0x44fb,0x44fc,0x44fd,0x44fe,0x44ff, + 0x4500,0x4501,0x4502,0x4503,0x4504,0x4505,0x4506,0x4507, + 0x4508,0x4509,0x450a,0x450b,0x450c,0x450d,0x450e,0x450f, + 0x4510,0x4511,0x4512,0x4513,0x4514,0x4515,0x4516,0x4517, + 0x4518,0x4519,0x451a,0x451b,0x451c,0x451d,0x451e,0x451f, + 0x4520,0x4521,0x4522,0x4523,0x4524,0x4525,0x4526,0x4527, + 0x4528,0x4529,0x452a,0x452b,0x452c,0x452d,0x452e,0x452f, + 0x4530,0x4531,0x4532,0x4533,0x4534,0x4535,0x4536,0x4537, + 0x4538,0x4539,0x453a,0x453b,0x453c,0x453d,0x453e,0x453f, + 0x4540,0x4541,0x4542,0x4543,0x4544,0x4545,0x4546,0x4547, + 0x4548,0x4549,0x454a,0x454b,0x454c,0x454d,0x454e,0x454f, + 0x4550,0x4551,0x4552,0x4553,0x4554,0x4555,0x4556,0x4557, + 0x4558,0x4559,0x455a,0x455b,0x455c,0x455d,0x455e,0x455f, + 0x4560,0x4561,0x4562,0x4563,0x4564,0x4565,0x4566,0x4567, + 0x4568,0x4569,0x456a,0x456b,0x456c,0x456d,0x456e,0x456f, + 0x4570,0x4571,0x4572,0x4573,0x4574,0x4575,0x4576,0x4577, + 0x4578,0x4579,0x457a,0x457b,0x457c,0x457d,0x457e,0x457f, + 0x4580,0x4581,0x4582,0x4583,0x4584,0x4585,0x4586,0x4587, + 0x4588,0x4589,0x458a,0x458b,0x458c,0x458d,0x458e,0x458f, + 0x4590,0x4591,0x4592,0x4593,0x4594,0x4595,0x4596,0x4597, + 0x4598,0x4599,0x459a,0x459b,0x459c,0x459d,0x459e,0x459f, + 0x45a0,0x45a1,0x45a2,0x45a3,0x45a4,0x45a5,0x45a6,0x45a7, + 0x45a8,0x45a9,0x45aa,0x45ab,0x45ac,0x45ad,0x45ae,0x45af, + 0x45b0,0x45b1,0x45b2,0x45b3,0x45b4,0x45b5,0x45b6,0x45b7, + 0x45b8,0x45b9,0x45ba,0x45bb,0x45bc,0x45bd,0x45be,0x45bf, + 0x45c0,0x45c1,0x45c2,0x45c3,0x45c4,0x45c5,0x45c6,0x45c7, + 0x45c8,0x45c9,0x45ca,0x45cb,0x45cc,0x45cd,0x45ce,0x45cf, + 0x45d0,0x45d1,0x45d2,0x45d3,0x45d4,0x45d5,0x45d6,0x45d7, + 0x45d8,0x45d9,0x45da,0x45db,0x45dc,0x45dd,0x45de,0x45df, + 0x45e0,0x45e1,0x45e2,0x45e3,0x45e4,0x45e5,0x45e6,0x45e7, + 0x45e8,0x45e9,0x45ea,0x45eb,0x45ec,0x45ed,0x45ee,0x45ef, + 0x45f0,0x45f1,0x45f2,0x45f3,0x45f4,0x45f5,0x45f6,0x45f7, + 0x45f8,0x45f9,0x45fa,0x45fb,0x45fc,0x45fd,0x45fe,0x45ff, + 0x4600,0x4601,0x4602,0x4603,0x4604,0x4605,0x4606,0x4607, + 0x4608,0x4609,0x460a,0x460b,0x460c,0x460d,0x460e,0x460f, + 0x4610,0x4611,0x4612,0x4613,0x4614,0x4615,0x4616,0x4617, + 0x4618,0x4619,0x461a,0x461b,0x461c,0x461d,0x461e,0x461f, + 0x4620,0x4621,0x4622,0x4623,0x4624,0x4625,0x4626,0x4627, + 0x4628,0x4629,0x462a,0x462b,0x462c,0x462d,0x462e,0x462f, + 0x4630,0x4631,0x4632,0x4633,0x4634,0x4635,0x4636,0x4637, + 0x4638,0x4639,0x463a,0x463b,0x463c,0x463d,0x463e,0x463f, + 0x4640,0x4641,0x4642,0x4643,0x4644,0x4645,0x4646,0x4647, + 0x4648,0x4649,0x464a,0x464b,0x464c,0x464d,0x464e,0x464f, + 0x4650,0x4651,0x4652,0x4653,0x4654,0x4655,0x4656,0x4657, + 0x4658,0x4659,0x465a,0x465b,0x465c,0x465d,0x465e,0x465f, + 0x4660,0x4661,0x4662,0x4663,0x4664,0x4665,0x4666,0x4667, + 0x4668,0x4669,0x466a,0x466b,0x466c,0x466d,0x466e,0x466f, + 0x4670,0x4671,0x4672,0x4673,0x4674,0x4675,0x4676,0x4677, + 0x4678,0x4679,0x467a,0x467b,0x467c,0x467d,0x467e,0x467f, + 0x4680,0x4681,0x4682,0x4683,0x4684,0x4685,0x4686,0x4687, + 0x4688,0x4689,0x468a,0x468b,0x468c,0x468d,0x468e,0x468f, + 0x4690,0x4691,0x4692,0x4693,0x4694,0x4695,0x4696,0x4697, + 0x4698,0x4699,0x469a,0x469b,0x469c,0x469d,0x469e,0x469f, + 0x46a0,0x46a1,0x46a2,0x46a3,0x46a4,0x46a5,0x46a6,0x46a7, + 0x46a8,0x46a9,0x46aa,0x46ab,0x46ac,0x46ad,0x46ae,0x46af, + 0x46b0,0x46b1,0x46b2,0x46b3,0x46b4,0x46b5,0x46b6,0x46b7, + 0x46b8,0x46b9,0x46ba,0x46bb,0x46bc,0x46bd,0x46be,0x46bf, + 0x46c0,0x46c1,0x46c2,0x46c3,0x46c4,0x46c5,0x46c6,0x46c7, + 0x46c8,0x46c9,0x46ca,0x46cb,0x46cc,0x46cd,0x46ce,0x46cf, + 0x46d0,0x46d1,0x46d2,0x46d3,0x46d4,0x46d5,0x46d6,0x46d7, + 0x46d8,0x46d9,0x46da,0x46db,0x46dc,0x46dd,0x46de,0x46df, + 0x46e0,0x46e1,0x46e2,0x46e3,0x46e4,0x46e5,0x46e6,0x46e7, + 0x46e8,0x46e9,0x46ea,0x46eb,0x46ec,0x46ed,0x46ee,0x46ef, + 0x46f0,0x46f1,0x46f2,0x46f3,0x46f4,0x46f5,0x46f6,0x46f7, + 0x46f8,0x46f9,0x46fa,0x46fb,0x46fc,0x46fd,0x46fe,0x46ff, + 0x4700,0x4701,0x4702,0x4703,0x4704,0x4705,0x4706,0x4707, + 0x4708,0x4709,0x470a,0x470b,0x470c,0x470d,0x470e,0x470f, + 0x4710,0x4711,0x4712,0x4713,0x4714,0x4715,0x4716,0x4717, + 0x4718,0x4719,0x471a,0x471b,0x471c,0x471d,0x471e,0x471f, + 0x4720,0x4721,0x4722,0x4723,0x4724,0x4725,0x4726,0x4727, + 0x4728,0x4729,0x472a,0x472b,0x472c,0x472d,0x472e,0x472f, + 0x4730,0x4731,0x4732,0x4733,0x4734,0x4735,0x4736,0x4737, + 0x4738,0x4739,0x473a,0x473b,0x473c,0x473d,0x473e,0x473f, + 0x4740,0x4741,0x4742,0x4743,0x4744,0x4745,0x4746,0x4747, + 0x4748,0x4749,0x474a,0x474b,0x474c,0x474d,0x474e,0x474f, + 0x4750,0x4751,0x4752,0x4753,0x4754,0x4755,0x4756,0x4757, + 0x4758,0x4759,0x475a,0x475b,0x475c,0x475d,0x475e,0x475f, + 0x4760,0x4761,0x4762,0x4763,0x4764,0x4765,0x4766,0x4767, + 0x4768,0x4769,0x476a,0x476b,0x476c,0x476d,0x476e,0x476f, + 0x4770,0x4771,0x4772,0x4773,0x4774,0x4775,0x4776,0x4777, + 0x4778,0x4779,0x477a,0x477b,0x477c,0x477d,0x477e,0x477f, + 0x4780,0x4781,0x4782,0x4783,0x4784,0x4785,0x4786,0x4787, + 0x4788,0x4789,0x478a,0x478b,0x478c,0x478d,0x478e,0x478f, + 0x4790,0x4791,0x4792,0x4793,0x4794,0x4795,0x4796,0x4797, + 0x4798,0x4799,0x479a,0x479b,0x479c,0x479d,0x479e,0x479f, + 0x47a0,0x47a1,0x47a2,0x47a3,0x47a4,0x47a5,0x47a6,0x47a7, + 0x47a8,0x47a9,0x47aa,0x47ab,0x47ac,0x47ad,0x47ae,0x47af, + 0x47b0,0x47b1,0x47b2,0x47b3,0x47b4,0x47b5,0x47b6,0x47b7, + 0x47b8,0x47b9,0x47ba,0x47bb,0x47bc,0x47bd,0x47be,0x47bf, + 0x47c0,0x47c1,0x47c2,0x47c3,0x47c4,0x47c5,0x47c6,0x47c7, + 0x47c8,0x47c9,0x47ca,0x47cb,0x47cc,0x47cd,0x47ce,0x47cf, + 0x47d0,0x47d1,0x47d2,0x47d3,0x47d4,0x47d5,0x47d6,0x47d7, + 0x47d8,0x47d9,0x47da,0x47db,0x47dc,0x47dd,0x47de,0x47df, + 0x47e0,0x47e1,0x47e2,0x47e3,0x47e4,0x47e5,0x47e6,0x47e7, + 0x47e8,0x47e9,0x47ea,0x47eb,0x47ec,0x47ed,0x47ee,0x47ef, + 0x47f0,0x47f1,0x47f2,0x47f3,0x47f4,0x47f5,0x47f6,0x47f7, + 0x47f8,0x47f9,0x47fa,0x47fb,0x47fc,0x47fd,0x47fe,0x47ff, + 0x4800,0x4801,0x4802,0x4803,0x4804,0x4805,0x4806,0x4807, + 0x4808,0x4809,0x480a,0x480b,0x480c,0x480d,0x480e,0x480f, + 0x4810,0x4811,0x4812,0x4813,0x4814,0x4815,0x4816,0x4817, + 0x4818,0x4819,0x481a,0x481b,0x481c,0x481d,0x481e,0x481f, + 0x4820,0x4821,0x4822,0x4823,0x4824,0x4825,0x4826,0x4827, + 0x4828,0x4829,0x482a,0x482b,0x482c,0x482d,0x482e,0x482f, + 0x4830,0x4831,0x4832,0x4833,0x4834,0x4835,0x4836,0x4837, + 0x4838,0x4839,0x483a,0x483b,0x483c,0x483d,0x483e,0x483f, + 0x4840,0x4841,0x4842,0x4843,0x4844,0x4845,0x4846,0x4847, + 0x4848,0x4849,0x484a,0x484b,0x484c,0x484d,0x484e,0x484f, + 0x4850,0x4851,0x4852,0x4853,0x4854,0x4855,0x4856,0x4857, + 0x4858,0x4859,0x485a,0x485b,0x485c,0x485d,0x485e,0x485f, + 0x4860,0x4861,0x4862,0x4863,0x4864,0x4865,0x4866,0x4867, + 0x4868,0x4869,0x486a,0x486b,0x486c,0x486d,0x486e,0x486f, + 0x4870,0x4871,0x4872,0x4873,0x4874,0x4875,0x4876,0x4877, + 0x4878,0x4879,0x487a,0x487b,0x487c,0x487d,0x487e,0x487f, + 0x4880,0x4881,0x4882,0x4883,0x4884,0x4885,0x4886,0x4887, + 0x4888,0x4889,0x488a,0x488b,0x488c,0x488d,0x488e,0x488f, + 0x4890,0x4891,0x4892,0x4893,0x4894,0x4895,0x4896,0x4897, + 0x4898,0x4899,0x489a,0x489b,0x489c,0x489d,0x489e,0x489f, + 0x48a0,0x48a1,0x48a2,0x48a3,0x48a4,0x48a5,0x48a6,0x48a7, + 0x48a8,0x48a9,0x48aa,0x48ab,0x48ac,0x48ad,0x48ae,0x48af, + 0x48b0,0x48b1,0x48b2,0x48b3,0x48b4,0x48b5,0x48b6,0x48b7, + 0x48b8,0x48b9,0x48ba,0x48bb,0x48bc,0x48bd,0x48be,0x48bf, + 0x48c0,0x48c1,0x48c2,0x48c3,0x48c4,0x48c5,0x48c6,0x48c7, + 0x48c8,0x48c9,0x48ca,0x48cb,0x48cc,0x48cd,0x48ce,0x48cf, + 0x48d0,0x48d1,0x48d2,0x48d3,0x48d4,0x48d5,0x48d6,0x48d7, + 0x48d8,0x48d9,0x48da,0x48db,0x48dc,0x48dd,0x48de,0x48df, + 0x48e0,0x48e1,0x48e2,0x48e3,0x48e4,0x48e5,0x48e6,0x48e7, + 0x48e8,0x48e9,0x48ea,0x48eb,0x48ec,0x48ed,0x48ee,0x48ef, + 0x48f0,0x48f1,0x48f2,0x48f3,0x48f4,0x48f5,0x48f6,0x48f7, + 0x48f8,0x48f9,0x48fa,0x48fb,0x48fc,0x48fd,0x48fe,0x48ff, + 0x4900,0x4901,0x4902,0x4903,0x4904,0x4905,0x4906,0x4907, + 0x4908,0x4909,0x490a,0x490b,0x490c,0x490d,0x490e,0x490f, + 0x4910,0x4911,0x4912,0x4913,0x4914,0x4915,0x4916,0x4917, + 0x4918,0x4919,0x491a,0x491b,0x491c,0x491d,0x491e,0x491f, + 0x4920,0x4921,0x4922,0x4923,0x4924,0x4925,0x4926,0x4927, + 0x4928,0x4929,0x492a,0x492b,0x492c,0x492d,0x492e,0x492f, + 0x4930,0x4931,0x4932,0x4933,0x4934,0x4935,0x4936,0x4937, + 0x4938,0x4939,0x493a,0x493b,0x493c,0x493d,0x493e,0x493f, + 0x4940,0x4941,0x4942,0x4943,0x4944,0x4945,0x4946,0x4947, + 0x4948,0x4949,0x494a,0x494b,0x494c,0x494d,0x494e,0x494f, + 0x4950,0x4951,0x4952,0x4953,0x4954,0x4955,0x4956,0x4957, + 0x4958,0x4959,0x495a,0x495b,0x495c,0x495d,0x495e,0x495f, + 0x4960,0x4961,0x4962,0x4963,0x4964,0x4965,0x4966,0x4967, + 0x4968,0x4969,0x496a,0x496b,0x496c,0x496d,0x496e,0x496f, + 0x4970,0x4971,0x4972,0x4973,0x4974,0x4975,0x4976,0x4977, + 0x4978,0x4979,0x497a,0x497b,0x497c,0x497d,0x497e,0x497f, + 0x4980,0x4981,0x4982,0x4983,0x4984,0x4985,0x4986,0x4987, + 0x4988,0x4989,0x498a,0x498b,0x498c,0x498d,0x498e,0x498f, + 0x4990,0x4991,0x4992,0x4993,0x4994,0x4995,0x4996,0x4997, + 0x4998,0x4999,0x499a,0x499b,0x499c,0x499d,0x499e,0x499f, + 0x49a0,0x49a1,0x49a2,0x49a3,0x49a4,0x49a5,0x49a6,0x49a7, + 0x49a8,0x49a9,0x49aa,0x49ab,0x49ac,0x49ad,0x49ae,0x49af, + 0x49b0,0x49b1,0x49b2,0x49b3,0x49b4,0x49b5,0x49b6,0x49b7, + 0x49b8,0x49b9,0x49ba,0x49bb,0x49bc,0x49bd,0x49be,0x49bf, + 0x49c0,0x49c1,0x49c2,0x49c3,0x49c4,0x49c5,0x49c6,0x49c7, + 0x49c8,0x49c9,0x49ca,0x49cb,0x49cc,0x49cd,0x49ce,0x49cf, + 0x49d0,0x49d1,0x49d2,0x49d3,0x49d4,0x49d5,0x49d6,0x49d7, + 0x49d8,0x49d9,0x49da,0x49db,0x49dc,0x49dd,0x49de,0x49df, + 0x49e0,0x49e1,0x49e2,0x49e3,0x49e4,0x49e5,0x49e6,0x49e7, + 0x49e8,0x49e9,0x49ea,0x49eb,0x49ec,0x49ed,0x49ee,0x49ef, + 0x49f0,0x49f1,0x49f2,0x49f3,0x49f4,0x49f5,0x49f6,0x49f7, + 0x49f8,0x49f9,0x49fa,0x49fb,0x49fc,0x49fd,0x49fe,0x49ff, + 0x4a00,0x4a01,0x4a02,0x4a03,0x4a04,0x4a05,0x4a06,0x4a07, + 0x4a08,0x4a09,0x4a0a,0x4a0b,0x4a0c,0x4a0d,0x4a0e,0x4a0f, + 0x4a10,0x4a11,0x4a12,0x4a13,0x4a14,0x4a15,0x4a16,0x4a17, + 0x4a18,0x4a19,0x4a1a,0x4a1b,0x4a1c,0x4a1d,0x4a1e,0x4a1f, + 0x4a20,0x4a21,0x4a22,0x4a23,0x4a24,0x4a25,0x4a26,0x4a27, + 0x4a28,0x4a29,0x4a2a,0x4a2b,0x4a2c,0x4a2d,0x4a2e,0x4a2f, + 0x4a30,0x4a31,0x4a32,0x4a33,0x4a34,0x4a35,0x4a36,0x4a37, + 0x4a38,0x4a39,0x4a3a,0x4a3b,0x4a3c,0x4a3d,0x4a3e,0x4a3f, + 0x4a40,0x4a41,0x4a42,0x4a43,0x4a44,0x4a45,0x4a46,0x4a47, + 0x4a48,0x4a49,0x4a4a,0x4a4b,0x4a4c,0x4a4d,0x4a4e,0x4a4f, + 0x4a50,0x4a51,0x4a52,0x4a53,0x4a54,0x4a55,0x4a56,0x4a57, + 0x4a58,0x4a59,0x4a5a,0x4a5b,0x4a5c,0x4a5d,0x4a5e,0x4a5f, + 0x4a60,0x4a61,0x4a62,0x4a63,0x4a64,0x4a65,0x4a66,0x4a67, + 0x4a68,0x4a69,0x4a6a,0x4a6b,0x4a6c,0x4a6d,0x4a6e,0x4a6f, + 0x4a70,0x4a71,0x4a72,0x4a73,0x4a74,0x4a75,0x4a76,0x4a77, + 0x4a78,0x4a79,0x4a7a,0x4a7b,0x4a7c,0x4a7d,0x4a7e,0x4a7f, + 0x4a80,0x4a81,0x4a82,0x4a83,0x4a84,0x4a85,0x4a86,0x4a87, + 0x4a88,0x4a89,0x4a8a,0x4a8b,0x4a8c,0x4a8d,0x4a8e,0x4a8f, + 0x4a90,0x4a91,0x4a92,0x4a93,0x4a94,0x4a95,0x4a96,0x4a97, + 0x4a98,0x4a99,0x4a9a,0x4a9b,0x4a9c,0x4a9d,0x4a9e,0x4a9f, + 0x4aa0,0x4aa1,0x4aa2,0x4aa3,0x4aa4,0x4aa5,0x4aa6,0x4aa7, + 0x4aa8,0x4aa9,0x4aaa,0x4aab,0x4aac,0x4aad,0x4aae,0x4aaf, + 0x4ab0,0x4ab1,0x4ab2,0x4ab3,0x4ab4,0x4ab5,0x4ab6,0x4ab7, + 0x4ab8,0x4ab9,0x4aba,0x4abb,0x4abc,0x4abd,0x4abe,0x4abf, + 0x4ac0,0x4ac1,0x4ac2,0x4ac3,0x4ac4,0x4ac5,0x4ac6,0x4ac7, + 0x4ac8,0x4ac9,0x4aca,0x4acb,0x4acc,0x4acd,0x4ace,0x4acf, + 0x4ad0,0x4ad1,0x4ad2,0x4ad3,0x4ad4,0x4ad5,0x4ad6,0x4ad7, + 0x4ad8,0x4ad9,0x4ada,0x4adb,0x4adc,0x4add,0x4ade,0x4adf, + 0x4ae0,0x4ae1,0x4ae2,0x4ae3,0x4ae4,0x4ae5,0x4ae6,0x4ae7, + 0x4ae8,0x4ae9,0x4aea,0x4aeb,0x4aec,0x4aed,0x4aee,0x4aef, + 0x4af0,0x4af1,0x4af2,0x4af3,0x4af4,0x4af5,0x4af6,0x4af7, + 0x4af8,0x4af9,0x4afa,0x4afb,0x4afc,0x4afd,0x4afe,0x4aff, + 0x4b00,0x4b01,0x4b02,0x4b03,0x4b04,0x4b05,0x4b06,0x4b07, + 0x4b08,0x4b09,0x4b0a,0x4b0b,0x4b0c,0x4b0d,0x4b0e,0x4b0f, + 0x4b10,0x4b11,0x4b12,0x4b13,0x4b14,0x4b15,0x4b16,0x4b17, + 0x4b18,0x4b19,0x4b1a,0x4b1b,0x4b1c,0x4b1d,0x4b1e,0x4b1f, + 0x4b20,0x4b21,0x4b22,0x4b23,0x4b24,0x4b25,0x4b26,0x4b27, + 0x4b28,0x4b29,0x4b2a,0x4b2b,0x4b2c,0x4b2d,0x4b2e,0x4b2f, + 0x4b30,0x4b31,0x4b32,0x4b33,0x4b34,0x4b35,0x4b36,0x4b37, + 0x4b38,0x4b39,0x4b3a,0x4b3b,0x4b3c,0x4b3d,0x4b3e,0x4b3f, + 0x4b40,0x4b41,0x4b42,0x4b43,0x4b44,0x4b45,0x4b46,0x4b47, + 0x4b48,0x4b49,0x4b4a,0x4b4b,0x4b4c,0x4b4d,0x4b4e,0x4b4f, + 0x4b50,0x4b51,0x4b52,0x4b53,0x4b54,0x4b55,0x4b56,0x4b57, + 0x4b58,0x4b59,0x4b5a,0x4b5b,0x4b5c,0x4b5d,0x4b5e,0x4b5f, + 0x4b60,0x4b61,0x4b62,0x4b63,0x4b64,0x4b65,0x4b66,0x4b67, + 0x4b68,0x4b69,0x4b6a,0x4b6b,0x4b6c,0x4b6d,0x4b6e,0x4b6f, + 0x4b70,0x4b71,0x4b72,0x4b73,0x4b74,0x4b75,0x4b76,0x4b77, + 0x4b78,0x4b79,0x4b7a,0x4b7b,0x4b7c,0x4b7d,0x4b7e,0x4b7f, + 0x4b80,0x4b81,0x4b82,0x4b83,0x4b84,0x4b85,0x4b86,0x4b87, + 0x4b88,0x4b89,0x4b8a,0x4b8b,0x4b8c,0x4b8d,0x4b8e,0x4b8f, + 0x4b90,0x4b91,0x4b92,0x4b93,0x4b94,0x4b95,0x4b96,0x4b97, + 0x4b98,0x4b99,0x4b9a,0x4b9b,0x4b9c,0x4b9d,0x4b9e,0x4b9f, + 0x4ba0,0x4ba1,0x4ba2,0x4ba3,0x4ba4,0x4ba5,0x4ba6,0x4ba7, + 0x4ba8,0x4ba9,0x4baa,0x4bab,0x4bac,0x4bad,0x4bae,0x4baf, + 0x4bb0,0x4bb1,0x4bb2,0x4bb3,0x4bb4,0x4bb5,0x4bb6,0x4bb7, + 0x4bb8,0x4bb9,0x4bba,0x4bbb,0x4bbc,0x4bbd,0x4bbe,0x4bbf, + 0x4bc0,0x4bc1,0x4bc2,0x4bc3,0x4bc4,0x4bc5,0x4bc6,0x4bc7, + 0x4bc8,0x4bc9,0x4bca,0x4bcb,0x4bcc,0x4bcd,0x4bce,0x4bcf, + 0x4bd0,0x4bd1,0x4bd2,0x4bd3,0x4bd4,0x4bd5,0x4bd6,0x4bd7, + 0x4bd8,0x4bd9,0x4bda,0x4bdb,0x4bdc,0x4bdd,0x4bde,0x4bdf, + 0x4be0,0x4be1,0x4be2,0x4be3,0x4be4,0x4be5,0x4be6,0x4be7, + 0x4be8,0x4be9,0x4bea,0x4beb,0x4bec,0x4bed,0x4bee,0x4bef, + 0x4bf0,0x4bf1,0x4bf2,0x4bf3,0x4bf4,0x4bf5,0x4bf6,0x4bf7, + 0x4bf8,0x4bf9,0x4bfa,0x4bfb,0x4bfc,0x4bfd,0x4bfe,0x4bff, + 0x4c00,0x4c01,0x4c02,0x4c03,0x4c04,0x4c05,0x4c06,0x4c07, + 0x4c08,0x4c09,0x4c0a,0x4c0b,0x4c0c,0x4c0d,0x4c0e,0x4c0f, + 0x4c10,0x4c11,0x4c12,0x4c13,0x4c14,0x4c15,0x4c16,0x4c17, + 0x4c18,0x4c19,0x4c1a,0x4c1b,0x4c1c,0x4c1d,0x4c1e,0x4c1f, + 0x4c20,0x4c21,0x4c22,0x4c23,0x4c24,0x4c25,0x4c26,0x4c27, + 0x4c28,0x4c29,0x4c2a,0x4c2b,0x4c2c,0x4c2d,0x4c2e,0x4c2f, + 0x4c30,0x4c31,0x4c32,0x4c33,0x4c34,0x4c35,0x4c36,0x4c37, + 0x4c38,0x4c39,0x4c3a,0x4c3b,0x4c3c,0x4c3d,0x4c3e,0x4c3f, + 0x4c40,0x4c41,0x4c42,0x4c43,0x4c44,0x4c45,0x4c46,0x4c47, + 0x4c48,0x4c49,0x4c4a,0x4c4b,0x4c4c,0x4c4d,0x4c4e,0x4c4f, + 0x4c50,0x4c51,0x4c52,0x4c53,0x4c54,0x4c55,0x4c56,0x4c57, + 0x4c58,0x4c59,0x4c5a,0x4c5b,0x4c5c,0x4c5d,0x4c5e,0x4c5f, + 0x4c60,0x4c61,0x4c62,0x4c63,0x4c64,0x4c65,0x4c66,0x4c67, + 0x4c68,0x4c69,0x4c6a,0x4c6b,0x4c6c,0x4c6d,0x4c6e,0x4c6f, + 0x4c70,0x4c71,0x4c72,0x4c73,0x4c74,0x4c75,0x4c76,0x4c77, + 0x4c78,0x4c79,0x4c7a,0x4c7b,0x4c7c,0x4c7d,0x4c7e,0x4c7f, + 0x4c80,0x4c81,0x4c82,0x4c83,0x4c84,0x4c85,0x4c86,0x4c87, + 0x4c88,0x4c89,0x4c8a,0x4c8b,0x4c8c,0x4c8d,0x4c8e,0x4c8f, + 0x4c90,0x4c91,0x4c92,0x4c93,0x4c94,0x4c95,0x4c96,0x4c97, + 0x4c98,0x4c99,0x4c9a,0x4c9b,0x4c9c,0x4c9d,0x4c9e,0x4c9f, + 0x4ca0,0x4ca1,0x4ca2,0x4ca3,0x4ca4,0x4ca5,0x4ca6,0x4ca7, + 0x4ca8,0x4ca9,0x4caa,0x4cab,0x4cac,0x4cad,0x4cae,0x4caf, + 0x4cb0,0x4cb1,0x4cb2,0x4cb3,0x4cb4,0x4cb5,0x4cb6,0x4cb7, + 0x4cb8,0x4cb9,0x4cba,0x4cbb,0x4cbc,0x4cbd,0x4cbe,0x4cbf, + 0x4cc0,0x4cc1,0x4cc2,0x4cc3,0x4cc4,0x4cc5,0x4cc6,0x4cc7, + 0x4cc8,0x4cc9,0x4cca,0x4ccb,0x4ccc,0x4ccd,0x4cce,0x4ccf, + 0x4cd0,0x4cd1,0x4cd2,0x4cd3,0x4cd4,0x4cd5,0x4cd6,0x4cd7, + 0x4cd8,0x4cd9,0x4cda,0x4cdb,0x4cdc,0x4cdd,0x4cde,0x4cdf, + 0x4ce0,0x4ce1,0x4ce2,0x4ce3,0x4ce4,0x4ce5,0x4ce6,0x4ce7, + 0x4ce8,0x4ce9,0x4cea,0x4ceb,0x4cec,0x4ced,0x4cee,0x4cef, + 0x4cf0,0x4cf1,0x4cf2,0x4cf3,0x4cf4,0x4cf5,0x4cf6,0x4cf7, + 0x4cf8,0x4cf9,0x4cfa,0x4cfb,0x4cfc,0x4cfd,0x4cfe,0x4cff, + 0x4d00,0x4d01,0x4d02,0x4d03,0x4d04,0x4d05,0x4d06,0x4d07, + 0x4d08,0x4d09,0x4d0a,0x4d0b,0x4d0c,0x4d0d,0x4d0e,0x4d0f, + 0x4d10,0x4d11,0x4d12,0x4d13,0x4d14,0x4d15,0x4d16,0x4d17, + 0x4d18,0x4d19,0x4d1a,0x4d1b,0x4d1c,0x4d1d,0x4d1e,0x4d1f, + 0x4d20,0x4d21,0x4d22,0x4d23,0x4d24,0x4d25,0x4d26,0x4d27, + 0x4d28,0x4d29,0x4d2a,0x4d2b,0x4d2c,0x4d2d,0x4d2e,0x4d2f, + 0x4d30,0x4d31,0x4d32,0x4d33,0x4d34,0x4d35,0x4d36,0x4d37, + 0x4d38,0x4d39,0x4d3a,0x4d3b,0x4d3c,0x4d3d,0x4d3e,0x4d3f, + 0x4d40,0x4d41,0x4d42,0x4d43,0x4d44,0x4d45,0x4d46,0x4d47, + 0x4d48,0x4d49,0x4d4a,0x4d4b,0x4d4c,0x4d4d,0x4d4e,0x4d4f, + 0x4d50,0x4d51,0x4d52,0x4d53,0x4d54,0x4d55,0x4d56,0x4d57, + 0x4d58,0x4d59,0x4d5a,0x4d5b,0x4d5c,0x4d5d,0x4d5e,0x4d5f, + 0x4d60,0x4d61,0x4d62,0x4d63,0x4d64,0x4d65,0x4d66,0x4d67, + 0x4d68,0x4d69,0x4d6a,0x4d6b,0x4d6c,0x4d6d,0x4d6e,0x4d6f, + 0x4d70,0x4d71,0x4d72,0x4d73,0x4d74,0x4d75,0x4d76,0x4d77, + 0x4d78,0x4d79,0x4d7a,0x4d7b,0x4d7c,0x4d7d,0x4d7e,0x4d7f, + 0x4d80,0x4d81,0x4d82,0x4d83,0x4d84,0x4d85,0x4d86,0x4d87, + 0x4d88,0x4d89,0x4d8a,0x4d8b,0x4d8c,0x4d8d,0x4d8e,0x4d8f, + 0x4d90,0x4d91,0x4d92,0x4d93,0x4d94,0x4d95,0x4d96,0x4d97, + 0x4d98,0x4d99,0x4d9a,0x4d9b,0x4d9c,0x4d9d,0x4d9e,0x4d9f, + 0x4da0,0x4da1,0x4da2,0x4da3,0x4da4,0x4da5,0x4da6,0x4da7, + 0x4da8,0x4da9,0x4daa,0x4dab,0x4dac,0x4dad,0x4dae,0x4daf, + 0x4db0,0x4db1,0x4db2,0x4db3,0x4db4,0x4db5,0x4db6,0x4db7, + 0x4db8,0x4db9,0x4dba,0x4dbb,0x4dbc,0x4dbd,0x4dbe,0x4dbf, + 0x4dc0,0x4dc1,0x4dc2,0x4dc3,0x4dc4,0x4dc5,0x4dc6,0x4dc7, + 0x4dc8,0x4dc9,0x4dca,0x4dcb,0x4dcc,0x4dcd,0x4dce,0x4dcf, + 0x4dd0,0x4dd1,0x4dd2,0x4dd3,0x4dd4,0x4dd5,0x4dd6,0x4dd7, + 0x4dd8,0x4dd9,0x4dda,0x4ddb,0x4ddc,0x4ddd,0x4dde,0x4ddf, + 0x4de0,0x4de1,0x4de2,0x4de3,0x4de4,0x4de5,0x4de6,0x4de7, + 0x4de8,0x4de9,0x4dea,0x4deb,0x4dec,0x4ded,0x4dee,0x4def, + 0x4df0,0x4df1,0x4df2,0x4df3,0x4df4,0x4df5,0x4df6,0x4df7, + 0x4df8,0x4df9,0x4dfa,0x4dfb,0x4dfc,0x4dfd,0x4dfe,0x4dff, + 0x4e00,0x4e01,0x4e02,0x4e03,0x4e04,0x4e05,0x4e06,0x4e07, + 0x4e08,0x4e09,0x4e0a,0x4e0b,0x4e0c,0x4e0d,0x4e0e,0x4e0f, + 0x4e10,0x4e11,0x4e12,0x4e13,0x4e14,0x4e15,0x4e16,0x4e17, + 0x4e18,0x4e19,0x4e1a,0x4e1b,0x4e1c,0x4e1d,0x4e1e,0x4e1f, + 0x4e20,0x4e21,0x4e22,0x4e23,0x4e24,0x4e25,0x4e26,0x4e27, + 0x4e28,0x4e29,0x4e2a,0x4e2b,0x4e2c,0x4e2d,0x4e2e,0x4e2f, + 0x4e30,0x4e31,0x4e32,0x4e33,0x4e34,0x4e35,0x4e36,0x4e37, + 0x4e38,0x4e39,0x4e3a,0x4e3b,0x4e3c,0x4e3d,0x4e3e,0x4e3f, + 0x4e40,0x4e41,0x4e42,0x4e43,0x4e44,0x4e45,0x4e46,0x4e47, + 0x4e48,0x4e49,0x4e4a,0x4e4b,0x4e4c,0x4e4d,0x4e4e,0x4e4f, + 0x4e50,0x4e51,0x4e52,0x4e53,0x4e54,0x4e55,0x4e56,0x4e57, + 0x4e58,0x4e59,0x4e5a,0x4e5b,0x4e5c,0x4e5d,0x4e5e,0x4e5f, + 0x4e60,0x4e61,0x4e62,0x4e63,0x4e64,0x4e65,0x4e66,0x4e67, + 0x4e68,0x4e69,0x4e6a,0x4e6b,0x4e6c,0x4e6d,0x4e6e,0x4e6f, + 0x4e70,0x4e71,0x4e72,0x4e73,0x4e74,0x4e75,0x4e76,0x4e77, + 0x4e78,0x4e79,0x4e7a,0x4e7b,0x4e7c,0x4e7d,0x4e7e,0x4e7f, + 0x4e80,0x4e81,0x4e82,0x4e83,0x4e84,0x4e85,0x4e86,0x4e87, + 0x4e88,0x4e89,0x4e8a,0x4e8b,0x4e8c,0x4e8d,0x4e8e,0x4e8f, + 0x4e90,0x4e91,0x4e92,0x4e93,0x4e94,0x4e95,0x4e96,0x4e97, + 0x4e98,0x4e99,0x4e9a,0x4e9b,0x4e9c,0x4e9d,0x4e9e,0x4e9f, + 0x4ea0,0x4ea1,0x4ea2,0x4ea3,0x4ea4,0x4ea5,0x4ea6,0x4ea7, + 0x4ea8,0x4ea9,0x4eaa,0x4eab,0x4eac,0x4ead,0x4eae,0x4eaf, + 0x4eb0,0x4eb1,0x4eb2,0x4eb3,0x4eb4,0x4eb5,0x4eb6,0x4eb7, + 0x4eb8,0x4eb9,0x4eba,0x4ebb,0x4ebc,0x4ebd,0x4ebe,0x4ebf, + 0x4ec0,0x4ec1,0x4ec2,0x4ec3,0x4ec4,0x4ec5,0x4ec6,0x4ec7, + 0x4ec8,0x4ec9,0x4eca,0x4ecb,0x4ecc,0x4ecd,0x4ece,0x4ecf, + 0x4ed0,0x4ed1,0x4ed2,0x4ed3,0x4ed4,0x4ed5,0x4ed6,0x4ed7, + 0x4ed8,0x4ed9,0x4eda,0x4edb,0x4edc,0x4edd,0x4ede,0x4edf, + 0x4ee0,0x4ee1,0x4ee2,0x4ee3,0x4ee4,0x4ee5,0x4ee6,0x4ee7, + 0x4ee8,0x4ee9,0x4eea,0x4eeb,0x4eec,0x4eed,0x4eee,0x4eef, + 0x4ef0,0x4ef1,0x4ef2,0x4ef3,0x4ef4,0x4ef5,0x4ef6,0x4ef7, + 0x4ef8,0x4ef9,0x4efa,0x4efb,0x4efc,0x4efd,0x4efe,0x4eff, + 0x4f00,0x4f01,0x4f02,0x4f03,0x4f04,0x4f05,0x4f06,0x4f07, + 0x4f08,0x4f09,0x4f0a,0x4f0b,0x4f0c,0x4f0d,0x4f0e,0x4f0f, + 0x4f10,0x4f11,0x4f12,0x4f13,0x4f14,0x4f15,0x4f16,0x4f17, + 0x4f18,0x4f19,0x4f1a,0x4f1b,0x4f1c,0x4f1d,0x4f1e,0x4f1f, + 0x4f20,0x4f21,0x4f22,0x4f23,0x4f24,0x4f25,0x4f26,0x4f27, + 0x4f28,0x4f29,0x4f2a,0x4f2b,0x4f2c,0x4f2d,0x4f2e,0x4f2f, + 0x4f30,0x4f31,0x4f32,0x4f33,0x4f34,0x4f35,0x4f36,0x4f37, + 0x4f38,0x4f39,0x4f3a,0x4f3b,0x4f3c,0x4f3d,0x4f3e,0x4f3f, + 0x4f40,0x4f41,0x4f42,0x4f43,0x4f44,0x4f45,0x4f46,0x4f47, + 0x4f48,0x4f49,0x4f4a,0x4f4b,0x4f4c,0x4f4d,0x4f4e,0x4f4f, + 0x4f50,0x4f51,0x4f52,0x4f53,0x4f54,0x4f55,0x4f56,0x4f57, + 0x4f58,0x4f59,0x4f5a,0x4f5b,0x4f5c,0x4f5d,0x4f5e,0x4f5f, + 0x4f60,0x4f61,0x4f62,0x4f63,0x4f64,0x4f65,0x4f66,0x4f67, + 0x4f68,0x4f69,0x4f6a,0x4f6b,0x4f6c,0x4f6d,0x4f6e,0x4f6f, + 0x4f70,0x4f71,0x4f72,0x4f73,0x4f74,0x4f75,0x4f76,0x4f77, + 0x4f78,0x4f79,0x4f7a,0x4f7b,0x4f7c,0x4f7d,0x4f7e,0x4f7f, + 0x4f80,0x4f81,0x4f82,0x4f83,0x4f84,0x4f85,0x4f86,0x4f87, + 0x4f88,0x4f89,0x4f8a,0x4f8b,0x4f8c,0x4f8d,0x4f8e,0x4f8f, + 0x4f90,0x4f91,0x4f92,0x4f93,0x4f94,0x4f95,0x4f96,0x4f97, + 0x4f98,0x4f99,0x4f9a,0x4f9b,0x4f9c,0x4f9d,0x4f9e,0x4f9f, + 0x4fa0,0x4fa1,0x4fa2,0x4fa3,0x4fa4,0x4fa5,0x4fa6,0x4fa7, + 0x4fa8,0x4fa9,0x4faa,0x4fab,0x4fac,0x4fad,0x4fae,0x4faf, + 0x4fb0,0x4fb1,0x4fb2,0x4fb3,0x4fb4,0x4fb5,0x4fb6,0x4fb7, + 0x4fb8,0x4fb9,0x4fba,0x4fbb,0x4fbc,0x4fbd,0x4fbe,0x4fbf, + 0x4fc0,0x4fc1,0x4fc2,0x4fc3,0x4fc4,0x4fc5,0x4fc6,0x4fc7, + 0x4fc8,0x4fc9,0x4fca,0x4fcb,0x4fcc,0x4fcd,0x4fce,0x4fcf, + 0x4fd0,0x4fd1,0x4fd2,0x4fd3,0x4fd4,0x4fd5,0x4fd6,0x4fd7, + 0x4fd8,0x4fd9,0x4fda,0x4fdb,0x4fdc,0x4fdd,0x4fde,0x4fdf, + 0x4fe0,0x4fe1,0x4fe2,0x4fe3,0x4fe4,0x4fe5,0x4fe6,0x4fe7, + 0x4fe8,0x4fe9,0x4fea,0x4feb,0x4fec,0x4fed,0x4fee,0x4fef, + 0x4ff0,0x4ff1,0x4ff2,0x4ff3,0x4ff4,0x4ff5,0x4ff6,0x4ff7, + 0x4ff8,0x4ff9,0x4ffa,0x4ffb,0x4ffc,0x4ffd,0x4ffe,0x4fff, + 0x5000,0x5001,0x5002,0x5003,0x5004,0x5005,0x5006,0x5007, + 0x5008,0x5009,0x500a,0x500b,0x500c,0x500d,0x500e,0x500f, + 0x5010,0x5011,0x5012,0x5013,0x5014,0x5015,0x5016,0x5017, + 0x5018,0x5019,0x501a,0x501b,0x501c,0x501d,0x501e,0x501f, + 0x5020,0x5021,0x5022,0x5023,0x5024,0x5025,0x5026,0x5027, + 0x5028,0x5029,0x502a,0x502b,0x502c,0x502d,0x502e,0x502f, + 0x5030,0x5031,0x5032,0x5033,0x5034,0x5035,0x5036,0x5037, + 0x5038,0x5039,0x503a,0x503b,0x503c,0x503d,0x503e,0x503f, + 0x5040,0x5041,0x5042,0x5043,0x5044,0x5045,0x5046,0x5047, + 0x5048,0x5049,0x504a,0x504b,0x504c,0x504d,0x504e,0x504f, + 0x5050,0x5051,0x5052,0x5053,0x5054,0x5055,0x5056,0x5057, + 0x5058,0x5059,0x505a,0x505b,0x505c,0x505d,0x505e,0x505f, + 0x5060,0x5061,0x5062,0x5063,0x5064,0x5065,0x5066,0x5067, + 0x5068,0x5069,0x506a,0x506b,0x506c,0x506d,0x506e,0x506f, + 0x5070,0x5071,0x5072,0x5073,0x5074,0x5075,0x5076,0x5077, + 0x5078,0x5079,0x507a,0x507b,0x507c,0x507d,0x507e,0x507f, + 0x5080,0x5081,0x5082,0x5083,0x5084,0x5085,0x5086,0x5087, + 0x5088,0x5089,0x508a,0x508b,0x508c,0x508d,0x508e,0x508f, + 0x5090,0x5091,0x5092,0x5093,0x5094,0x5095,0x5096,0x5097, + 0x5098,0x5099,0x509a,0x509b,0x509c,0x509d,0x509e,0x509f, + 0x50a0,0x50a1,0x50a2,0x50a3,0x50a4,0x50a5,0x50a6,0x50a7, + 0x50a8,0x50a9,0x50aa,0x50ab,0x50ac,0x50ad,0x50ae,0x50af, + 0x50b0,0x50b1,0x50b2,0x50b3,0x50b4,0x50b5,0x50b6,0x50b7, + 0x50b8,0x50b9,0x50ba,0x50bb,0x50bc,0x50bd,0x50be,0x50bf, + 0x50c0,0x50c1,0x50c2,0x50c3,0x50c4,0x50c5,0x50c6,0x50c7, + 0x50c8,0x50c9,0x50ca,0x50cb,0x50cc,0x50cd,0x50ce,0x50cf, + 0x50d0,0x50d1,0x50d2,0x50d3,0x50d4,0x50d5,0x50d6,0x50d7, + 0x50d8,0x50d9,0x50da,0x50db,0x50dc,0x50dd,0x50de,0x50df, + 0x50e0,0x50e1,0x50e2,0x50e3,0x50e4,0x50e5,0x50e6,0x50e7, + 0x50e8,0x50e9,0x50ea,0x50eb,0x50ec,0x50ed,0x50ee,0x50ef, + 0x50f0,0x50f1,0x50f2,0x50f3,0x50f4,0x50f5,0x50f6,0x50f7, + 0x50f8,0x50f9,0x50fa,0x50fb,0x50fc,0x50fd,0x50fe,0x50ff, + 0x5100,0x5101,0x5102,0x5103,0x5104,0x5105,0x5106,0x5107, + 0x5108,0x5109,0x510a,0x510b,0x510c,0x510d,0x510e,0x510f, + 0x5110,0x5111,0x5112,0x5113,0x5114,0x5115,0x5116,0x5117, + 0x5118,0x5119,0x511a,0x511b,0x511c,0x511d,0x511e,0x511f, + 0x5120,0x5121,0x5122,0x5123,0x5124,0x5125,0x5126,0x5127, + 0x5128,0x5129,0x512a,0x512b,0x512c,0x512d,0x512e,0x512f, + 0x5130,0x5131,0x5132,0x5133,0x5134,0x5135,0x5136,0x5137, + 0x5138,0x5139,0x513a,0x513b,0x513c,0x513d,0x513e,0x513f, + 0x5140,0x5141,0x5142,0x5143,0x5144,0x5145,0x5146,0x5147, + 0x5148,0x5149,0x514a,0x514b,0x514c,0x514d,0x514e,0x514f, + 0x5150,0x5151,0x5152,0x5153,0x5154,0x5155,0x5156,0x5157, + 0x5158,0x5159,0x515a,0x515b,0x515c,0x515d,0x515e,0x515f, + 0x5160,0x5161,0x5162,0x5163,0x5164,0x5165,0x5166,0x5167, + 0x5168,0x5169,0x516a,0x516b,0x516c,0x516d,0x516e,0x516f, + 0x5170,0x5171,0x5172,0x5173,0x5174,0x5175,0x5176,0x5177, + 0x5178,0x5179,0x517a,0x517b,0x517c,0x517d,0x517e,0x517f, + 0x5180,0x5181,0x5182,0x5183,0x5184,0x5185,0x5186,0x5187, + 0x5188,0x5189,0x518a,0x518b,0x518c,0x518d,0x518e,0x518f, + 0x5190,0x5191,0x5192,0x5193,0x5194,0x5195,0x5196,0x5197, + 0x5198,0x5199,0x519a,0x519b,0x519c,0x519d,0x519e,0x519f, + 0x51a0,0x51a1,0x51a2,0x51a3,0x51a4,0x51a5,0x51a6,0x51a7, + 0x51a8,0x51a9,0x51aa,0x51ab,0x51ac,0x51ad,0x51ae,0x51af, + 0x51b0,0x51b1,0x51b2,0x51b3,0x51b4,0x51b5,0x51b6,0x51b7, + 0x51b8,0x51b9,0x51ba,0x51bb,0x51bc,0x51bd,0x51be,0x51bf, + 0x51c0,0x51c1,0x51c2,0x51c3,0x51c4,0x51c5,0x51c6,0x51c7, + 0x51c8,0x51c9,0x51ca,0x51cb,0x51cc,0x51cd,0x51ce,0x51cf, + 0x51d0,0x51d1,0x51d2,0x51d3,0x51d4,0x51d5,0x51d6,0x51d7, + 0x51d8,0x51d9,0x51da,0x51db,0x51dc,0x51dd,0x51de,0x51df, + 0x51e0,0x51e1,0x51e2,0x51e3,0x51e4,0x51e5,0x51e6,0x51e7, + 0x51e8,0x51e9,0x51ea,0x51eb,0x51ec,0x51ed,0x51ee,0x51ef, + 0x51f0,0x51f1,0x51f2,0x51f3,0x51f4,0x51f5,0x51f6,0x51f7, + 0x51f8,0x51f9,0x51fa,0x51fb,0x51fc,0x51fd,0x51fe,0x51ff, + 0x5200,0x5201,0x5202,0x5203,0x5204,0x5205,0x5206,0x5207, + 0x5208,0x5209,0x520a,0x520b,0x520c,0x520d,0x520e,0x520f, + 0x5210,0x5211,0x5212,0x5213,0x5214,0x5215,0x5216,0x5217, + 0x5218,0x5219,0x521a,0x521b,0x521c,0x521d,0x521e,0x521f, + 0x5220,0x5221,0x5222,0x5223,0x5224,0x5225,0x5226,0x5227, + 0x5228,0x5229,0x522a,0x522b,0x522c,0x522d,0x522e,0x522f, + 0x5230,0x5231,0x5232,0x5233,0x5234,0x5235,0x5236,0x5237, + 0x5238,0x5239,0x523a,0x523b,0x523c,0x523d,0x523e,0x523f, + 0x5240,0x5241,0x5242,0x5243,0x5244,0x5245,0x5246,0x5247, + 0x5248,0x5249,0x524a,0x524b,0x524c,0x524d,0x524e,0x524f, + 0x5250,0x5251,0x5252,0x5253,0x5254,0x5255,0x5256,0x5257, + 0x5258,0x5259,0x525a,0x525b,0x525c,0x525d,0x525e,0x525f, + 0x5260,0x5261,0x5262,0x5263,0x5264,0x5265,0x5266,0x5267, + 0x5268,0x5269,0x526a,0x526b,0x526c,0x526d,0x526e,0x526f, + 0x5270,0x5271,0x5272,0x5273,0x5274,0x5275,0x5276,0x5277, + 0x5278,0x5279,0x527a,0x527b,0x527c,0x527d,0x527e,0x527f, + 0x5280,0x5281,0x5282,0x5283,0x5284,0x5285,0x5286,0x5287, + 0x5288,0x5289,0x528a,0x528b,0x528c,0x528d,0x528e,0x528f, + 0x5290,0x5291,0x5292,0x5293,0x5294,0x5295,0x5296,0x5297, + 0x5298,0x5299,0x529a,0x529b,0x529c,0x529d,0x529e,0x529f, + 0x52a0,0x52a1,0x52a2,0x52a3,0x52a4,0x52a5,0x52a6,0x52a7, + 0x52a8,0x52a9,0x52aa,0x52ab,0x52ac,0x52ad,0x52ae,0x52af, + 0x52b0,0x52b1,0x52b2,0x52b3,0x52b4,0x52b5,0x52b6,0x52b7, + 0x52b8,0x52b9,0x52ba,0x52bb,0x52bc,0x52bd,0x52be,0x52bf, + 0x52c0,0x52c1,0x52c2,0x52c3,0x52c4,0x52c5,0x52c6,0x52c7, + 0x52c8,0x52c9,0x52ca,0x52cb,0x52cc,0x52cd,0x52ce,0x52cf, + 0x52d0,0x52d1,0x52d2,0x52d3,0x52d4,0x52d5,0x52d6,0x52d7, + 0x52d8,0x52d9,0x52da,0x52db,0x52dc,0x52dd,0x52de,0x52df, + 0x52e0,0x52e1,0x52e2,0x52e3,0x52e4,0x52e5,0x52e6,0x52e7, + 0x52e8,0x52e9,0x52ea,0x52eb,0x52ec,0x52ed,0x52ee,0x52ef, + 0x52f0,0x52f1,0x52f2,0x52f3,0x52f4,0x52f5,0x52f6,0x52f7, + 0x52f8,0x52f9,0x52fa,0x52fb,0x52fc,0x52fd,0x52fe,0x52ff, + 0x5300,0x5301,0x5302,0x5303,0x5304,0x5305,0x5306,0x5307, + 0x5308,0x5309,0x530a,0x530b,0x530c,0x530d,0x530e,0x530f, + 0x5310,0x5311,0x5312,0x5313,0x5314,0x5315,0x5316,0x5317, + 0x5318,0x5319,0x531a,0x531b,0x531c,0x531d,0x531e,0x531f, + 0x5320,0x5321,0x5322,0x5323,0x5324,0x5325,0x5326,0x5327, + 0x5328,0x5329,0x532a,0x532b,0x532c,0x532d,0x532e,0x532f, + 0x5330,0x5331,0x5332,0x5333,0x5334,0x5335,0x5336,0x5337, + 0x5338,0x5339,0x533a,0x533b,0x533c,0x533d,0x533e,0x533f, + 0x5340,0x5341,0x5342,0x5343,0x5344,0x5345,0x5346,0x5347, + 0x5348,0x5349,0x534a,0x534b,0x534c,0x534d,0x534e,0x534f, + 0x5350,0x5351,0x5352,0x5353,0x5354,0x5355,0x5356,0x5357, + 0x5358,0x5359,0x535a,0x535b,0x535c,0x535d,0x535e,0x535f, + 0x5360,0x5361,0x5362,0x5363,0x5364,0x5365,0x5366,0x5367, + 0x5368,0x5369,0x536a,0x536b,0x536c,0x536d,0x536e,0x536f, + 0x5370,0x5371,0x5372,0x5373,0x5374,0x5375,0x5376,0x5377, + 0x5378,0x5379,0x537a,0x537b,0x537c,0x537d,0x537e,0x537f, + 0x5380,0x5381,0x5382,0x5383,0x5384,0x5385,0x5386,0x5387, + 0x5388,0x5389,0x538a,0x538b,0x538c,0x538d,0x538e,0x538f, + 0x5390,0x5391,0x5392,0x5393,0x5394,0x5395,0x5396,0x5397, + 0x5398,0x5399,0x539a,0x539b,0x539c,0x539d,0x539e,0x539f, + 0x53a0,0x53a1,0x53a2,0x53a3,0x53a4,0x53a5,0x53a6,0x53a7, + 0x53a8,0x53a9,0x53aa,0x53ab,0x53ac,0x53ad,0x53ae,0x53af, + 0x53b0,0x53b1,0x53b2,0x53b3,0x53b4,0x53b5,0x53b6,0x53b7, + 0x53b8,0x53b9,0x53ba,0x53bb,0x53bc,0x53bd,0x53be,0x53bf, + 0x53c0,0x53c1,0x53c2,0x53c3,0x53c4,0x53c5,0x53c6,0x53c7, + 0x53c8,0x53c9,0x53ca,0x53cb,0x53cc,0x53cd,0x53ce,0x53cf, + 0x53d0,0x53d1,0x53d2,0x53d3,0x53d4,0x53d5,0x53d6,0x53d7, + 0x53d8,0x53d9,0x53da,0x53db,0x53dc,0x53dd,0x53de,0x53df, + 0x53e0,0x53e1,0x53e2,0x53e3,0x53e4,0x53e5,0x53e6,0x53e7, + 0x53e8,0x53e9,0x53ea,0x53eb,0x53ec,0x53ed,0x53ee,0x53ef, + 0x53f0,0x53f1,0x53f2,0x53f3,0x53f4,0x53f5,0x53f6,0x53f7, + 0x53f8,0x53f9,0x53fa,0x53fb,0x53fc,0x53fd,0x53fe,0x53ff, + 0x5400,0x5401,0x5402,0x5403,0x5404,0x5405,0x5406,0x5407, + 0x5408,0x5409,0x540a,0x540b,0x540c,0x540d,0x540e,0x540f, + 0x5410,0x5411,0x5412,0x5413,0x5414,0x5415,0x5416,0x5417, + 0x5418,0x5419,0x541a,0x541b,0x541c,0x541d,0x541e,0x541f, + 0x5420,0x5421,0x5422,0x5423,0x5424,0x5425,0x5426,0x5427, + 0x5428,0x5429,0x542a,0x542b,0x542c,0x542d,0x542e,0x542f, + 0x5430,0x5431,0x5432,0x5433,0x5434,0x5435,0x5436,0x5437, + 0x5438,0x5439,0x543a,0x543b,0x543c,0x543d,0x543e,0x543f, + 0x5440,0x5441,0x5442,0x5443,0x5444,0x5445,0x5446,0x5447, + 0x5448,0x5449,0x544a,0x544b,0x544c,0x544d,0x544e,0x544f, + 0x5450,0x5451,0x5452,0x5453,0x5454,0x5455,0x5456,0x5457, + 0x5458,0x5459,0x545a,0x545b,0x545c,0x545d,0x545e,0x545f, + 0x5460,0x5461,0x5462,0x5463,0x5464,0x5465,0x5466,0x5467, + 0x5468,0x5469,0x546a,0x546b,0x546c,0x546d,0x546e,0x546f, + 0x5470,0x5471,0x5472,0x5473,0x5474,0x5475,0x5476,0x5477, + 0x5478,0x5479,0x547a,0x547b,0x547c,0x547d,0x547e,0x547f, + 0x5480,0x5481,0x5482,0x5483,0x5484,0x5485,0x5486,0x5487, + 0x5488,0x5489,0x548a,0x548b,0x548c,0x548d,0x548e,0x548f, + 0x5490,0x5491,0x5492,0x5493,0x5494,0x5495,0x5496,0x5497, + 0x5498,0x5499,0x549a,0x549b,0x549c,0x549d,0x549e,0x549f, + 0x54a0,0x54a1,0x54a2,0x54a3,0x54a4,0x54a5,0x54a6,0x54a7, + 0x54a8,0x54a9,0x54aa,0x54ab,0x54ac,0x54ad,0x54ae,0x54af, + 0x54b0,0x54b1,0x54b2,0x54b3,0x54b4,0x54b5,0x54b6,0x54b7, + 0x54b8,0x54b9,0x54ba,0x54bb,0x54bc,0x54bd,0x54be,0x54bf, + 0x54c0,0x54c1,0x54c2,0x54c3,0x54c4,0x54c5,0x54c6,0x54c7, + 0x54c8,0x54c9,0x54ca,0x54cb,0x54cc,0x54cd,0x54ce,0x54cf, + 0x54d0,0x54d1,0x54d2,0x54d3,0x54d4,0x54d5,0x54d6,0x54d7, + 0x54d8,0x54d9,0x54da,0x54db,0x54dc,0x54dd,0x54de,0x54df, + 0x54e0,0x54e1,0x54e2,0x54e3,0x54e4,0x54e5,0x54e6,0x54e7, + 0x54e8,0x54e9,0x54ea,0x54eb,0x54ec,0x54ed,0x54ee,0x54ef, + 0x54f0,0x54f1,0x54f2,0x54f3,0x54f4,0x54f5,0x54f6,0x54f7, + 0x54f8,0x54f9,0x54fa,0x54fb,0x54fc,0x54fd,0x54fe,0x54ff, + 0x5500,0x5501,0x5502,0x5503,0x5504,0x5505,0x5506,0x5507, + 0x5508,0x5509,0x550a,0x550b,0x550c,0x550d,0x550e,0x550f, + 0x5510,0x5511,0x5512,0x5513,0x5514,0x5515,0x5516,0x5517, + 0x5518,0x5519,0x551a,0x551b,0x551c,0x551d,0x551e,0x551f, + 0x5520,0x5521,0x5522,0x5523,0x5524,0x5525,0x5526,0x5527, + 0x5528,0x5529,0x552a,0x552b,0x552c,0x552d,0x552e,0x552f, + 0x5530,0x5531,0x5532,0x5533,0x5534,0x5535,0x5536,0x5537, + 0x5538,0x5539,0x553a,0x553b,0x553c,0x553d,0x553e,0x553f, + 0x5540,0x5541,0x5542,0x5543,0x5544,0x5545,0x5546,0x5547, + 0x5548,0x5549,0x554a,0x554b,0x554c,0x554d,0x554e,0x554f, + 0x5550,0x5551,0x5552,0x5553,0x5554,0x5555,0x5556,0x5557, + 0x5558,0x5559,0x555a,0x555b,0x555c,0x555d,0x555e,0x555f, + 0x5560,0x5561,0x5562,0x5563,0x5564,0x5565,0x5566,0x5567, + 0x5568,0x5569,0x556a,0x556b,0x556c,0x556d,0x556e,0x556f, + 0x5570,0x5571,0x5572,0x5573,0x5574,0x5575,0x5576,0x5577, + 0x5578,0x5579,0x557a,0x557b,0x557c,0x557d,0x557e,0x557f, + 0x5580,0x5581,0x5582,0x5583,0x5584,0x5585,0x5586,0x5587, + 0x5588,0x5589,0x558a,0x558b,0x558c,0x558d,0x558e,0x558f, + 0x5590,0x5591,0x5592,0x5593,0x5594,0x5595,0x5596,0x5597, + 0x5598,0x5599,0x559a,0x559b,0x559c,0x559d,0x559e,0x559f, + 0x55a0,0x55a1,0x55a2,0x55a3,0x55a4,0x55a5,0x55a6,0x55a7, + 0x55a8,0x55a9,0x55aa,0x55ab,0x55ac,0x55ad,0x55ae,0x55af, + 0x55b0,0x55b1,0x55b2,0x55b3,0x55b4,0x55b5,0x55b6,0x55b7, + 0x55b8,0x55b9,0x55ba,0x55bb,0x55bc,0x55bd,0x55be,0x55bf, + 0x55c0,0x55c1,0x55c2,0x55c3,0x55c4,0x55c5,0x55c6,0x55c7, + 0x55c8,0x55c9,0x55ca,0x55cb,0x55cc,0x55cd,0x55ce,0x55cf, + 0x55d0,0x55d1,0x55d2,0x55d3,0x55d4,0x55d5,0x55d6,0x55d7, + 0x55d8,0x55d9,0x55da,0x55db,0x55dc,0x55dd,0x55de,0x55df, + 0x55e0,0x55e1,0x55e2,0x55e3,0x55e4,0x55e5,0x55e6,0x55e7, + 0x55e8,0x55e9,0x55ea,0x55eb,0x55ec,0x55ed,0x55ee,0x55ef, + 0x55f0,0x55f1,0x55f2,0x55f3,0x55f4,0x55f5,0x55f6,0x55f7, + 0x55f8,0x55f9,0x55fa,0x55fb,0x55fc,0x55fd,0x55fe,0x55ff, + 0x5600,0x5601,0x5602,0x5603,0x5604,0x5605,0x5606,0x5607, + 0x5608,0x5609,0x560a,0x560b,0x560c,0x560d,0x560e,0x560f, + 0x5610,0x5611,0x5612,0x5613,0x5614,0x5615,0x5616,0x5617, + 0x5618,0x5619,0x561a,0x561b,0x561c,0x561d,0x561e,0x561f, + 0x5620,0x5621,0x5622,0x5623,0x5624,0x5625,0x5626,0x5627, + 0x5628,0x5629,0x562a,0x562b,0x562c,0x562d,0x562e,0x562f, + 0x5630,0x5631,0x5632,0x5633,0x5634,0x5635,0x5636,0x5637, + 0x5638,0x5639,0x563a,0x563b,0x563c,0x563d,0x563e,0x563f, + 0x5640,0x5641,0x5642,0x5643,0x5644,0x5645,0x5646,0x5647, + 0x5648,0x5649,0x564a,0x564b,0x564c,0x564d,0x564e,0x564f, + 0x5650,0x5651,0x5652,0x5653,0x5654,0x5655,0x5656,0x5657, + 0x5658,0x5659,0x565a,0x565b,0x565c,0x565d,0x565e,0x565f, + 0x5660,0x5661,0x5662,0x5663,0x5664,0x5665,0x5666,0x5667, + 0x5668,0x5669,0x566a,0x566b,0x566c,0x566d,0x566e,0x566f, + 0x5670,0x5671,0x5672,0x5673,0x5674,0x5675,0x5676,0x5677, + 0x5678,0x5679,0x567a,0x567b,0x567c,0x567d,0x567e,0x567f, + 0x5680,0x5681,0x5682,0x5683,0x5684,0x5685,0x5686,0x5687, + 0x5688,0x5689,0x568a,0x568b,0x568c,0x568d,0x568e,0x568f, + 0x5690,0x5691,0x5692,0x5693,0x5694,0x5695,0x5696,0x5697, + 0x5698,0x5699,0x569a,0x569b,0x569c,0x569d,0x569e,0x569f, + 0x56a0,0x56a1,0x56a2,0x56a3,0x56a4,0x56a5,0x56a6,0x56a7, + 0x56a8,0x56a9,0x56aa,0x56ab,0x56ac,0x56ad,0x56ae,0x56af, + 0x56b0,0x56b1,0x56b2,0x56b3,0x56b4,0x56b5,0x56b6,0x56b7, + 0x56b8,0x56b9,0x56ba,0x56bb,0x56bc,0x56bd,0x56be,0x56bf, + 0x56c0,0x56c1,0x56c2,0x56c3,0x56c4,0x56c5,0x56c6,0x56c7, + 0x56c8,0x56c9,0x56ca,0x56cb,0x56cc,0x56cd,0x56ce,0x56cf, + 0x56d0,0x56d1,0x56d2,0x56d3,0x56d4,0x56d5,0x56d6,0x56d7, + 0x56d8,0x56d9,0x56da,0x56db,0x56dc,0x56dd,0x56de,0x56df, + 0x56e0,0x56e1,0x56e2,0x56e3,0x56e4,0x56e5,0x56e6,0x56e7, + 0x56e8,0x56e9,0x56ea,0x56eb,0x56ec,0x56ed,0x56ee,0x56ef, + 0x56f0,0x56f1,0x56f2,0x56f3,0x56f4,0x56f5,0x56f6,0x56f7, + 0x56f8,0x56f9,0x56fa,0x56fb,0x56fc,0x56fd,0x56fe,0x56ff, + 0x5700,0x5701,0x5702,0x5703,0x5704,0x5705,0x5706,0x5707, + 0x5708,0x5709,0x570a,0x570b,0x570c,0x570d,0x570e,0x570f, + 0x5710,0x5711,0x5712,0x5713,0x5714,0x5715,0x5716,0x5717, + 0x5718,0x5719,0x571a,0x571b,0x571c,0x571d,0x571e,0x571f, + 0x5720,0x5721,0x5722,0x5723,0x5724,0x5725,0x5726,0x5727, + 0x5728,0x5729,0x572a,0x572b,0x572c,0x572d,0x572e,0x572f, + 0x5730,0x5731,0x5732,0x5733,0x5734,0x5735,0x5736,0x5737, + 0x5738,0x5739,0x573a,0x573b,0x573c,0x573d,0x573e,0x573f, + 0x5740,0x5741,0x5742,0x5743,0x5744,0x5745,0x5746,0x5747, + 0x5748,0x5749,0x574a,0x574b,0x574c,0x574d,0x574e,0x574f, + 0x5750,0x5751,0x5752,0x5753,0x5754,0x5755,0x5756,0x5757, + 0x5758,0x5759,0x575a,0x575b,0x575c,0x575d,0x575e,0x575f, + 0x5760,0x5761,0x5762,0x5763,0x5764,0x5765,0x5766,0x5767, + 0x5768,0x5769,0x576a,0x576b,0x576c,0x576d,0x576e,0x576f, + 0x5770,0x5771,0x5772,0x5773,0x5774,0x5775,0x5776,0x5777, + 0x5778,0x5779,0x577a,0x577b,0x577c,0x577d,0x577e,0x577f, + 0x5780,0x5781,0x5782,0x5783,0x5784,0x5785,0x5786,0x5787, + 0x5788,0x5789,0x578a,0x578b,0x578c,0x578d,0x578e,0x578f, + 0x5790,0x5791,0x5792,0x5793,0x5794,0x5795,0x5796,0x5797, + 0x5798,0x5799,0x579a,0x579b,0x579c,0x579d,0x579e,0x579f, + 0x57a0,0x57a1,0x57a2,0x57a3,0x57a4,0x57a5,0x57a6,0x57a7, + 0x57a8,0x57a9,0x57aa,0x57ab,0x57ac,0x57ad,0x57ae,0x57af, + 0x57b0,0x57b1,0x57b2,0x57b3,0x57b4,0x57b5,0x57b6,0x57b7, + 0x57b8,0x57b9,0x57ba,0x57bb,0x57bc,0x57bd,0x57be,0x57bf, + 0x57c0,0x57c1,0x57c2,0x57c3,0x57c4,0x57c5,0x57c6,0x57c7, + 0x57c8,0x57c9,0x57ca,0x57cb,0x57cc,0x57cd,0x57ce,0x57cf, + 0x57d0,0x57d1,0x57d2,0x57d3,0x57d4,0x57d5,0x57d6,0x57d7, + 0x57d8,0x57d9,0x57da,0x57db,0x57dc,0x57dd,0x57de,0x57df, + 0x57e0,0x57e1,0x57e2,0x57e3,0x57e4,0x57e5,0x57e6,0x57e7, + 0x57e8,0x57e9,0x57ea,0x57eb,0x57ec,0x57ed,0x57ee,0x57ef, + 0x57f0,0x57f1,0x57f2,0x57f3,0x57f4,0x57f5,0x57f6,0x57f7, + 0x57f8,0x57f9,0x57fa,0x57fb,0x57fc,0x57fd,0x57fe,0x57ff, + 0x5800,0x5801,0x5802,0x5803,0x5804,0x5805,0x5806,0x5807, + 0x5808,0x5809,0x580a,0x580b,0x580c,0x580d,0x580e,0x580f, + 0x5810,0x5811,0x5812,0x5813,0x5814,0x5815,0x5816,0x5817, + 0x5818,0x5819,0x581a,0x581b,0x581c,0x581d,0x581e,0x581f, + 0x5820,0x5821,0x5822,0x5823,0x5824,0x5825,0x5826,0x5827, + 0x5828,0x5829,0x582a,0x582b,0x582c,0x582d,0x582e,0x582f, + 0x5830,0x5831,0x5832,0x5833,0x5834,0x5835,0x5836,0x5837, + 0x5838,0x5839,0x583a,0x583b,0x583c,0x583d,0x583e,0x583f, + 0x5840,0x5841,0x5842,0x5843,0x5844,0x5845,0x5846,0x5847, + 0x5848,0x5849,0x584a,0x584b,0x584c,0x584d,0x584e,0x584f, + 0x5850,0x5851,0x5852,0x5853,0x5854,0x5855,0x5856,0x5857, + 0x5858,0x5859,0x585a,0x585b,0x585c,0x585d,0x585e,0x585f, + 0x5860,0x5861,0x5862,0x5863,0x5864,0x5865,0x5866,0x5867, + 0x5868,0x5869,0x586a,0x586b,0x586c,0x586d,0x586e,0x586f, + 0x5870,0x5871,0x5872,0x5873,0x5874,0x5875,0x5876,0x5877, + 0x5878,0x5879,0x587a,0x587b,0x587c,0x587d,0x587e,0x587f, + 0x5880,0x5881,0x5882,0x5883,0x5884,0x5885,0x5886,0x5887, + 0x5888,0x5889,0x588a,0x588b,0x588c,0x588d,0x588e,0x588f, + 0x5890,0x5891,0x5892,0x5893,0x5894,0x5895,0x5896,0x5897, + 0x5898,0x5899,0x589a,0x589b,0x589c,0x589d,0x589e,0x589f, + 0x58a0,0x58a1,0x58a2,0x58a3,0x58a4,0x58a5,0x58a6,0x58a7, + 0x58a8,0x58a9,0x58aa,0x58ab,0x58ac,0x58ad,0x58ae,0x58af, + 0x58b0,0x58b1,0x58b2,0x58b3,0x58b4,0x58b5,0x58b6,0x58b7, + 0x58b8,0x58b9,0x58ba,0x58bb,0x58bc,0x58bd,0x58be,0x58bf, + 0x58c0,0x58c1,0x58c2,0x58c3,0x58c4,0x58c5,0x58c6,0x58c7, + 0x58c8,0x58c9,0x58ca,0x58cb,0x58cc,0x58cd,0x58ce,0x58cf, + 0x58d0,0x58d1,0x58d2,0x58d3,0x58d4,0x58d5,0x58d6,0x58d7, + 0x58d8,0x58d9,0x58da,0x58db,0x58dc,0x58dd,0x58de,0x58df, + 0x58e0,0x58e1,0x58e2,0x58e3,0x58e4,0x58e5,0x58e6,0x58e7, + 0x58e8,0x58e9,0x58ea,0x58eb,0x58ec,0x58ed,0x58ee,0x58ef, + 0x58f0,0x58f1,0x58f2,0x58f3,0x58f4,0x58f5,0x58f6,0x58f7, + 0x58f8,0x58f9,0x58fa,0x58fb,0x58fc,0x58fd,0x58fe,0x58ff, + 0x5900,0x5901,0x5902,0x5903,0x5904,0x5905,0x5906,0x5907, + 0x5908,0x5909,0x590a,0x590b,0x590c,0x590d,0x590e,0x590f, + 0x5910,0x5911,0x5912,0x5913,0x5914,0x5915,0x5916,0x5917, + 0x5918,0x5919,0x591a,0x591b,0x591c,0x591d,0x591e,0x591f, + 0x5920,0x5921,0x5922,0x5923,0x5924,0x5925,0x5926,0x5927, + 0x5928,0x5929,0x592a,0x592b,0x592c,0x592d,0x592e,0x592f, + 0x5930,0x5931,0x5932,0x5933,0x5934,0x5935,0x5936,0x5937, + 0x5938,0x5939,0x593a,0x593b,0x593c,0x593d,0x593e,0x593f, + 0x5940,0x5941,0x5942,0x5943,0x5944,0x5945,0x5946,0x5947, + 0x5948,0x5949,0x594a,0x594b,0x594c,0x594d,0x594e,0x594f, + 0x5950,0x5951,0x5952,0x5953,0x5954,0x5955,0x5956,0x5957, + 0x5958,0x5959,0x595a,0x595b,0x595c,0x595d,0x595e,0x595f, + 0x5960,0x5961,0x5962,0x5963,0x5964,0x5965,0x5966,0x5967, + 0x5968,0x5969,0x596a,0x596b,0x596c,0x596d,0x596e,0x596f, + 0x5970,0x5971,0x5972,0x5973,0x5974,0x5975,0x5976,0x5977, + 0x5978,0x5979,0x597a,0x597b,0x597c,0x597d,0x597e,0x597f, + 0x5980,0x5981,0x5982,0x5983,0x5984,0x5985,0x5986,0x5987, + 0x5988,0x5989,0x598a,0x598b,0x598c,0x598d,0x598e,0x598f, + 0x5990,0x5991,0x5992,0x5993,0x5994,0x5995,0x5996,0x5997, + 0x5998,0x5999,0x599a,0x599b,0x599c,0x599d,0x599e,0x599f, + 0x59a0,0x59a1,0x59a2,0x59a3,0x59a4,0x59a5,0x59a6,0x59a7, + 0x59a8,0x59a9,0x59aa,0x59ab,0x59ac,0x59ad,0x59ae,0x59af, + 0x59b0,0x59b1,0x59b2,0x59b3,0x59b4,0x59b5,0x59b6,0x59b7, + 0x59b8,0x59b9,0x59ba,0x59bb,0x59bc,0x59bd,0x59be,0x59bf, + 0x59c0,0x59c1,0x59c2,0x59c3,0x59c4,0x59c5,0x59c6,0x59c7, + 0x59c8,0x59c9,0x59ca,0x59cb,0x59cc,0x59cd,0x59ce,0x59cf, + 0x59d0,0x59d1,0x59d2,0x59d3,0x59d4,0x59d5,0x59d6,0x59d7, + 0x59d8,0x59d9,0x59da,0x59db,0x59dc,0x59dd,0x59de,0x59df, + 0x59e0,0x59e1,0x59e2,0x59e3,0x59e4,0x59e5,0x59e6,0x59e7, + 0x59e8,0x59e9,0x59ea,0x59eb,0x59ec,0x59ed,0x59ee,0x59ef, + 0x59f0,0x59f1,0x59f2,0x59f3,0x59f4,0x59f5,0x59f6,0x59f7, + 0x59f8,0x59f9,0x59fa,0x59fb,0x59fc,0x59fd,0x59fe,0x59ff, + 0x5a00,0x5a01,0x5a02,0x5a03,0x5a04,0x5a05,0x5a06,0x5a07, + 0x5a08,0x5a09,0x5a0a,0x5a0b,0x5a0c,0x5a0d,0x5a0e,0x5a0f, + 0x5a10,0x5a11,0x5a12,0x5a13,0x5a14,0x5a15,0x5a16,0x5a17, + 0x5a18,0x5a19,0x5a1a,0x5a1b,0x5a1c,0x5a1d,0x5a1e,0x5a1f, + 0x5a20,0x5a21,0x5a22,0x5a23,0x5a24,0x5a25,0x5a26,0x5a27, + 0x5a28,0x5a29,0x5a2a,0x5a2b,0x5a2c,0x5a2d,0x5a2e,0x5a2f, + 0x5a30,0x5a31,0x5a32,0x5a33,0x5a34,0x5a35,0x5a36,0x5a37, + 0x5a38,0x5a39,0x5a3a,0x5a3b,0x5a3c,0x5a3d,0x5a3e,0x5a3f, + 0x5a40,0x5a41,0x5a42,0x5a43,0x5a44,0x5a45,0x5a46,0x5a47, + 0x5a48,0x5a49,0x5a4a,0x5a4b,0x5a4c,0x5a4d,0x5a4e,0x5a4f, + 0x5a50,0x5a51,0x5a52,0x5a53,0x5a54,0x5a55,0x5a56,0x5a57, + 0x5a58,0x5a59,0x5a5a,0x5a5b,0x5a5c,0x5a5d,0x5a5e,0x5a5f, + 0x5a60,0x5a61,0x5a62,0x5a63,0x5a64,0x5a65,0x5a66,0x5a67, + 0x5a68,0x5a69,0x5a6a,0x5a6b,0x5a6c,0x5a6d,0x5a6e,0x5a6f, + 0x5a70,0x5a71,0x5a72,0x5a73,0x5a74,0x5a75,0x5a76,0x5a77, + 0x5a78,0x5a79,0x5a7a,0x5a7b,0x5a7c,0x5a7d,0x5a7e,0x5a7f, + 0x5a80,0x5a81,0x5a82,0x5a83,0x5a84,0x5a85,0x5a86,0x5a87, + 0x5a88,0x5a89,0x5a8a,0x5a8b,0x5a8c,0x5a8d,0x5a8e,0x5a8f, + 0x5a90,0x5a91,0x5a92,0x5a93,0x5a94,0x5a95,0x5a96,0x5a97, + 0x5a98,0x5a99,0x5a9a,0x5a9b,0x5a9c,0x5a9d,0x5a9e,0x5a9f, + 0x5aa0,0x5aa1,0x5aa2,0x5aa3,0x5aa4,0x5aa5,0x5aa6,0x5aa7, + 0x5aa8,0x5aa9,0x5aaa,0x5aab,0x5aac,0x5aad,0x5aae,0x5aaf, + 0x5ab0,0x5ab1,0x5ab2,0x5ab3,0x5ab4,0x5ab5,0x5ab6,0x5ab7, + 0x5ab8,0x5ab9,0x5aba,0x5abb,0x5abc,0x5abd,0x5abe,0x5abf, + 0x5ac0,0x5ac1,0x5ac2,0x5ac3,0x5ac4,0x5ac5,0x5ac6,0x5ac7, + 0x5ac8,0x5ac9,0x5aca,0x5acb,0x5acc,0x5acd,0x5ace,0x5acf, + 0x5ad0,0x5ad1,0x5ad2,0x5ad3,0x5ad4,0x5ad5,0x5ad6,0x5ad7, + 0x5ad8,0x5ad9,0x5ada,0x5adb,0x5adc,0x5add,0x5ade,0x5adf, + 0x5ae0,0x5ae1,0x5ae2,0x5ae3,0x5ae4,0x5ae5,0x5ae6,0x5ae7, + 0x5ae8,0x5ae9,0x5aea,0x5aeb,0x5aec,0x5aed,0x5aee,0x5aef, + 0x5af0,0x5af1,0x5af2,0x5af3,0x5af4,0x5af5,0x5af6,0x5af7, + 0x5af8,0x5af9,0x5afa,0x5afb,0x5afc,0x5afd,0x5afe,0x5aff, + 0x5b00,0x5b01,0x5b02,0x5b03,0x5b04,0x5b05,0x5b06,0x5b07, + 0x5b08,0x5b09,0x5b0a,0x5b0b,0x5b0c,0x5b0d,0x5b0e,0x5b0f, + 0x5b10,0x5b11,0x5b12,0x5b13,0x5b14,0x5b15,0x5b16,0x5b17, + 0x5b18,0x5b19,0x5b1a,0x5b1b,0x5b1c,0x5b1d,0x5b1e,0x5b1f, + 0x5b20,0x5b21,0x5b22,0x5b23,0x5b24,0x5b25,0x5b26,0x5b27, + 0x5b28,0x5b29,0x5b2a,0x5b2b,0x5b2c,0x5b2d,0x5b2e,0x5b2f, + 0x5b30,0x5b31,0x5b32,0x5b33,0x5b34,0x5b35,0x5b36,0x5b37, + 0x5b38,0x5b39,0x5b3a,0x5b3b,0x5b3c,0x5b3d,0x5b3e,0x5b3f, + 0x5b40,0x5b41,0x5b42,0x5b43,0x5b44,0x5b45,0x5b46,0x5b47, + 0x5b48,0x5b49,0x5b4a,0x5b4b,0x5b4c,0x5b4d,0x5b4e,0x5b4f, + 0x5b50,0x5b51,0x5b52,0x5b53,0x5b54,0x5b55,0x5b56,0x5b57, + 0x5b58,0x5b59,0x5b5a,0x5b5b,0x5b5c,0x5b5d,0x5b5e,0x5b5f, + 0x5b60,0x5b61,0x5b62,0x5b63,0x5b64,0x5b65,0x5b66,0x5b67, + 0x5b68,0x5b69,0x5b6a,0x5b6b,0x5b6c,0x5b6d,0x5b6e,0x5b6f, + 0x5b70,0x5b71,0x5b72,0x5b73,0x5b74,0x5b75,0x5b76,0x5b77, + 0x5b78,0x5b79,0x5b7a,0x5b7b,0x5b7c,0x5b7d,0x5b7e,0x5b7f, + 0x5b80,0x5b81,0x5b82,0x5b83,0x5b84,0x5b85,0x5b86,0x5b87, + 0x5b88,0x5b89,0x5b8a,0x5b8b,0x5b8c,0x5b8d,0x5b8e,0x5b8f, + 0x5b90,0x5b91,0x5b92,0x5b93,0x5b94,0x5b95,0x5b96,0x5b97, + 0x5b98,0x5b99,0x5b9a,0x5b9b,0x5b9c,0x5b9d,0x5b9e,0x5b9f, + 0x5ba0,0x5ba1,0x5ba2,0x5ba3,0x5ba4,0x5ba5,0x5ba6,0x5ba7, + 0x5ba8,0x5ba9,0x5baa,0x5bab,0x5bac,0x5bad,0x5bae,0x5baf, + 0x5bb0,0x5bb1,0x5bb2,0x5bb3,0x5bb4,0x5bb5,0x5bb6,0x5bb7, + 0x5bb8,0x5bb9,0x5bba,0x5bbb,0x5bbc,0x5bbd,0x5bbe,0x5bbf, + 0x5bc0,0x5bc1,0x5bc2,0x5bc3,0x5bc4,0x5bc5,0x5bc6,0x5bc7, + 0x5bc8,0x5bc9,0x5bca,0x5bcb,0x5bcc,0x5bcd,0x5bce,0x5bcf, + 0x5bd0,0x5bd1,0x5bd2,0x5bd3,0x5bd4,0x5bd5,0x5bd6,0x5bd7, + 0x5bd8,0x5bd9,0x5bda,0x5bdb,0x5bdc,0x5bdd,0x5bde,0x5bdf, + 0x5be0,0x5be1,0x5be2,0x5be3,0x5be4,0x5be5,0x5be6,0x5be7, + 0x5be8,0x5be9,0x5bea,0x5beb,0x5bec,0x5bed,0x5bee,0x5bef, + 0x5bf0,0x5bf1,0x5bf2,0x5bf3,0x5bf4,0x5bf5,0x5bf6,0x5bf7, + 0x5bf8,0x5bf9,0x5bfa,0x5bfb,0x5bfc,0x5bfd,0x5bfe,0x5bff, + 0x5c00,0x5c01,0x5c02,0x5c03,0x5c04,0x5c05,0x5c06,0x5c07, + 0x5c08,0x5c09,0x5c0a,0x5c0b,0x5c0c,0x5c0d,0x5c0e,0x5c0f, + 0x5c10,0x5c11,0x5c12,0x5c13,0x5c14,0x5c15,0x5c16,0x5c17, + 0x5c18,0x5c19,0x5c1a,0x5c1b,0x5c1c,0x5c1d,0x5c1e,0x5c1f, + 0x5c20,0x5c21,0x5c22,0x5c23,0x5c24,0x5c25,0x5c26,0x5c27, + 0x5c28,0x5c29,0x5c2a,0x5c2b,0x5c2c,0x5c2d,0x5c2e,0x5c2f, + 0x5c30,0x5c31,0x5c32,0x5c33,0x5c34,0x5c35,0x5c36,0x5c37, + 0x5c38,0x5c39,0x5c3a,0x5c3b,0x5c3c,0x5c3d,0x5c3e,0x5c3f, + 0x5c40,0x5c41,0x5c42,0x5c43,0x5c44,0x5c45,0x5c46,0x5c47, + 0x5c48,0x5c49,0x5c4a,0x5c4b,0x5c4c,0x5c4d,0x5c4e,0x5c4f, + 0x5c50,0x5c51,0x5c52,0x5c53,0x5c54,0x5c55,0x5c56,0x5c57, + 0x5c58,0x5c59,0x5c5a,0x5c5b,0x5c5c,0x5c5d,0x5c5e,0x5c5f, + 0x5c60,0x5c61,0x5c62,0x5c63,0x5c64,0x5c65,0x5c66,0x5c67, + 0x5c68,0x5c69,0x5c6a,0x5c6b,0x5c6c,0x5c6d,0x5c6e,0x5c6f, + 0x5c70,0x5c71,0x5c72,0x5c73,0x5c74,0x5c75,0x5c76,0x5c77, + 0x5c78,0x5c79,0x5c7a,0x5c7b,0x5c7c,0x5c7d,0x5c7e,0x5c7f, + 0x5c80,0x5c81,0x5c82,0x5c83,0x5c84,0x5c85,0x5c86,0x5c87, + 0x5c88,0x5c89,0x5c8a,0x5c8b,0x5c8c,0x5c8d,0x5c8e,0x5c8f, + 0x5c90,0x5c91,0x5c92,0x5c93,0x5c94,0x5c95,0x5c96,0x5c97, + 0x5c98,0x5c99,0x5c9a,0x5c9b,0x5c9c,0x5c9d,0x5c9e,0x5c9f, + 0x5ca0,0x5ca1,0x5ca2,0x5ca3,0x5ca4,0x5ca5,0x5ca6,0x5ca7, + 0x5ca8,0x5ca9,0x5caa,0x5cab,0x5cac,0x5cad,0x5cae,0x5caf, + 0x5cb0,0x5cb1,0x5cb2,0x5cb3,0x5cb4,0x5cb5,0x5cb6,0x5cb7, + 0x5cb8,0x5cb9,0x5cba,0x5cbb,0x5cbc,0x5cbd,0x5cbe,0x5cbf, + 0x5cc0,0x5cc1,0x5cc2,0x5cc3,0x5cc4,0x5cc5,0x5cc6,0x5cc7, + 0x5cc8,0x5cc9,0x5cca,0x5ccb,0x5ccc,0x5ccd,0x5cce,0x5ccf, + 0x5cd0,0x5cd1,0x5cd2,0x5cd3,0x5cd4,0x5cd5,0x5cd6,0x5cd7, + 0x5cd8,0x5cd9,0x5cda,0x5cdb,0x5cdc,0x5cdd,0x5cde,0x5cdf, + 0x5ce0,0x5ce1,0x5ce2,0x5ce3,0x5ce4,0x5ce5,0x5ce6,0x5ce7, + 0x5ce8,0x5ce9,0x5cea,0x5ceb,0x5cec,0x5ced,0x5cee,0x5cef, + 0x5cf0,0x5cf1,0x5cf2,0x5cf3,0x5cf4,0x5cf5,0x5cf6,0x5cf7, + 0x5cf8,0x5cf9,0x5cfa,0x5cfb,0x5cfc,0x5cfd,0x5cfe,0x5cff, + 0x5d00,0x5d01,0x5d02,0x5d03,0x5d04,0x5d05,0x5d06,0x5d07, + 0x5d08,0x5d09,0x5d0a,0x5d0b,0x5d0c,0x5d0d,0x5d0e,0x5d0f, + 0x5d10,0x5d11,0x5d12,0x5d13,0x5d14,0x5d15,0x5d16,0x5d17, + 0x5d18,0x5d19,0x5d1a,0x5d1b,0x5d1c,0x5d1d,0x5d1e,0x5d1f, + 0x5d20,0x5d21,0x5d22,0x5d23,0x5d24,0x5d25,0x5d26,0x5d27, + 0x5d28,0x5d29,0x5d2a,0x5d2b,0x5d2c,0x5d2d,0x5d2e,0x5d2f, + 0x5d30,0x5d31,0x5d32,0x5d33,0x5d34,0x5d35,0x5d36,0x5d37, + 0x5d38,0x5d39,0x5d3a,0x5d3b,0x5d3c,0x5d3d,0x5d3e,0x5d3f, + 0x5d40,0x5d41,0x5d42,0x5d43,0x5d44,0x5d45,0x5d46,0x5d47, + 0x5d48,0x5d49,0x5d4a,0x5d4b,0x5d4c,0x5d4d,0x5d4e,0x5d4f, + 0x5d50,0x5d51,0x5d52,0x5d53,0x5d54,0x5d55,0x5d56,0x5d57, + 0x5d58,0x5d59,0x5d5a,0x5d5b,0x5d5c,0x5d5d,0x5d5e,0x5d5f, + 0x5d60,0x5d61,0x5d62,0x5d63,0x5d64,0x5d65,0x5d66,0x5d67, + 0x5d68,0x5d69,0x5d6a,0x5d6b,0x5d6c,0x5d6d,0x5d6e,0x5d6f, + 0x5d70,0x5d71,0x5d72,0x5d73,0x5d74,0x5d75,0x5d76,0x5d77, + 0x5d78,0x5d79,0x5d7a,0x5d7b,0x5d7c,0x5d7d,0x5d7e,0x5d7f, + 0x5d80,0x5d81,0x5d82,0x5d83,0x5d84,0x5d85,0x5d86,0x5d87, + 0x5d88,0x5d89,0x5d8a,0x5d8b,0x5d8c,0x5d8d,0x5d8e,0x5d8f, + 0x5d90,0x5d91,0x5d92,0x5d93,0x5d94,0x5d95,0x5d96,0x5d97, + 0x5d98,0x5d99,0x5d9a,0x5d9b,0x5d9c,0x5d9d,0x5d9e,0x5d9f, + 0x5da0,0x5da1,0x5da2,0x5da3,0x5da4,0x5da5,0x5da6,0x5da7, + 0x5da8,0x5da9,0x5daa,0x5dab,0x5dac,0x5dad,0x5dae,0x5daf, + 0x5db0,0x5db1,0x5db2,0x5db3,0x5db4,0x5db5,0x5db6,0x5db7, + 0x5db8,0x5db9,0x5dba,0x5dbb,0x5dbc,0x5dbd,0x5dbe,0x5dbf, + 0x5dc0,0x5dc1,0x5dc2,0x5dc3,0x5dc4,0x5dc5,0x5dc6,0x5dc7, + 0x5dc8,0x5dc9,0x5dca,0x5dcb,0x5dcc,0x5dcd,0x5dce,0x5dcf, + 0x5dd0,0x5dd1,0x5dd2,0x5dd3,0x5dd4,0x5dd5,0x5dd6,0x5dd7, + 0x5dd8,0x5dd9,0x5dda,0x5ddb,0x5ddc,0x5ddd,0x5dde,0x5ddf, + 0x5de0,0x5de1,0x5de2,0x5de3,0x5de4,0x5de5,0x5de6,0x5de7, + 0x5de8,0x5de9,0x5dea,0x5deb,0x5dec,0x5ded,0x5dee,0x5def, + 0x5df0,0x5df1,0x5df2,0x5df3,0x5df4,0x5df5,0x5df6,0x5df7, + 0x5df8,0x5df9,0x5dfa,0x5dfb,0x5dfc,0x5dfd,0x5dfe,0x5dff, + 0x5e00,0x5e01,0x5e02,0x5e03,0x5e04,0x5e05,0x5e06,0x5e07, + 0x5e08,0x5e09,0x5e0a,0x5e0b,0x5e0c,0x5e0d,0x5e0e,0x5e0f, + 0x5e10,0x5e11,0x5e12,0x5e13,0x5e14,0x5e15,0x5e16,0x5e17, + 0x5e18,0x5e19,0x5e1a,0x5e1b,0x5e1c,0x5e1d,0x5e1e,0x5e1f, + 0x5e20,0x5e21,0x5e22,0x5e23,0x5e24,0x5e25,0x5e26,0x5e27, + 0x5e28,0x5e29,0x5e2a,0x5e2b,0x5e2c,0x5e2d,0x5e2e,0x5e2f, + 0x5e30,0x5e31,0x5e32,0x5e33,0x5e34,0x5e35,0x5e36,0x5e37, + 0x5e38,0x5e39,0x5e3a,0x5e3b,0x5e3c,0x5e3d,0x5e3e,0x5e3f, + 0x5e40,0x5e41,0x5e42,0x5e43,0x5e44,0x5e45,0x5e46,0x5e47, + 0x5e48,0x5e49,0x5e4a,0x5e4b,0x5e4c,0x5e4d,0x5e4e,0x5e4f, + 0x5e50,0x5e51,0x5e52,0x5e53,0x5e54,0x5e55,0x5e56,0x5e57, + 0x5e58,0x5e59,0x5e5a,0x5e5b,0x5e5c,0x5e5d,0x5e5e,0x5e5f, + 0x5e60,0x5e61,0x5e62,0x5e63,0x5e64,0x5e65,0x5e66,0x5e67, + 0x5e68,0x5e69,0x5e6a,0x5e6b,0x5e6c,0x5e6d,0x5e6e,0x5e6f, + 0x5e70,0x5e71,0x5e72,0x5e73,0x5e74,0x5e75,0x5e76,0x5e77, + 0x5e78,0x5e79,0x5e7a,0x5e7b,0x5e7c,0x5e7d,0x5e7e,0x5e7f, + 0x5e80,0x5e81,0x5e82,0x5e83,0x5e84,0x5e85,0x5e86,0x5e87, + 0x5e88,0x5e89,0x5e8a,0x5e8b,0x5e8c,0x5e8d,0x5e8e,0x5e8f, + 0x5e90,0x5e91,0x5e92,0x5e93,0x5e94,0x5e95,0x5e96,0x5e97, + 0x5e98,0x5e99,0x5e9a,0x5e9b,0x5e9c,0x5e9d,0x5e9e,0x5e9f, + 0x5ea0,0x5ea1,0x5ea2,0x5ea3,0x5ea4,0x5ea5,0x5ea6,0x5ea7, + 0x5ea8,0x5ea9,0x5eaa,0x5eab,0x5eac,0x5ead,0x5eae,0x5eaf, + 0x5eb0,0x5eb1,0x5eb2,0x5eb3,0x5eb4,0x5eb5,0x5eb6,0x5eb7, + 0x5eb8,0x5eb9,0x5eba,0x5ebb,0x5ebc,0x5ebd,0x5ebe,0x5ebf, + 0x5ec0,0x5ec1,0x5ec2,0x5ec3,0x5ec4,0x5ec5,0x5ec6,0x5ec7, + 0x5ec8,0x5ec9,0x5eca,0x5ecb,0x5ecc,0x5ecd,0x5ece,0x5ecf, + 0x5ed0,0x5ed1,0x5ed2,0x5ed3,0x5ed4,0x5ed5,0x5ed6,0x5ed7, + 0x5ed8,0x5ed9,0x5eda,0x5edb,0x5edc,0x5edd,0x5ede,0x5edf, + 0x5ee0,0x5ee1,0x5ee2,0x5ee3,0x5ee4,0x5ee5,0x5ee6,0x5ee7, + 0x5ee8,0x5ee9,0x5eea,0x5eeb,0x5eec,0x5eed,0x5eee,0x5eef, + 0x5ef0,0x5ef1,0x5ef2,0x5ef3,0x5ef4,0x5ef5,0x5ef6,0x5ef7, + 0x5ef8,0x5ef9,0x5efa,0x5efb,0x5efc,0x5efd,0x5efe,0x5eff, + 0x5f00,0x5f01,0x5f02,0x5f03,0x5f04,0x5f05,0x5f06,0x5f07, + 0x5f08,0x5f09,0x5f0a,0x5f0b,0x5f0c,0x5f0d,0x5f0e,0x5f0f, + 0x5f10,0x5f11,0x5f12,0x5f13,0x5f14,0x5f15,0x5f16,0x5f17, + 0x5f18,0x5f19,0x5f1a,0x5f1b,0x5f1c,0x5f1d,0x5f1e,0x5f1f, + 0x5f20,0x5f21,0x5f22,0x5f23,0x5f24,0x5f25,0x5f26,0x5f27, + 0x5f28,0x5f29,0x5f2a,0x5f2b,0x5f2c,0x5f2d,0x5f2e,0x5f2f, + 0x5f30,0x5f31,0x5f32,0x5f33,0x5f34,0x5f35,0x5f36,0x5f37, + 0x5f38,0x5f39,0x5f3a,0x5f3b,0x5f3c,0x5f3d,0x5f3e,0x5f3f, + 0x5f40,0x5f41,0x5f42,0x5f43,0x5f44,0x5f45,0x5f46,0x5f47, + 0x5f48,0x5f49,0x5f4a,0x5f4b,0x5f4c,0x5f4d,0x5f4e,0x5f4f, + 0x5f50,0x5f51,0x5f52,0x5f53,0x5f54,0x5f55,0x5f56,0x5f57, + 0x5f58,0x5f59,0x5f5a,0x5f5b,0x5f5c,0x5f5d,0x5f5e,0x5f5f, + 0x5f60,0x5f61,0x5f62,0x5f63,0x5f64,0x5f65,0x5f66,0x5f67, + 0x5f68,0x5f69,0x5f6a,0x5f6b,0x5f6c,0x5f6d,0x5f6e,0x5f6f, + 0x5f70,0x5f71,0x5f72,0x5f73,0x5f74,0x5f75,0x5f76,0x5f77, + 0x5f78,0x5f79,0x5f7a,0x5f7b,0x5f7c,0x5f7d,0x5f7e,0x5f7f, + 0x5f80,0x5f81,0x5f82,0x5f83,0x5f84,0x5f85,0x5f86,0x5f87, + 0x5f88,0x5f89,0x5f8a,0x5f8b,0x5f8c,0x5f8d,0x5f8e,0x5f8f, + 0x5f90,0x5f91,0x5f92,0x5f93,0x5f94,0x5f95,0x5f96,0x5f97, + 0x5f98,0x5f99,0x5f9a,0x5f9b,0x5f9c,0x5f9d,0x5f9e,0x5f9f, + 0x5fa0,0x5fa1,0x5fa2,0x5fa3,0x5fa4,0x5fa5,0x5fa6,0x5fa7, + 0x5fa8,0x5fa9,0x5faa,0x5fab,0x5fac,0x5fad,0x5fae,0x5faf, + 0x5fb0,0x5fb1,0x5fb2,0x5fb3,0x5fb4,0x5fb5,0x5fb6,0x5fb7, + 0x5fb8,0x5fb9,0x5fba,0x5fbb,0x5fbc,0x5fbd,0x5fbe,0x5fbf, + 0x5fc0,0x5fc1,0x5fc2,0x5fc3,0x5fc4,0x5fc5,0x5fc6,0x5fc7, + 0x5fc8,0x5fc9,0x5fca,0x5fcb,0x5fcc,0x5fcd,0x5fce,0x5fcf, + 0x5fd0,0x5fd1,0x5fd2,0x5fd3,0x5fd4,0x5fd5,0x5fd6,0x5fd7, + 0x5fd8,0x5fd9,0x5fda,0x5fdb,0x5fdc,0x5fdd,0x5fde,0x5fdf, + 0x5fe0,0x5fe1,0x5fe2,0x5fe3,0x5fe4,0x5fe5,0x5fe6,0x5fe7, + 0x5fe8,0x5fe9,0x5fea,0x5feb,0x5fec,0x5fed,0x5fee,0x5fef, + 0x5ff0,0x5ff1,0x5ff2,0x5ff3,0x5ff4,0x5ff5,0x5ff6,0x5ff7, + 0x5ff8,0x5ff9,0x5ffa,0x5ffb,0x5ffc,0x5ffd,0x5ffe,0x5fff, + 0x6000,0x6001,0x6002,0x6003,0x6004,0x6005,0x6006,0x6007, + 0x6008,0x6009,0x600a,0x600b,0x600c,0x600d,0x600e,0x600f, + 0x6010,0x6011,0x6012,0x6013,0x6014,0x6015,0x6016,0x6017, + 0x6018,0x6019,0x601a,0x601b,0x601c,0x601d,0x601e,0x601f, + 0x6020,0x6021,0x6022,0x6023,0x6024,0x6025,0x6026,0x6027, + 0x6028,0x6029,0x602a,0x602b,0x602c,0x602d,0x602e,0x602f, + 0x6030,0x6031,0x6032,0x6033,0x6034,0x6035,0x6036,0x6037, + 0x6038,0x6039,0x603a,0x603b,0x603c,0x603d,0x603e,0x603f, + 0x6040,0x6041,0x6042,0x6043,0x6044,0x6045,0x6046,0x6047, + 0x6048,0x6049,0x604a,0x604b,0x604c,0x604d,0x604e,0x604f, + 0x6050,0x6051,0x6052,0x6053,0x6054,0x6055,0x6056,0x6057, + 0x6058,0x6059,0x605a,0x605b,0x605c,0x605d,0x605e,0x605f, + 0x6060,0x6061,0x6062,0x6063,0x6064,0x6065,0x6066,0x6067, + 0x6068,0x6069,0x606a,0x606b,0x606c,0x606d,0x606e,0x606f, + 0x6070,0x6071,0x6072,0x6073,0x6074,0x6075,0x6076,0x6077, + 0x6078,0x6079,0x607a,0x607b,0x607c,0x607d,0x607e,0x607f, + 0x6080,0x6081,0x6082,0x6083,0x6084,0x6085,0x6086,0x6087, + 0x6088,0x6089,0x608a,0x608b,0x608c,0x608d,0x608e,0x608f, + 0x6090,0x6091,0x6092,0x6093,0x6094,0x6095,0x6096,0x6097, + 0x6098,0x6099,0x609a,0x609b,0x609c,0x609d,0x609e,0x609f, + 0x60a0,0x60a1,0x60a2,0x60a3,0x60a4,0x60a5,0x60a6,0x60a7, + 0x60a8,0x60a9,0x60aa,0x60ab,0x60ac,0x60ad,0x60ae,0x60af, + 0x60b0,0x60b1,0x60b2,0x60b3,0x60b4,0x60b5,0x60b6,0x60b7, + 0x60b8,0x60b9,0x60ba,0x60bb,0x60bc,0x60bd,0x60be,0x60bf, + 0x60c0,0x60c1,0x60c2,0x60c3,0x60c4,0x60c5,0x60c6,0x60c7, + 0x60c8,0x60c9,0x60ca,0x60cb,0x60cc,0x60cd,0x60ce,0x60cf, + 0x60d0,0x60d1,0x60d2,0x60d3,0x60d4,0x60d5,0x60d6,0x60d7, + 0x60d8,0x60d9,0x60da,0x60db,0x60dc,0x60dd,0x60de,0x60df, + 0x60e0,0x60e1,0x60e2,0x60e3,0x60e4,0x60e5,0x60e6,0x60e7, + 0x60e8,0x60e9,0x60ea,0x60eb,0x60ec,0x60ed,0x60ee,0x60ef, + 0x60f0,0x60f1,0x60f2,0x60f3,0x60f4,0x60f5,0x60f6,0x60f7, + 0x60f8,0x60f9,0x60fa,0x60fb,0x60fc,0x60fd,0x60fe,0x60ff, + 0x6100,0x6101,0x6102,0x6103,0x6104,0x6105,0x6106,0x6107, + 0x6108,0x6109,0x610a,0x610b,0x610c,0x610d,0x610e,0x610f, + 0x6110,0x6111,0x6112,0x6113,0x6114,0x6115,0x6116,0x6117, + 0x6118,0x6119,0x611a,0x611b,0x611c,0x611d,0x611e,0x611f, + 0x6120,0x6121,0x6122,0x6123,0x6124,0x6125,0x6126,0x6127, + 0x6128,0x6129,0x612a,0x612b,0x612c,0x612d,0x612e,0x612f, + 0x6130,0x6131,0x6132,0x6133,0x6134,0x6135,0x6136,0x6137, + 0x6138,0x6139,0x613a,0x613b,0x613c,0x613d,0x613e,0x613f, + 0x6140,0x6141,0x6142,0x6143,0x6144,0x6145,0x6146,0x6147, + 0x6148,0x6149,0x614a,0x614b,0x614c,0x614d,0x614e,0x614f, + 0x6150,0x6151,0x6152,0x6153,0x6154,0x6155,0x6156,0x6157, + 0x6158,0x6159,0x615a,0x615b,0x615c,0x615d,0x615e,0x615f, + 0x6160,0x6161,0x6162,0x6163,0x6164,0x6165,0x6166,0x6167, + 0x6168,0x6169,0x616a,0x616b,0x616c,0x616d,0x616e,0x616f, + 0x6170,0x6171,0x6172,0x6173,0x6174,0x6175,0x6176,0x6177, + 0x6178,0x6179,0x617a,0x617b,0x617c,0x617d,0x617e,0x617f, + 0x6180,0x6181,0x6182,0x6183,0x6184,0x6185,0x6186,0x6187, + 0x6188,0x6189,0x618a,0x618b,0x618c,0x618d,0x618e,0x618f, + 0x6190,0x6191,0x6192,0x6193,0x6194,0x6195,0x6196,0x6197, + 0x6198,0x6199,0x619a,0x619b,0x619c,0x619d,0x619e,0x619f, + 0x61a0,0x61a1,0x61a2,0x61a3,0x61a4,0x61a5,0x61a6,0x61a7, + 0x61a8,0x61a9,0x61aa,0x61ab,0x61ac,0x61ad,0x61ae,0x61af, + 0x61b0,0x61b1,0x61b2,0x61b3,0x61b4,0x61b5,0x61b6,0x61b7, + 0x61b8,0x61b9,0x61ba,0x61bb,0x61bc,0x61bd,0x61be,0x61bf, + 0x61c0,0x61c1,0x61c2,0x61c3,0x61c4,0x61c5,0x61c6,0x61c7, + 0x61c8,0x61c9,0x61ca,0x61cb,0x61cc,0x61cd,0x61ce,0x61cf, + 0x61d0,0x61d1,0x61d2,0x61d3,0x61d4,0x61d5,0x61d6,0x61d7, + 0x61d8,0x61d9,0x61da,0x61db,0x61dc,0x61dd,0x61de,0x61df, + 0x61e0,0x61e1,0x61e2,0x61e3,0x61e4,0x61e5,0x61e6,0x61e7, + 0x61e8,0x61e9,0x61ea,0x61eb,0x61ec,0x61ed,0x61ee,0x61ef, + 0x61f0,0x61f1,0x61f2,0x61f3,0x61f4,0x61f5,0x61f6,0x61f7, + 0x61f8,0x61f9,0x61fa,0x61fb,0x61fc,0x61fd,0x61fe,0x61ff, + 0x6200,0x6201,0x6202,0x6203,0x6204,0x6205,0x6206,0x6207, + 0x6208,0x6209,0x620a,0x620b,0x620c,0x620d,0x620e,0x620f, + 0x6210,0x6211,0x6212,0x6213,0x6214,0x6215,0x6216,0x6217, + 0x6218,0x6219,0x621a,0x621b,0x621c,0x621d,0x621e,0x621f, + 0x6220,0x6221,0x6222,0x6223,0x6224,0x6225,0x6226,0x6227, + 0x6228,0x6229,0x622a,0x622b,0x622c,0x622d,0x622e,0x622f, + 0x6230,0x6231,0x6232,0x6233,0x6234,0x6235,0x6236,0x6237, + 0x6238,0x6239,0x623a,0x623b,0x623c,0x623d,0x623e,0x623f, + 0x6240,0x6241,0x6242,0x6243,0x6244,0x6245,0x6246,0x6247, + 0x6248,0x6249,0x624a,0x624b,0x624c,0x624d,0x624e,0x624f, + 0x6250,0x6251,0x6252,0x6253,0x6254,0x6255,0x6256,0x6257, + 0x6258,0x6259,0x625a,0x625b,0x625c,0x625d,0x625e,0x625f, + 0x6260,0x6261,0x6262,0x6263,0x6264,0x6265,0x6266,0x6267, + 0x6268,0x6269,0x626a,0x626b,0x626c,0x626d,0x626e,0x626f, + 0x6270,0x6271,0x6272,0x6273,0x6274,0x6275,0x6276,0x6277, + 0x6278,0x6279,0x627a,0x627b,0x627c,0x627d,0x627e,0x627f, + 0x6280,0x6281,0x6282,0x6283,0x6284,0x6285,0x6286,0x6287, + 0x6288,0x6289,0x628a,0x628b,0x628c,0x628d,0x628e,0x628f, + 0x6290,0x6291,0x6292,0x6293,0x6294,0x6295,0x6296,0x6297, + 0x6298,0x6299,0x629a,0x629b,0x629c,0x629d,0x629e,0x629f, + 0x62a0,0x62a1,0x62a2,0x62a3,0x62a4,0x62a5,0x62a6,0x62a7, + 0x62a8,0x62a9,0x62aa,0x62ab,0x62ac,0x62ad,0x62ae,0x62af, + 0x62b0,0x62b1,0x62b2,0x62b3,0x62b4,0x62b5,0x62b6,0x62b7, + 0x62b8,0x62b9,0x62ba,0x62bb,0x62bc,0x62bd,0x62be,0x62bf, + 0x62c0,0x62c1,0x62c2,0x62c3,0x62c4,0x62c5,0x62c6,0x62c7, + 0x62c8,0x62c9,0x62ca,0x62cb,0x62cc,0x62cd,0x62ce,0x62cf, + 0x62d0,0x62d1,0x62d2,0x62d3,0x62d4,0x62d5,0x62d6,0x62d7, + 0x62d8,0x62d9,0x62da,0x62db,0x62dc,0x62dd,0x62de,0x62df, + 0x62e0,0x62e1,0x62e2,0x62e3,0x62e4,0x62e5,0x62e6,0x62e7, + 0x62e8,0x62e9,0x62ea,0x62eb,0x62ec,0x62ed,0x62ee,0x62ef, + 0x62f0,0x62f1,0x62f2,0x62f3,0x62f4,0x62f5,0x62f6,0x62f7, + 0x62f8,0x62f9,0x62fa,0x62fb,0x62fc,0x62fd,0x62fe,0x62ff, + 0x6300,0x6301,0x6302,0x6303,0x6304,0x6305,0x6306,0x6307, + 0x6308,0x6309,0x630a,0x630b,0x630c,0x630d,0x630e,0x630f, + 0x6310,0x6311,0x6312,0x6313,0x6314,0x6315,0x6316,0x6317, + 0x6318,0x6319,0x631a,0x631b,0x631c,0x631d,0x631e,0x631f, + 0x6320,0x6321,0x6322,0x6323,0x6324,0x6325,0x6326,0x6327, + 0x6328,0x6329,0x632a,0x632b,0x632c,0x632d,0x632e,0x632f, + 0x6330,0x6331,0x6332,0x6333,0x6334,0x6335,0x6336,0x6337, + 0x6338,0x6339,0x633a,0x633b,0x633c,0x633d,0x633e,0x633f, + 0x6340,0x6341,0x6342,0x6343,0x6344,0x6345,0x6346,0x6347, + 0x6348,0x6349,0x634a,0x634b,0x634c,0x634d,0x634e,0x634f, + 0x6350,0x6351,0x6352,0x6353,0x6354,0x6355,0x6356,0x6357, + 0x6358,0x6359,0x635a,0x635b,0x635c,0x635d,0x635e,0x635f, + 0x6360,0x6361,0x6362,0x6363,0x6364,0x6365,0x6366,0x6367, + 0x6368,0x6369,0x636a,0x636b,0x636c,0x636d,0x636e,0x636f, + 0x6370,0x6371,0x6372,0x6373,0x6374,0x6375,0x6376,0x6377, + 0x6378,0x6379,0x637a,0x637b,0x637c,0x637d,0x637e,0x637f, + 0x6380,0x6381,0x6382,0x6383,0x6384,0x6385,0x6386,0x6387, + 0x6388,0x6389,0x638a,0x638b,0x638c,0x638d,0x638e,0x638f, + 0x6390,0x6391,0x6392,0x6393,0x6394,0x6395,0x6396,0x6397, + 0x6398,0x6399,0x639a,0x639b,0x639c,0x639d,0x639e,0x639f, + 0x63a0,0x63a1,0x63a2,0x63a3,0x63a4,0x63a5,0x63a6,0x63a7, + 0x63a8,0x63a9,0x63aa,0x63ab,0x63ac,0x63ad,0x63ae,0x63af, + 0x63b0,0x63b1,0x63b2,0x63b3,0x63b4,0x63b5,0x63b6,0x63b7, + 0x63b8,0x63b9,0x63ba,0x63bb,0x63bc,0x63bd,0x63be,0x63bf, + 0x63c0,0x63c1,0x63c2,0x63c3,0x63c4,0x63c5,0x63c6,0x63c7, + 0x63c8,0x63c9,0x63ca,0x63cb,0x63cc,0x63cd,0x63ce,0x63cf, + 0x63d0,0x63d1,0x63d2,0x63d3,0x63d4,0x63d5,0x63d6,0x63d7, + 0x63d8,0x63d9,0x63da,0x63db,0x63dc,0x63dd,0x63de,0x63df, + 0x63e0,0x63e1,0x63e2,0x63e3,0x63e4,0x63e5,0x63e6,0x63e7, + 0x63e8,0x63e9,0x63ea,0x63eb,0x63ec,0x63ed,0x63ee,0x63ef, + 0x63f0,0x63f1,0x63f2,0x63f3,0x63f4,0x63f5,0x63f6,0x63f7, + 0x63f8,0x63f9,0x63fa,0x63fb,0x63fc,0x63fd,0x63fe,0x63ff, + 0x6400,0x6401,0x6402,0x6403,0x6404,0x6405,0x6406,0x6407, + 0x6408,0x6409,0x640a,0x640b,0x640c,0x640d,0x640e,0x640f, + 0x6410,0x6411,0x6412,0x6413,0x6414,0x6415,0x6416,0x6417, + 0x6418,0x6419,0x641a,0x641b,0x641c,0x641d,0x641e,0x641f, + 0x6420,0x6421,0x6422,0x6423,0x6424,0x6425,0x6426,0x6427, + 0x6428,0x6429,0x642a,0x642b,0x642c,0x642d,0x642e,0x642f, + 0x6430,0x6431,0x6432,0x6433,0x6434,0x6435,0x6436,0x6437, + 0x6438,0x6439,0x643a,0x643b,0x643c,0x643d,0x643e,0x643f, + 0x6440,0x6441,0x6442,0x6443,0x6444,0x6445,0x6446,0x6447, + 0x6448,0x6449,0x644a,0x644b,0x644c,0x644d,0x644e,0x644f, + 0x6450,0x6451,0x6452,0x6453,0x6454,0x6455,0x6456,0x6457, + 0x6458,0x6459,0x645a,0x645b,0x645c,0x645d,0x645e,0x645f, + 0x6460,0x6461,0x6462,0x6463,0x6464,0x6465,0x6466,0x6467, + 0x6468,0x6469,0x646a,0x646b,0x646c,0x646d,0x646e,0x646f, + 0x6470,0x6471,0x6472,0x6473,0x6474,0x6475,0x6476,0x6477, + 0x6478,0x6479,0x647a,0x647b,0x647c,0x647d,0x647e,0x647f, + 0x6480,0x6481,0x6482,0x6483,0x6484,0x6485,0x6486,0x6487, + 0x6488,0x6489,0x648a,0x648b,0x648c,0x648d,0x648e,0x648f, + 0x6490,0x6491,0x6492,0x6493,0x6494,0x6495,0x6496,0x6497, + 0x6498,0x6499,0x649a,0x649b,0x649c,0x649d,0x649e,0x649f, + 0x64a0,0x64a1,0x64a2,0x64a3,0x64a4,0x64a5,0x64a6,0x64a7, + 0x64a8,0x64a9,0x64aa,0x64ab,0x64ac,0x64ad,0x64ae,0x64af, + 0x64b0,0x64b1,0x64b2,0x64b3,0x64b4,0x64b5,0x64b6,0x64b7, + 0x64b8,0x64b9,0x64ba,0x64bb,0x64bc,0x64bd,0x64be,0x64bf, + 0x64c0,0x64c1,0x64c2,0x64c3,0x64c4,0x64c5,0x64c6,0x64c7, + 0x64c8,0x64c9,0x64ca,0x64cb,0x64cc,0x64cd,0x64ce,0x64cf, + 0x64d0,0x64d1,0x64d2,0x64d3,0x64d4,0x64d5,0x64d6,0x64d7, + 0x64d8,0x64d9,0x64da,0x64db,0x64dc,0x64dd,0x64de,0x64df, + 0x64e0,0x64e1,0x64e2,0x64e3,0x64e4,0x64e5,0x64e6,0x64e7, + 0x64e8,0x64e9,0x64ea,0x64eb,0x64ec,0x64ed,0x64ee,0x64ef, + 0x64f0,0x64f1,0x64f2,0x64f3,0x64f4,0x64f5,0x64f6,0x64f7, + 0x64f8,0x64f9,0x64fa,0x64fb,0x64fc,0x64fd,0x64fe,0x64ff, + 0x6500,0x6501,0x6502,0x6503,0x6504,0x6505,0x6506,0x6507, + 0x6508,0x6509,0x650a,0x650b,0x650c,0x650d,0x650e,0x650f, + 0x6510,0x6511,0x6512,0x6513,0x6514,0x6515,0x6516,0x6517, + 0x6518,0x6519,0x651a,0x651b,0x651c,0x651d,0x651e,0x651f, + 0x6520,0x6521,0x6522,0x6523,0x6524,0x6525,0x6526,0x6527, + 0x6528,0x6529,0x652a,0x652b,0x652c,0x652d,0x652e,0x652f, + 0x6530,0x6531,0x6532,0x6533,0x6534,0x6535,0x6536,0x6537, + 0x6538,0x6539,0x653a,0x653b,0x653c,0x653d,0x653e,0x653f, + 0x6540,0x6541,0x6542,0x6543,0x6544,0x6545,0x6546,0x6547, + 0x6548,0x6549,0x654a,0x654b,0x654c,0x654d,0x654e,0x654f, + 0x6550,0x6551,0x6552,0x6553,0x6554,0x6555,0x6556,0x6557, + 0x6558,0x6559,0x655a,0x655b,0x655c,0x655d,0x655e,0x655f, + 0x6560,0x6561,0x6562,0x6563,0x6564,0x6565,0x6566,0x6567, + 0x6568,0x6569,0x656a,0x656b,0x656c,0x656d,0x656e,0x656f, + 0x6570,0x6571,0x6572,0x6573,0x6574,0x6575,0x6576,0x6577, + 0x6578,0x6579,0x657a,0x657b,0x657c,0x657d,0x657e,0x657f, + 0x6580,0x6581,0x6582,0x6583,0x6584,0x6585,0x6586,0x6587, + 0x6588,0x6589,0x658a,0x658b,0x658c,0x658d,0x658e,0x658f, + 0x6590,0x6591,0x6592,0x6593,0x6594,0x6595,0x6596,0x6597, + 0x6598,0x6599,0x659a,0x659b,0x659c,0x659d,0x659e,0x659f, + 0x65a0,0x65a1,0x65a2,0x65a3,0x65a4,0x65a5,0x65a6,0x65a7, + 0x65a8,0x65a9,0x65aa,0x65ab,0x65ac,0x65ad,0x65ae,0x65af, + 0x65b0,0x65b1,0x65b2,0x65b3,0x65b4,0x65b5,0x65b6,0x65b7, + 0x65b8,0x65b9,0x65ba,0x65bb,0x65bc,0x65bd,0x65be,0x65bf, + 0x65c0,0x65c1,0x65c2,0x65c3,0x65c4,0x65c5,0x65c6,0x65c7, + 0x65c8,0x65c9,0x65ca,0x65cb,0x65cc,0x65cd,0x65ce,0x65cf, + 0x65d0,0x65d1,0x65d2,0x65d3,0x65d4,0x65d5,0x65d6,0x65d7, + 0x65d8,0x65d9,0x65da,0x65db,0x65dc,0x65dd,0x65de,0x65df, + 0x65e0,0x65e1,0x65e2,0x65e3,0x65e4,0x65e5,0x65e6,0x65e7, + 0x65e8,0x65e9,0x65ea,0x65eb,0x65ec,0x65ed,0x65ee,0x65ef, + 0x65f0,0x65f1,0x65f2,0x65f3,0x65f4,0x65f5,0x65f6,0x65f7, + 0x65f8,0x65f9,0x65fa,0x65fb,0x65fc,0x65fd,0x65fe,0x65ff, + 0x6600,0x6601,0x6602,0x6603,0x6604,0x6605,0x6606,0x6607, + 0x6608,0x6609,0x660a,0x660b,0x660c,0x660d,0x660e,0x660f, + 0x6610,0x6611,0x6612,0x6613,0x6614,0x6615,0x6616,0x6617, + 0x6618,0x6619,0x661a,0x661b,0x661c,0x661d,0x661e,0x661f, + 0x6620,0x6621,0x6622,0x6623,0x6624,0x6625,0x6626,0x6627, + 0x6628,0x6629,0x662a,0x662b,0x662c,0x662d,0x662e,0x662f, + 0x6630,0x6631,0x6632,0x6633,0x6634,0x6635,0x6636,0x6637, + 0x6638,0x6639,0x663a,0x663b,0x663c,0x663d,0x663e,0x663f, + 0x6640,0x6641,0x6642,0x6643,0x6644,0x6645,0x6646,0x6647, + 0x6648,0x6649,0x664a,0x664b,0x664c,0x664d,0x664e,0x664f, + 0x6650,0x6651,0x6652,0x6653,0x6654,0x6655,0x6656,0x6657, + 0x6658,0x6659,0x665a,0x665b,0x665c,0x665d,0x665e,0x665f, + 0x6660,0x6661,0x6662,0x6663,0x6664,0x6665,0x6666,0x6667, + 0x6668,0x6669,0x666a,0x666b,0x666c,0x666d,0x666e,0x666f, + 0x6670,0x6671,0x6672,0x6673,0x6674,0x6675,0x6676,0x6677, + 0x6678,0x6679,0x667a,0x667b,0x667c,0x667d,0x667e,0x667f, + 0x6680,0x6681,0x6682,0x6683,0x6684,0x6685,0x6686,0x6687, + 0x6688,0x6689,0x668a,0x668b,0x668c,0x668d,0x668e,0x668f, + 0x6690,0x6691,0x6692,0x6693,0x6694,0x6695,0x6696,0x6697, + 0x6698,0x6699,0x669a,0x669b,0x669c,0x669d,0x669e,0x669f, + 0x66a0,0x66a1,0x66a2,0x66a3,0x66a4,0x66a5,0x66a6,0x66a7, + 0x66a8,0x66a9,0x66aa,0x66ab,0x66ac,0x66ad,0x66ae,0x66af, + 0x66b0,0x66b1,0x66b2,0x66b3,0x66b4,0x66b5,0x66b6,0x66b7, + 0x66b8,0x66b9,0x66ba,0x66bb,0x66bc,0x66bd,0x66be,0x66bf, + 0x66c0,0x66c1,0x66c2,0x66c3,0x66c4,0x66c5,0x66c6,0x66c7, + 0x66c8,0x66c9,0x66ca,0x66cb,0x66cc,0x66cd,0x66ce,0x66cf, + 0x66d0,0x66d1,0x66d2,0x66d3,0x66d4,0x66d5,0x66d6,0x66d7, + 0x66d8,0x66d9,0x66da,0x66db,0x66dc,0x66dd,0x66de,0x66df, + 0x66e0,0x66e1,0x66e2,0x66e3,0x66e4,0x66e5,0x66e6,0x66e7, + 0x66e8,0x66e9,0x66ea,0x66eb,0x66ec,0x66ed,0x66ee,0x66ef, + 0x66f0,0x66f1,0x66f2,0x66f3,0x66f4,0x66f5,0x66f6,0x66f7, + 0x66f8,0x66f9,0x66fa,0x66fb,0x66fc,0x66fd,0x66fe,0x66ff, + 0x6700,0x6701,0x6702,0x6703,0x6704,0x6705,0x6706,0x6707, + 0x6708,0x6709,0x670a,0x670b,0x670c,0x670d,0x670e,0x670f, + 0x6710,0x6711,0x6712,0x6713,0x6714,0x6715,0x6716,0x6717, + 0x6718,0x6719,0x671a,0x671b,0x671c,0x671d,0x671e,0x671f, + 0x6720,0x6721,0x6722,0x6723,0x6724,0x6725,0x6726,0x6727, + 0x6728,0x6729,0x672a,0x672b,0x672c,0x672d,0x672e,0x672f, + 0x6730,0x6731,0x6732,0x6733,0x6734,0x6735,0x6736,0x6737, + 0x6738,0x6739,0x673a,0x673b,0x673c,0x673d,0x673e,0x673f, + 0x6740,0x6741,0x6742,0x6743,0x6744,0x6745,0x6746,0x6747, + 0x6748,0x6749,0x674a,0x674b,0x674c,0x674d,0x674e,0x674f, + 0x6750,0x6751,0x6752,0x6753,0x6754,0x6755,0x6756,0x6757, + 0x6758,0x6759,0x675a,0x675b,0x675c,0x675d,0x675e,0x675f, + 0x6760,0x6761,0x6762,0x6763,0x6764,0x6765,0x6766,0x6767, + 0x6768,0x6769,0x676a,0x676b,0x676c,0x676d,0x676e,0x676f, + 0x6770,0x6771,0x6772,0x6773,0x6774,0x6775,0x6776,0x6777, + 0x6778,0x6779,0x677a,0x677b,0x677c,0x677d,0x677e,0x677f, + 0x6780,0x6781,0x6782,0x6783,0x6784,0x6785,0x6786,0x6787, + 0x6788,0x6789,0x678a,0x678b,0x678c,0x678d,0x678e,0x678f, + 0x6790,0x6791,0x6792,0x6793,0x6794,0x6795,0x6796,0x6797, + 0x6798,0x6799,0x679a,0x679b,0x679c,0x679d,0x679e,0x679f, + 0x67a0,0x67a1,0x67a2,0x67a3,0x67a4,0x67a5,0x67a6,0x67a7, + 0x67a8,0x67a9,0x67aa,0x67ab,0x67ac,0x67ad,0x67ae,0x67af, + 0x67b0,0x67b1,0x67b2,0x67b3,0x67b4,0x67b5,0x67b6,0x67b7, + 0x67b8,0x67b9,0x67ba,0x67bb,0x67bc,0x67bd,0x67be,0x67bf, + 0x67c0,0x67c1,0x67c2,0x67c3,0x67c4,0x67c5,0x67c6,0x67c7, + 0x67c8,0x67c9,0x67ca,0x67cb,0x67cc,0x67cd,0x67ce,0x67cf, + 0x67d0,0x67d1,0x67d2,0x67d3,0x67d4,0x67d5,0x67d6,0x67d7, + 0x67d8,0x67d9,0x67da,0x67db,0x67dc,0x67dd,0x67de,0x67df, + 0x67e0,0x67e1,0x67e2,0x67e3,0x67e4,0x67e5,0x67e6,0x67e7, + 0x67e8,0x67e9,0x67ea,0x67eb,0x67ec,0x67ed,0x67ee,0x67ef, + 0x67f0,0x67f1,0x67f2,0x67f3,0x67f4,0x67f5,0x67f6,0x67f7, + 0x67f8,0x67f9,0x67fa,0x67fb,0x67fc,0x67fd,0x67fe,0x67ff, + 0x6800,0x6801,0x6802,0x6803,0x6804,0x6805,0x6806,0x6807, + 0x6808,0x6809,0x680a,0x680b,0x680c,0x680d,0x680e,0x680f, + 0x6810,0x6811,0x6812,0x6813,0x6814,0x6815,0x6816,0x6817, + 0x6818,0x6819,0x681a,0x681b,0x681c,0x681d,0x681e,0x681f, + 0x6820,0x6821,0x6822,0x6823,0x6824,0x6825,0x6826,0x6827, + 0x6828,0x6829,0x682a,0x682b,0x682c,0x682d,0x682e,0x682f, + 0x6830,0x6831,0x6832,0x6833,0x6834,0x6835,0x6836,0x6837, + 0x6838,0x6839,0x683a,0x683b,0x683c,0x683d,0x683e,0x683f, + 0x6840,0x6841,0x6842,0x6843,0x6844,0x6845,0x6846,0x6847, + 0x6848,0x6849,0x684a,0x684b,0x684c,0x684d,0x684e,0x684f, + 0x6850,0x6851,0x6852,0x6853,0x6854,0x6855,0x6856,0x6857, + 0x6858,0x6859,0x685a,0x685b,0x685c,0x685d,0x685e,0x685f, + 0x6860,0x6861,0x6862,0x6863,0x6864,0x6865,0x6866,0x6867, + 0x6868,0x6869,0x686a,0x686b,0x686c,0x686d,0x686e,0x686f, + 0x6870,0x6871,0x6872,0x6873,0x6874,0x6875,0x6876,0x6877, + 0x6878,0x6879,0x687a,0x687b,0x687c,0x687d,0x687e,0x687f, + 0x6880,0x6881,0x6882,0x6883,0x6884,0x6885,0x6886,0x6887, + 0x6888,0x6889,0x688a,0x688b,0x688c,0x688d,0x688e,0x688f, + 0x6890,0x6891,0x6892,0x6893,0x6894,0x6895,0x6896,0x6897, + 0x6898,0x6899,0x689a,0x689b,0x689c,0x689d,0x689e,0x689f, + 0x68a0,0x68a1,0x68a2,0x68a3,0x68a4,0x68a5,0x68a6,0x68a7, + 0x68a8,0x68a9,0x68aa,0x68ab,0x68ac,0x68ad,0x68ae,0x68af, + 0x68b0,0x68b1,0x68b2,0x68b3,0x68b4,0x68b5,0x68b6,0x68b7, + 0x68b8,0x68b9,0x68ba,0x68bb,0x68bc,0x68bd,0x68be,0x68bf, + 0x68c0,0x68c1,0x68c2,0x68c3,0x68c4,0x68c5,0x68c6,0x68c7, + 0x68c8,0x68c9,0x68ca,0x68cb,0x68cc,0x68cd,0x68ce,0x68cf, + 0x68d0,0x68d1,0x68d2,0x68d3,0x68d4,0x68d5,0x68d6,0x68d7, + 0x68d8,0x68d9,0x68da,0x68db,0x68dc,0x68dd,0x68de,0x68df, + 0x68e0,0x68e1,0x68e2,0x68e3,0x68e4,0x68e5,0x68e6,0x68e7, + 0x68e8,0x68e9,0x68ea,0x68eb,0x68ec,0x68ed,0x68ee,0x68ef, + 0x68f0,0x68f1,0x68f2,0x68f3,0x68f4,0x68f5,0x68f6,0x68f7, + 0x68f8,0x68f9,0x68fa,0x68fb,0x68fc,0x68fd,0x68fe,0x68ff, + 0x6900,0x6901,0x6902,0x6903,0x6904,0x6905,0x6906,0x6907, + 0x6908,0x6909,0x690a,0x690b,0x690c,0x690d,0x690e,0x690f, + 0x6910,0x6911,0x6912,0x6913,0x6914,0x6915,0x6916,0x6917, + 0x6918,0x6919,0x691a,0x691b,0x691c,0x691d,0x691e,0x691f, + 0x6920,0x6921,0x6922,0x6923,0x6924,0x6925,0x6926,0x6927, + 0x6928,0x6929,0x692a,0x692b,0x692c,0x692d,0x692e,0x692f, + 0x6930,0x6931,0x6932,0x6933,0x6934,0x6935,0x6936,0x6937, + 0x6938,0x6939,0x693a,0x693b,0x693c,0x693d,0x693e,0x693f, + 0x6940,0x6941,0x6942,0x6943,0x6944,0x6945,0x6946,0x6947, + 0x6948,0x6949,0x694a,0x694b,0x694c,0x694d,0x694e,0x694f, + 0x6950,0x6951,0x6952,0x6953,0x6954,0x6955,0x6956,0x6957, + 0x6958,0x6959,0x695a,0x695b,0x695c,0x695d,0x695e,0x695f, + 0x6960,0x6961,0x6962,0x6963,0x6964,0x6965,0x6966,0x6967, + 0x6968,0x6969,0x696a,0x696b,0x696c,0x696d,0x696e,0x696f, + 0x6970,0x6971,0x6972,0x6973,0x6974,0x6975,0x6976,0x6977, + 0x6978,0x6979,0x697a,0x697b,0x697c,0x697d,0x697e,0x697f, + 0x6980,0x6981,0x6982,0x6983,0x6984,0x6985,0x6986,0x6987, + 0x6988,0x6989,0x698a,0x698b,0x698c,0x698d,0x698e,0x698f, + 0x6990,0x6991,0x6992,0x6993,0x6994,0x6995,0x6996,0x6997, + 0x6998,0x6999,0x699a,0x699b,0x699c,0x699d,0x699e,0x699f, + 0x69a0,0x69a1,0x69a2,0x69a3,0x69a4,0x69a5,0x69a6,0x69a7, + 0x69a8,0x69a9,0x69aa,0x69ab,0x69ac,0x69ad,0x69ae,0x69af, + 0x69b0,0x69b1,0x69b2,0x69b3,0x69b4,0x69b5,0x69b6,0x69b7, + 0x69b8,0x69b9,0x69ba,0x69bb,0x69bc,0x69bd,0x69be,0x69bf, + 0x69c0,0x69c1,0x69c2,0x69c3,0x69c4,0x69c5,0x69c6,0x69c7, + 0x69c8,0x69c9,0x69ca,0x69cb,0x69cc,0x69cd,0x69ce,0x69cf, + 0x69d0,0x69d1,0x69d2,0x69d3,0x69d4,0x69d5,0x69d6,0x69d7, + 0x69d8,0x69d9,0x69da,0x69db,0x69dc,0x69dd,0x69de,0x69df, + 0x69e0,0x69e1,0x69e2,0x69e3,0x69e4,0x69e5,0x69e6,0x69e7, + 0x69e8,0x69e9,0x69ea,0x69eb,0x69ec,0x69ed,0x69ee,0x69ef, + 0x69f0,0x69f1,0x69f2,0x69f3,0x69f4,0x69f5,0x69f6,0x69f7, + 0x69f8,0x69f9,0x69fa,0x69fb,0x69fc,0x69fd,0x69fe,0x69ff, + 0x6a00,0x6a01,0x6a02,0x6a03,0x6a04,0x6a05,0x6a06,0x6a07, + 0x6a08,0x6a09,0x6a0a,0x6a0b,0x6a0c,0x6a0d,0x6a0e,0x6a0f, + 0x6a10,0x6a11,0x6a12,0x6a13,0x6a14,0x6a15,0x6a16,0x6a17, + 0x6a18,0x6a19,0x6a1a,0x6a1b,0x6a1c,0x6a1d,0x6a1e,0x6a1f, + 0x6a20,0x6a21,0x6a22,0x6a23,0x6a24,0x6a25,0x6a26,0x6a27, + 0x6a28,0x6a29,0x6a2a,0x6a2b,0x6a2c,0x6a2d,0x6a2e,0x6a2f, + 0x6a30,0x6a31,0x6a32,0x6a33,0x6a34,0x6a35,0x6a36,0x6a37, + 0x6a38,0x6a39,0x6a3a,0x6a3b,0x6a3c,0x6a3d,0x6a3e,0x6a3f, + 0x6a40,0x6a41,0x6a42,0x6a43,0x6a44,0x6a45,0x6a46,0x6a47, + 0x6a48,0x6a49,0x6a4a,0x6a4b,0x6a4c,0x6a4d,0x6a4e,0x6a4f, + 0x6a50,0x6a51,0x6a52,0x6a53,0x6a54,0x6a55,0x6a56,0x6a57, + 0x6a58,0x6a59,0x6a5a,0x6a5b,0x6a5c,0x6a5d,0x6a5e,0x6a5f, + 0x6a60,0x6a61,0x6a62,0x6a63,0x6a64,0x6a65,0x6a66,0x6a67, + 0x6a68,0x6a69,0x6a6a,0x6a6b,0x6a6c,0x6a6d,0x6a6e,0x6a6f, + 0x6a70,0x6a71,0x6a72,0x6a73,0x6a74,0x6a75,0x6a76,0x6a77, + 0x6a78,0x6a79,0x6a7a,0x6a7b,0x6a7c,0x6a7d,0x6a7e,0x6a7f, + 0x6a80,0x6a81,0x6a82,0x6a83,0x6a84,0x6a85,0x6a86,0x6a87, + 0x6a88,0x6a89,0x6a8a,0x6a8b,0x6a8c,0x6a8d,0x6a8e,0x6a8f, + 0x6a90,0x6a91,0x6a92,0x6a93,0x6a94,0x6a95,0x6a96,0x6a97, + 0x6a98,0x6a99,0x6a9a,0x6a9b,0x6a9c,0x6a9d,0x6a9e,0x6a9f, + 0x6aa0,0x6aa1,0x6aa2,0x6aa3,0x6aa4,0x6aa5,0x6aa6,0x6aa7, + 0x6aa8,0x6aa9,0x6aaa,0x6aab,0x6aac,0x6aad,0x6aae,0x6aaf, + 0x6ab0,0x6ab1,0x6ab2,0x6ab3,0x6ab4,0x6ab5,0x6ab6,0x6ab7, + 0x6ab8,0x6ab9,0x6aba,0x6abb,0x6abc,0x6abd,0x6abe,0x6abf, + 0x6ac0,0x6ac1,0x6ac2,0x6ac3,0x6ac4,0x6ac5,0x6ac6,0x6ac7, + 0x6ac8,0x6ac9,0x6aca,0x6acb,0x6acc,0x6acd,0x6ace,0x6acf, + 0x6ad0,0x6ad1,0x6ad2,0x6ad3,0x6ad4,0x6ad5,0x6ad6,0x6ad7, + 0x6ad8,0x6ad9,0x6ada,0x6adb,0x6adc,0x6add,0x6ade,0x6adf, + 0x6ae0,0x6ae1,0x6ae2,0x6ae3,0x6ae4,0x6ae5,0x6ae6,0x6ae7, + 0x6ae8,0x6ae9,0x6aea,0x6aeb,0x6aec,0x6aed,0x6aee,0x6aef, + 0x6af0,0x6af1,0x6af2,0x6af3,0x6af4,0x6af5,0x6af6,0x6af7, + 0x6af8,0x6af9,0x6afa,0x6afb,0x6afc,0x6afd,0x6afe,0x6aff, + 0x6b00,0x6b01,0x6b02,0x6b03,0x6b04,0x6b05,0x6b06,0x6b07, + 0x6b08,0x6b09,0x6b0a,0x6b0b,0x6b0c,0x6b0d,0x6b0e,0x6b0f, + 0x6b10,0x6b11,0x6b12,0x6b13,0x6b14,0x6b15,0x6b16,0x6b17, + 0x6b18,0x6b19,0x6b1a,0x6b1b,0x6b1c,0x6b1d,0x6b1e,0x6b1f, + 0x6b20,0x6b21,0x6b22,0x6b23,0x6b24,0x6b25,0x6b26,0x6b27, + 0x6b28,0x6b29,0x6b2a,0x6b2b,0x6b2c,0x6b2d,0x6b2e,0x6b2f, + 0x6b30,0x6b31,0x6b32,0x6b33,0x6b34,0x6b35,0x6b36,0x6b37, + 0x6b38,0x6b39,0x6b3a,0x6b3b,0x6b3c,0x6b3d,0x6b3e,0x6b3f, + 0x6b40,0x6b41,0x6b42,0x6b43,0x6b44,0x6b45,0x6b46,0x6b47, + 0x6b48,0x6b49,0x6b4a,0x6b4b,0x6b4c,0x6b4d,0x6b4e,0x6b4f, + 0x6b50,0x6b51,0x6b52,0x6b53,0x6b54,0x6b55,0x6b56,0x6b57, + 0x6b58,0x6b59,0x6b5a,0x6b5b,0x6b5c,0x6b5d,0x6b5e,0x6b5f, + 0x6b60,0x6b61,0x6b62,0x6b63,0x6b64,0x6b65,0x6b66,0x6b67, + 0x6b68,0x6b69,0x6b6a,0x6b6b,0x6b6c,0x6b6d,0x6b6e,0x6b6f, + 0x6b70,0x6b71,0x6b72,0x6b73,0x6b74,0x6b75,0x6b76,0x6b77, + 0x6b78,0x6b79,0x6b7a,0x6b7b,0x6b7c,0x6b7d,0x6b7e,0x6b7f, + 0x6b80,0x6b81,0x6b82,0x6b83,0x6b84,0x6b85,0x6b86,0x6b87, + 0x6b88,0x6b89,0x6b8a,0x6b8b,0x6b8c,0x6b8d,0x6b8e,0x6b8f, + 0x6b90,0x6b91,0x6b92,0x6b93,0x6b94,0x6b95,0x6b96,0x6b97, + 0x6b98,0x6b99,0x6b9a,0x6b9b,0x6b9c,0x6b9d,0x6b9e,0x6b9f, + 0x6ba0,0x6ba1,0x6ba2,0x6ba3,0x6ba4,0x6ba5,0x6ba6,0x6ba7, + 0x6ba8,0x6ba9,0x6baa,0x6bab,0x6bac,0x6bad,0x6bae,0x6baf, + 0x6bb0,0x6bb1,0x6bb2,0x6bb3,0x6bb4,0x6bb5,0x6bb6,0x6bb7, + 0x6bb8,0x6bb9,0x6bba,0x6bbb,0x6bbc,0x6bbd,0x6bbe,0x6bbf, + 0x6bc0,0x6bc1,0x6bc2,0x6bc3,0x6bc4,0x6bc5,0x6bc6,0x6bc7, + 0x6bc8,0x6bc9,0x6bca,0x6bcb,0x6bcc,0x6bcd,0x6bce,0x6bcf, + 0x6bd0,0x6bd1,0x6bd2,0x6bd3,0x6bd4,0x6bd5,0x6bd6,0x6bd7, + 0x6bd8,0x6bd9,0x6bda,0x6bdb,0x6bdc,0x6bdd,0x6bde,0x6bdf, + 0x6be0,0x6be1,0x6be2,0x6be3,0x6be4,0x6be5,0x6be6,0x6be7, + 0x6be8,0x6be9,0x6bea,0x6beb,0x6bec,0x6bed,0x6bee,0x6bef, + 0x6bf0,0x6bf1,0x6bf2,0x6bf3,0x6bf4,0x6bf5,0x6bf6,0x6bf7, + 0x6bf8,0x6bf9,0x6bfa,0x6bfb,0x6bfc,0x6bfd,0x6bfe,0x6bff, + 0x6c00,0x6c01,0x6c02,0x6c03,0x6c04,0x6c05,0x6c06,0x6c07, + 0x6c08,0x6c09,0x6c0a,0x6c0b,0x6c0c,0x6c0d,0x6c0e,0x6c0f, + 0x6c10,0x6c11,0x6c12,0x6c13,0x6c14,0x6c15,0x6c16,0x6c17, + 0x6c18,0x6c19,0x6c1a,0x6c1b,0x6c1c,0x6c1d,0x6c1e,0x6c1f, + 0x6c20,0x6c21,0x6c22,0x6c23,0x6c24,0x6c25,0x6c26,0x6c27, + 0x6c28,0x6c29,0x6c2a,0x6c2b,0x6c2c,0x6c2d,0x6c2e,0x6c2f, + 0x6c30,0x6c31,0x6c32,0x6c33,0x6c34,0x6c35,0x6c36,0x6c37, + 0x6c38,0x6c39,0x6c3a,0x6c3b,0x6c3c,0x6c3d,0x6c3e,0x6c3f, + 0x6c40,0x6c41,0x6c42,0x6c43,0x6c44,0x6c45,0x6c46,0x6c47, + 0x6c48,0x6c49,0x6c4a,0x6c4b,0x6c4c,0x6c4d,0x6c4e,0x6c4f, + 0x6c50,0x6c51,0x6c52,0x6c53,0x6c54,0x6c55,0x6c56,0x6c57, + 0x6c58,0x6c59,0x6c5a,0x6c5b,0x6c5c,0x6c5d,0x6c5e,0x6c5f, + 0x6c60,0x6c61,0x6c62,0x6c63,0x6c64,0x6c65,0x6c66,0x6c67, + 0x6c68,0x6c69,0x6c6a,0x6c6b,0x6c6c,0x6c6d,0x6c6e,0x6c6f, + 0x6c70,0x6c71,0x6c72,0x6c73,0x6c74,0x6c75,0x6c76,0x6c77, + 0x6c78,0x6c79,0x6c7a,0x6c7b,0x6c7c,0x6c7d,0x6c7e,0x6c7f, + 0x6c80,0x6c81,0x6c82,0x6c83,0x6c84,0x6c85,0x6c86,0x6c87, + 0x6c88,0x6c89,0x6c8a,0x6c8b,0x6c8c,0x6c8d,0x6c8e,0x6c8f, + 0x6c90,0x6c91,0x6c92,0x6c93,0x6c94,0x6c95,0x6c96,0x6c97, + 0x6c98,0x6c99,0x6c9a,0x6c9b,0x6c9c,0x6c9d,0x6c9e,0x6c9f, + 0x6ca0,0x6ca1,0x6ca2,0x6ca3,0x6ca4,0x6ca5,0x6ca6,0x6ca7, + 0x6ca8,0x6ca9,0x6caa,0x6cab,0x6cac,0x6cad,0x6cae,0x6caf, + 0x6cb0,0x6cb1,0x6cb2,0x6cb3,0x6cb4,0x6cb5,0x6cb6,0x6cb7, + 0x6cb8,0x6cb9,0x6cba,0x6cbb,0x6cbc,0x6cbd,0x6cbe,0x6cbf, + 0x6cc0,0x6cc1,0x6cc2,0x6cc3,0x6cc4,0x6cc5,0x6cc6,0x6cc7, + 0x6cc8,0x6cc9,0x6cca,0x6ccb,0x6ccc,0x6ccd,0x6cce,0x6ccf, + 0x6cd0,0x6cd1,0x6cd2,0x6cd3,0x6cd4,0x6cd5,0x6cd6,0x6cd7, + 0x6cd8,0x6cd9,0x6cda,0x6cdb,0x6cdc,0x6cdd,0x6cde,0x6cdf, + 0x6ce0,0x6ce1,0x6ce2,0x6ce3,0x6ce4,0x6ce5,0x6ce6,0x6ce7, + 0x6ce8,0x6ce9,0x6cea,0x6ceb,0x6cec,0x6ced,0x6cee,0x6cef, + 0x6cf0,0x6cf1,0x6cf2,0x6cf3,0x6cf4,0x6cf5,0x6cf6,0x6cf7, + 0x6cf8,0x6cf9,0x6cfa,0x6cfb,0x6cfc,0x6cfd,0x6cfe,0x6cff, + 0x6d00,0x6d01,0x6d02,0x6d03,0x6d04,0x6d05,0x6d06,0x6d07, + 0x6d08,0x6d09,0x6d0a,0x6d0b,0x6d0c,0x6d0d,0x6d0e,0x6d0f, + 0x6d10,0x6d11,0x6d12,0x6d13,0x6d14,0x6d15,0x6d16,0x6d17, + 0x6d18,0x6d19,0x6d1a,0x6d1b,0x6d1c,0x6d1d,0x6d1e,0x6d1f, + 0x6d20,0x6d21,0x6d22,0x6d23,0x6d24,0x6d25,0x6d26,0x6d27, + 0x6d28,0x6d29,0x6d2a,0x6d2b,0x6d2c,0x6d2d,0x6d2e,0x6d2f, + 0x6d30,0x6d31,0x6d32,0x6d33,0x6d34,0x6d35,0x6d36,0x6d37, + 0x6d38,0x6d39,0x6d3a,0x6d3b,0x6d3c,0x6d3d,0x6d3e,0x6d3f, + 0x6d40,0x6d41,0x6d42,0x6d43,0x6d44,0x6d45,0x6d46,0x6d47, + 0x6d48,0x6d49,0x6d4a,0x6d4b,0x6d4c,0x6d4d,0x6d4e,0x6d4f, + 0x6d50,0x6d51,0x6d52,0x6d53,0x6d54,0x6d55,0x6d56,0x6d57, + 0x6d58,0x6d59,0x6d5a,0x6d5b,0x6d5c,0x6d5d,0x6d5e,0x6d5f, + 0x6d60,0x6d61,0x6d62,0x6d63,0x6d64,0x6d65,0x6d66,0x6d67, + 0x6d68,0x6d69,0x6d6a,0x6d6b,0x6d6c,0x6d6d,0x6d6e,0x6d6f, + 0x6d70,0x6d71,0x6d72,0x6d73,0x6d74,0x6d75,0x6d76,0x6d77, + 0x6d78,0x6d79,0x6d7a,0x6d7b,0x6d7c,0x6d7d,0x6d7e,0x6d7f, + 0x6d80,0x6d81,0x6d82,0x6d83,0x6d84,0x6d85,0x6d86,0x6d87, + 0x6d88,0x6d89,0x6d8a,0x6d8b,0x6d8c,0x6d8d,0x6d8e,0x6d8f, + 0x6d90,0x6d91,0x6d92,0x6d93,0x6d94,0x6d95,0x6d96,0x6d97, + 0x6d98,0x6d99,0x6d9a,0x6d9b,0x6d9c,0x6d9d,0x6d9e,0x6d9f, + 0x6da0,0x6da1,0x6da2,0x6da3,0x6da4,0x6da5,0x6da6,0x6da7, + 0x6da8,0x6da9,0x6daa,0x6dab,0x6dac,0x6dad,0x6dae,0x6daf, + 0x6db0,0x6db1,0x6db2,0x6db3,0x6db4,0x6db5,0x6db6,0x6db7, + 0x6db8,0x6db9,0x6dba,0x6dbb,0x6dbc,0x6dbd,0x6dbe,0x6dbf, + 0x6dc0,0x6dc1,0x6dc2,0x6dc3,0x6dc4,0x6dc5,0x6dc6,0x6dc7, + 0x6dc8,0x6dc9,0x6dca,0x6dcb,0x6dcc,0x6dcd,0x6dce,0x6dcf, + 0x6dd0,0x6dd1,0x6dd2,0x6dd3,0x6dd4,0x6dd5,0x6dd6,0x6dd7, + 0x6dd8,0x6dd9,0x6dda,0x6ddb,0x6ddc,0x6ddd,0x6dde,0x6ddf, + 0x6de0,0x6de1,0x6de2,0x6de3,0x6de4,0x6de5,0x6de6,0x6de7, + 0x6de8,0x6de9,0x6dea,0x6deb,0x6dec,0x6ded,0x6dee,0x6def, + 0x6df0,0x6df1,0x6df2,0x6df3,0x6df4,0x6df5,0x6df6,0x6df7, + 0x6df8,0x6df9,0x6dfa,0x6dfb,0x6dfc,0x6dfd,0x6dfe,0x6dff, + 0x6e00,0x6e01,0x6e02,0x6e03,0x6e04,0x6e05,0x6e06,0x6e07, + 0x6e08,0x6e09,0x6e0a,0x6e0b,0x6e0c,0x6e0d,0x6e0e,0x6e0f, + 0x6e10,0x6e11,0x6e12,0x6e13,0x6e14,0x6e15,0x6e16,0x6e17, + 0x6e18,0x6e19,0x6e1a,0x6e1b,0x6e1c,0x6e1d,0x6e1e,0x6e1f, + 0x6e20,0x6e21,0x6e22,0x6e23,0x6e24,0x6e25,0x6e26,0x6e27, + 0x6e28,0x6e29,0x6e2a,0x6e2b,0x6e2c,0x6e2d,0x6e2e,0x6e2f, + 0x6e30,0x6e31,0x6e32,0x6e33,0x6e34,0x6e35,0x6e36,0x6e37, + 0x6e38,0x6e39,0x6e3a,0x6e3b,0x6e3c,0x6e3d,0x6e3e,0x6e3f, + 0x6e40,0x6e41,0x6e42,0x6e43,0x6e44,0x6e45,0x6e46,0x6e47, + 0x6e48,0x6e49,0x6e4a,0x6e4b,0x6e4c,0x6e4d,0x6e4e,0x6e4f, + 0x6e50,0x6e51,0x6e52,0x6e53,0x6e54,0x6e55,0x6e56,0x6e57, + 0x6e58,0x6e59,0x6e5a,0x6e5b,0x6e5c,0x6e5d,0x6e5e,0x6e5f, + 0x6e60,0x6e61,0x6e62,0x6e63,0x6e64,0x6e65,0x6e66,0x6e67, + 0x6e68,0x6e69,0x6e6a,0x6e6b,0x6e6c,0x6e6d,0x6e6e,0x6e6f, + 0x6e70,0x6e71,0x6e72,0x6e73,0x6e74,0x6e75,0x6e76,0x6e77, + 0x6e78,0x6e79,0x6e7a,0x6e7b,0x6e7c,0x6e7d,0x6e7e,0x6e7f, + 0x6e80,0x6e81,0x6e82,0x6e83,0x6e84,0x6e85,0x6e86,0x6e87, + 0x6e88,0x6e89,0x6e8a,0x6e8b,0x6e8c,0x6e8d,0x6e8e,0x6e8f, + 0x6e90,0x6e91,0x6e92,0x6e93,0x6e94,0x6e95,0x6e96,0x6e97, + 0x6e98,0x6e99,0x6e9a,0x6e9b,0x6e9c,0x6e9d,0x6e9e,0x6e9f, + 0x6ea0,0x6ea1,0x6ea2,0x6ea3,0x6ea4,0x6ea5,0x6ea6,0x6ea7, + 0x6ea8,0x6ea9,0x6eaa,0x6eab,0x6eac,0x6ead,0x6eae,0x6eaf, + 0x6eb0,0x6eb1,0x6eb2,0x6eb3,0x6eb4,0x6eb5,0x6eb6,0x6eb7, + 0x6eb8,0x6eb9,0x6eba,0x6ebb,0x6ebc,0x6ebd,0x6ebe,0x6ebf, + 0x6ec0,0x6ec1,0x6ec2,0x6ec3,0x6ec4,0x6ec5,0x6ec6,0x6ec7, + 0x6ec8,0x6ec9,0x6eca,0x6ecb,0x6ecc,0x6ecd,0x6ece,0x6ecf, + 0x6ed0,0x6ed1,0x6ed2,0x6ed3,0x6ed4,0x6ed5,0x6ed6,0x6ed7, + 0x6ed8,0x6ed9,0x6eda,0x6edb,0x6edc,0x6edd,0x6ede,0x6edf, + 0x6ee0,0x6ee1,0x6ee2,0x6ee3,0x6ee4,0x6ee5,0x6ee6,0x6ee7, + 0x6ee8,0x6ee9,0x6eea,0x6eeb,0x6eec,0x6eed,0x6eee,0x6eef, + 0x6ef0,0x6ef1,0x6ef2,0x6ef3,0x6ef4,0x6ef5,0x6ef6,0x6ef7, + 0x6ef8,0x6ef9,0x6efa,0x6efb,0x6efc,0x6efd,0x6efe,0x6eff, + 0x6f00,0x6f01,0x6f02,0x6f03,0x6f04,0x6f05,0x6f06,0x6f07, + 0x6f08,0x6f09,0x6f0a,0x6f0b,0x6f0c,0x6f0d,0x6f0e,0x6f0f, + 0x6f10,0x6f11,0x6f12,0x6f13,0x6f14,0x6f15,0x6f16,0x6f17, + 0x6f18,0x6f19,0x6f1a,0x6f1b,0x6f1c,0x6f1d,0x6f1e,0x6f1f, + 0x6f20,0x6f21,0x6f22,0x6f23,0x6f24,0x6f25,0x6f26,0x6f27, + 0x6f28,0x6f29,0x6f2a,0x6f2b,0x6f2c,0x6f2d,0x6f2e,0x6f2f, + 0x6f30,0x6f31,0x6f32,0x6f33,0x6f34,0x6f35,0x6f36,0x6f37, + 0x6f38,0x6f39,0x6f3a,0x6f3b,0x6f3c,0x6f3d,0x6f3e,0x6f3f, + 0x6f40,0x6f41,0x6f42,0x6f43,0x6f44,0x6f45,0x6f46,0x6f47, + 0x6f48,0x6f49,0x6f4a,0x6f4b,0x6f4c,0x6f4d,0x6f4e,0x6f4f, + 0x6f50,0x6f51,0x6f52,0x6f53,0x6f54,0x6f55,0x6f56,0x6f57, + 0x6f58,0x6f59,0x6f5a,0x6f5b,0x6f5c,0x6f5d,0x6f5e,0x6f5f, + 0x6f60,0x6f61,0x6f62,0x6f63,0x6f64,0x6f65,0x6f66,0x6f67, + 0x6f68,0x6f69,0x6f6a,0x6f6b,0x6f6c,0x6f6d,0x6f6e,0x6f6f, + 0x6f70,0x6f71,0x6f72,0x6f73,0x6f74,0x6f75,0x6f76,0x6f77, + 0x6f78,0x6f79,0x6f7a,0x6f7b,0x6f7c,0x6f7d,0x6f7e,0x6f7f, + 0x6f80,0x6f81,0x6f82,0x6f83,0x6f84,0x6f85,0x6f86,0x6f87, + 0x6f88,0x6f89,0x6f8a,0x6f8b,0x6f8c,0x6f8d,0x6f8e,0x6f8f, + 0x6f90,0x6f91,0x6f92,0x6f93,0x6f94,0x6f95,0x6f96,0x6f97, + 0x6f98,0x6f99,0x6f9a,0x6f9b,0x6f9c,0x6f9d,0x6f9e,0x6f9f, + 0x6fa0,0x6fa1,0x6fa2,0x6fa3,0x6fa4,0x6fa5,0x6fa6,0x6fa7, + 0x6fa8,0x6fa9,0x6faa,0x6fab,0x6fac,0x6fad,0x6fae,0x6faf, + 0x6fb0,0x6fb1,0x6fb2,0x6fb3,0x6fb4,0x6fb5,0x6fb6,0x6fb7, + 0x6fb8,0x6fb9,0x6fba,0x6fbb,0x6fbc,0x6fbd,0x6fbe,0x6fbf, + 0x6fc0,0x6fc1,0x6fc2,0x6fc3,0x6fc4,0x6fc5,0x6fc6,0x6fc7, + 0x6fc8,0x6fc9,0x6fca,0x6fcb,0x6fcc,0x6fcd,0x6fce,0x6fcf, + 0x6fd0,0x6fd1,0x6fd2,0x6fd3,0x6fd4,0x6fd5,0x6fd6,0x6fd7, + 0x6fd8,0x6fd9,0x6fda,0x6fdb,0x6fdc,0x6fdd,0x6fde,0x6fdf, + 0x6fe0,0x6fe1,0x6fe2,0x6fe3,0x6fe4,0x6fe5,0x6fe6,0x6fe7, + 0x6fe8,0x6fe9,0x6fea,0x6feb,0x6fec,0x6fed,0x6fee,0x6fef, + 0x6ff0,0x6ff1,0x6ff2,0x6ff3,0x6ff4,0x6ff5,0x6ff6,0x6ff7, + 0x6ff8,0x6ff9,0x6ffa,0x6ffb,0x6ffc,0x6ffd,0x6ffe,0x6fff, + 0x7000,0x7001,0x7002,0x7003,0x7004,0x7005,0x7006,0x7007, + 0x7008,0x7009,0x700a,0x700b,0x700c,0x700d,0x700e,0x700f, + 0x7010,0x7011,0x7012,0x7013,0x7014,0x7015,0x7016,0x7017, + 0x7018,0x7019,0x701a,0x701b,0x701c,0x701d,0x701e,0x701f, + 0x7020,0x7021,0x7022,0x7023,0x7024,0x7025,0x7026,0x7027, + 0x7028,0x7029,0x702a,0x702b,0x702c,0x702d,0x702e,0x702f, + 0x7030,0x7031,0x7032,0x7033,0x7034,0x7035,0x7036,0x7037, + 0x7038,0x7039,0x703a,0x703b,0x703c,0x703d,0x703e,0x703f, + 0x7040,0x7041,0x7042,0x7043,0x7044,0x7045,0x7046,0x7047, + 0x7048,0x7049,0x704a,0x704b,0x704c,0x704d,0x704e,0x704f, + 0x7050,0x7051,0x7052,0x7053,0x7054,0x7055,0x7056,0x7057, + 0x7058,0x7059,0x705a,0x705b,0x705c,0x705d,0x705e,0x705f, + 0x7060,0x7061,0x7062,0x7063,0x7064,0x7065,0x7066,0x7067, + 0x7068,0x7069,0x706a,0x706b,0x706c,0x706d,0x706e,0x706f, + 0x7070,0x7071,0x7072,0x7073,0x7074,0x7075,0x7076,0x7077, + 0x7078,0x7079,0x707a,0x707b,0x707c,0x707d,0x707e,0x707f, + 0x7080,0x7081,0x7082,0x7083,0x7084,0x7085,0x7086,0x7087, + 0x7088,0x7089,0x708a,0x708b,0x708c,0x708d,0x708e,0x708f, + 0x7090,0x7091,0x7092,0x7093,0x7094,0x7095,0x7096,0x7097, + 0x7098,0x7099,0x709a,0x709b,0x709c,0x709d,0x709e,0x709f, + 0x70a0,0x70a1,0x70a2,0x70a3,0x70a4,0x70a5,0x70a6,0x70a7, + 0x70a8,0x70a9,0x70aa,0x70ab,0x70ac,0x70ad,0x70ae,0x70af, + 0x70b0,0x70b1,0x70b2,0x70b3,0x70b4,0x70b5,0x70b6,0x70b7, + 0x70b8,0x70b9,0x70ba,0x70bb,0x70bc,0x70bd,0x70be,0x70bf, + 0x70c0,0x70c1,0x70c2,0x70c3,0x70c4,0x70c5,0x70c6,0x70c7, + 0x70c8,0x70c9,0x70ca,0x70cb,0x70cc,0x70cd,0x70ce,0x70cf, + 0x70d0,0x70d1,0x70d2,0x70d3,0x70d4,0x70d5,0x70d6,0x70d7, + 0x70d8,0x70d9,0x70da,0x70db,0x70dc,0x70dd,0x70de,0x70df, + 0x70e0,0x70e1,0x70e2,0x70e3,0x70e4,0x70e5,0x70e6,0x70e7, + 0x70e8,0x70e9,0x70ea,0x70eb,0x70ec,0x70ed,0x70ee,0x70ef, + 0x70f0,0x70f1,0x70f2,0x70f3,0x70f4,0x70f5,0x70f6,0x70f7, + 0x70f8,0x70f9,0x70fa,0x70fb,0x70fc,0x70fd,0x70fe,0x70ff, + 0x7100,0x7101,0x7102,0x7103,0x7104,0x7105,0x7106,0x7107, + 0x7108,0x7109,0x710a,0x710b,0x710c,0x710d,0x710e,0x710f, + 0x7110,0x7111,0x7112,0x7113,0x7114,0x7115,0x7116,0x7117, + 0x7118,0x7119,0x711a,0x711b,0x711c,0x711d,0x711e,0x711f, + 0x7120,0x7121,0x7122,0x7123,0x7124,0x7125,0x7126,0x7127, + 0x7128,0x7129,0x712a,0x712b,0x712c,0x712d,0x712e,0x712f, + 0x7130,0x7131,0x7132,0x7133,0x7134,0x7135,0x7136,0x7137, + 0x7138,0x7139,0x713a,0x713b,0x713c,0x713d,0x713e,0x713f, + 0x7140,0x7141,0x7142,0x7143,0x7144,0x7145,0x7146,0x7147, + 0x7148,0x7149,0x714a,0x714b,0x714c,0x714d,0x714e,0x714f, + 0x7150,0x7151,0x7152,0x7153,0x7154,0x7155,0x7156,0x7157, + 0x7158,0x7159,0x715a,0x715b,0x715c,0x715d,0x715e,0x715f, + 0x7160,0x7161,0x7162,0x7163,0x7164,0x7165,0x7166,0x7167, + 0x7168,0x7169,0x716a,0x716b,0x716c,0x716d,0x716e,0x716f, + 0x7170,0x7171,0x7172,0x7173,0x7174,0x7175,0x7176,0x7177, + 0x7178,0x7179,0x717a,0x717b,0x717c,0x717d,0x717e,0x717f, + 0x7180,0x7181,0x7182,0x7183,0x7184,0x7185,0x7186,0x7187, + 0x7188,0x7189,0x718a,0x718b,0x718c,0x718d,0x718e,0x718f, + 0x7190,0x7191,0x7192,0x7193,0x7194,0x7195,0x7196,0x7197, + 0x7198,0x7199,0x719a,0x719b,0x719c,0x719d,0x719e,0x719f, + 0x71a0,0x71a1,0x71a2,0x71a3,0x71a4,0x71a5,0x71a6,0x71a7, + 0x71a8,0x71a9,0x71aa,0x71ab,0x71ac,0x71ad,0x71ae,0x71af, + 0x71b0,0x71b1,0x71b2,0x71b3,0x71b4,0x71b5,0x71b6,0x71b7, + 0x71b8,0x71b9,0x71ba,0x71bb,0x71bc,0x71bd,0x71be,0x71bf, + 0x71c0,0x71c1,0x71c2,0x71c3,0x71c4,0x71c5,0x71c6,0x71c7, + 0x71c8,0x71c9,0x71ca,0x71cb,0x71cc,0x71cd,0x71ce,0x71cf, + 0x71d0,0x71d1,0x71d2,0x71d3,0x71d4,0x71d5,0x71d6,0x71d7, + 0x71d8,0x71d9,0x71da,0x71db,0x71dc,0x71dd,0x71de,0x71df, + 0x71e0,0x71e1,0x71e2,0x71e3,0x71e4,0x71e5,0x71e6,0x71e7, + 0x71e8,0x71e9,0x71ea,0x71eb,0x71ec,0x71ed,0x71ee,0x71ef, + 0x71f0,0x71f1,0x71f2,0x71f3,0x71f4,0x71f5,0x71f6,0x71f7, + 0x71f8,0x71f9,0x71fa,0x71fb,0x71fc,0x71fd,0x71fe,0x71ff, + 0x7200,0x7201,0x7202,0x7203,0x7204,0x7205,0x7206,0x7207, + 0x7208,0x7209,0x720a,0x720b,0x720c,0x720d,0x720e,0x720f, + 0x7210,0x7211,0x7212,0x7213,0x7214,0x7215,0x7216,0x7217, + 0x7218,0x7219,0x721a,0x721b,0x721c,0x721d,0x721e,0x721f, + 0x7220,0x7221,0x7222,0x7223,0x7224,0x7225,0x7226,0x7227, + 0x7228,0x7229,0x722a,0x722b,0x722c,0x722d,0x722e,0x722f, + 0x7230,0x7231,0x7232,0x7233,0x7234,0x7235,0x7236,0x7237, + 0x7238,0x7239,0x723a,0x723b,0x723c,0x723d,0x723e,0x723f, + 0x7240,0x7241,0x7242,0x7243,0x7244,0x7245,0x7246,0x7247, + 0x7248,0x7249,0x724a,0x724b,0x724c,0x724d,0x724e,0x724f, + 0x7250,0x7251,0x7252,0x7253,0x7254,0x7255,0x7256,0x7257, + 0x7258,0x7259,0x725a,0x725b,0x725c,0x725d,0x725e,0x725f, + 0x7260,0x7261,0x7262,0x7263,0x7264,0x7265,0x7266,0x7267, + 0x7268,0x7269,0x726a,0x726b,0x726c,0x726d,0x726e,0x726f, + 0x7270,0x7271,0x7272,0x7273,0x7274,0x7275,0x7276,0x7277, + 0x7278,0x7279,0x727a,0x727b,0x727c,0x727d,0x727e,0x727f, + 0x7280,0x7281,0x7282,0x7283,0x7284,0x7285,0x7286,0x7287, + 0x7288,0x7289,0x728a,0x728b,0x728c,0x728d,0x728e,0x728f, + 0x7290,0x7291,0x7292,0x7293,0x7294,0x7295,0x7296,0x7297, + 0x7298,0x7299,0x729a,0x729b,0x729c,0x729d,0x729e,0x729f, + 0x72a0,0x72a1,0x72a2,0x72a3,0x72a4,0x72a5,0x72a6,0x72a7, + 0x72a8,0x72a9,0x72aa,0x72ab,0x72ac,0x72ad,0x72ae,0x72af, + 0x72b0,0x72b1,0x72b2,0x72b3,0x72b4,0x72b5,0x72b6,0x72b7, + 0x72b8,0x72b9,0x72ba,0x72bb,0x72bc,0x72bd,0x72be,0x72bf, + 0x72c0,0x72c1,0x72c2,0x72c3,0x72c4,0x72c5,0x72c6,0x72c7, + 0x72c8,0x72c9,0x72ca,0x72cb,0x72cc,0x72cd,0x72ce,0x72cf, + 0x72d0,0x72d1,0x72d2,0x72d3,0x72d4,0x72d5,0x72d6,0x72d7, + 0x72d8,0x72d9,0x72da,0x72db,0x72dc,0x72dd,0x72de,0x72df, + 0x72e0,0x72e1,0x72e2,0x72e3,0x72e4,0x72e5,0x72e6,0x72e7, + 0x72e8,0x72e9,0x72ea,0x72eb,0x72ec,0x72ed,0x72ee,0x72ef, + 0x72f0,0x72f1,0x72f2,0x72f3,0x72f4,0x72f5,0x72f6,0x72f7, + 0x72f8,0x72f9,0x72fa,0x72fb,0x72fc,0x72fd,0x72fe,0x72ff, + 0x7300,0x7301,0x7302,0x7303,0x7304,0x7305,0x7306,0x7307, + 0x7308,0x7309,0x730a,0x730b,0x730c,0x730d,0x730e,0x730f, + 0x7310,0x7311,0x7312,0x7313,0x7314,0x7315,0x7316,0x7317, + 0x7318,0x7319,0x731a,0x731b,0x731c,0x731d,0x731e,0x731f, + 0x7320,0x7321,0x7322,0x7323,0x7324,0x7325,0x7326,0x7327, + 0x7328,0x7329,0x732a,0x732b,0x732c,0x732d,0x732e,0x732f, + 0x7330,0x7331,0x7332,0x7333,0x7334,0x7335,0x7336,0x7337, + 0x7338,0x7339,0x733a,0x733b,0x733c,0x733d,0x733e,0x733f, + 0x7340,0x7341,0x7342,0x7343,0x7344,0x7345,0x7346,0x7347, + 0x7348,0x7349,0x734a,0x734b,0x734c,0x734d,0x734e,0x734f, + 0x7350,0x7351,0x7352,0x7353,0x7354,0x7355,0x7356,0x7357, + 0x7358,0x7359,0x735a,0x735b,0x735c,0x735d,0x735e,0x735f, + 0x7360,0x7361,0x7362,0x7363,0x7364,0x7365,0x7366,0x7367, + 0x7368,0x7369,0x736a,0x736b,0x736c,0x736d,0x736e,0x736f, + 0x7370,0x7371,0x7372,0x7373,0x7374,0x7375,0x7376,0x7377, + 0x7378,0x7379,0x737a,0x737b,0x737c,0x737d,0x737e,0x737f, + 0x7380,0x7381,0x7382,0x7383,0x7384,0x7385,0x7386,0x7387, + 0x7388,0x7389,0x738a,0x738b,0x738c,0x738d,0x738e,0x738f, + 0x7390,0x7391,0x7392,0x7393,0x7394,0x7395,0x7396,0x7397, + 0x7398,0x7399,0x739a,0x739b,0x739c,0x739d,0x739e,0x739f, + 0x73a0,0x73a1,0x73a2,0x73a3,0x73a4,0x73a5,0x73a6,0x73a7, + 0x73a8,0x73a9,0x73aa,0x73ab,0x73ac,0x73ad,0x73ae,0x73af, + 0x73b0,0x73b1,0x73b2,0x73b3,0x73b4,0x73b5,0x73b6,0x73b7, + 0x73b8,0x73b9,0x73ba,0x73bb,0x73bc,0x73bd,0x73be,0x73bf, + 0x73c0,0x73c1,0x73c2,0x73c3,0x73c4,0x73c5,0x73c6,0x73c7, + 0x73c8,0x73c9,0x73ca,0x73cb,0x73cc,0x73cd,0x73ce,0x73cf, + 0x73d0,0x73d1,0x73d2,0x73d3,0x73d4,0x73d5,0x73d6,0x73d7, + 0x73d8,0x73d9,0x73da,0x73db,0x73dc,0x73dd,0x73de,0x73df, + 0x73e0,0x73e1,0x73e2,0x73e3,0x73e4,0x73e5,0x73e6,0x73e7, + 0x73e8,0x73e9,0x73ea,0x73eb,0x73ec,0x73ed,0x73ee,0x73ef, + 0x73f0,0x73f1,0x73f2,0x73f3,0x73f4,0x73f5,0x73f6,0x73f7, + 0x73f8,0x73f9,0x73fa,0x73fb,0x73fc,0x73fd,0x73fe,0x73ff, + 0x7400,0x7401,0x7402,0x7403,0x7404,0x7405,0x7406,0x7407, + 0x7408,0x7409,0x740a,0x740b,0x740c,0x740d,0x740e,0x740f, + 0x7410,0x7411,0x7412,0x7413,0x7414,0x7415,0x7416,0x7417, + 0x7418,0x7419,0x741a,0x741b,0x741c,0x741d,0x741e,0x741f, + 0x7420,0x7421,0x7422,0x7423,0x7424,0x7425,0x7426,0x7427, + 0x7428,0x7429,0x742a,0x742b,0x742c,0x742d,0x742e,0x742f, + 0x7430,0x7431,0x7432,0x7433,0x7434,0x7435,0x7436,0x7437, + 0x7438,0x7439,0x743a,0x743b,0x743c,0x743d,0x743e,0x743f, + 0x7440,0x7441,0x7442,0x7443,0x7444,0x7445,0x7446,0x7447, + 0x7448,0x7449,0x744a,0x744b,0x744c,0x744d,0x744e,0x744f, + 0x7450,0x7451,0x7452,0x7453,0x7454,0x7455,0x7456,0x7457, + 0x7458,0x7459,0x745a,0x745b,0x745c,0x745d,0x745e,0x745f, + 0x7460,0x7461,0x7462,0x7463,0x7464,0x7465,0x7466,0x7467, + 0x7468,0x7469,0x746a,0x746b,0x746c,0x746d,0x746e,0x746f, + 0x7470,0x7471,0x7472,0x7473,0x7474,0x7475,0x7476,0x7477, + 0x7478,0x7479,0x747a,0x747b,0x747c,0x747d,0x747e,0x747f, + 0x7480,0x7481,0x7482,0x7483,0x7484,0x7485,0x7486,0x7487, + 0x7488,0x7489,0x748a,0x748b,0x748c,0x748d,0x748e,0x748f, + 0x7490,0x7491,0x7492,0x7493,0x7494,0x7495,0x7496,0x7497, + 0x7498,0x7499,0x749a,0x749b,0x749c,0x749d,0x749e,0x749f, + 0x74a0,0x74a1,0x74a2,0x74a3,0x74a4,0x74a5,0x74a6,0x74a7, + 0x74a8,0x74a9,0x74aa,0x74ab,0x74ac,0x74ad,0x74ae,0x74af, + 0x74b0,0x74b1,0x74b2,0x74b3,0x74b4,0x74b5,0x74b6,0x74b7, + 0x74b8,0x74b9,0x74ba,0x74bb,0x74bc,0x74bd,0x74be,0x74bf, + 0x74c0,0x74c1,0x74c2,0x74c3,0x74c4,0x74c5,0x74c6,0x74c7, + 0x74c8,0x74c9,0x74ca,0x74cb,0x74cc,0x74cd,0x74ce,0x74cf, + 0x74d0,0x74d1,0x74d2,0x74d3,0x74d4,0x74d5,0x74d6,0x74d7, + 0x74d8,0x74d9,0x74da,0x74db,0x74dc,0x74dd,0x74de,0x74df, + 0x74e0,0x74e1,0x74e2,0x74e3,0x74e4,0x74e5,0x74e6,0x74e7, + 0x74e8,0x74e9,0x74ea,0x74eb,0x74ec,0x74ed,0x74ee,0x74ef, + 0x74f0,0x74f1,0x74f2,0x74f3,0x74f4,0x74f5,0x74f6,0x74f7, + 0x74f8,0x74f9,0x74fa,0x74fb,0x74fc,0x74fd,0x74fe,0x74ff, + 0x7500,0x7501,0x7502,0x7503,0x7504,0x7505,0x7506,0x7507, + 0x7508,0x7509,0x750a,0x750b,0x750c,0x750d,0x750e,0x750f, + 0x7510,0x7511,0x7512,0x7513,0x7514,0x7515,0x7516,0x7517, + 0x7518,0x7519,0x751a,0x751b,0x751c,0x751d,0x751e,0x751f, + 0x7520,0x7521,0x7522,0x7523,0x7524,0x7525,0x7526,0x7527, + 0x7528,0x7529,0x752a,0x752b,0x752c,0x752d,0x752e,0x752f, + 0x7530,0x7531,0x7532,0x7533,0x7534,0x7535,0x7536,0x7537, + 0x7538,0x7539,0x753a,0x753b,0x753c,0x753d,0x753e,0x753f, + 0x7540,0x7541,0x7542,0x7543,0x7544,0x7545,0x7546,0x7547, + 0x7548,0x7549,0x754a,0x754b,0x754c,0x754d,0x754e,0x754f, + 0x7550,0x7551,0x7552,0x7553,0x7554,0x7555,0x7556,0x7557, + 0x7558,0x7559,0x755a,0x755b,0x755c,0x755d,0x755e,0x755f, + 0x7560,0x7561,0x7562,0x7563,0x7564,0x7565,0x7566,0x7567, + 0x7568,0x7569,0x756a,0x756b,0x756c,0x756d,0x756e,0x756f, + 0x7570,0x7571,0x7572,0x7573,0x7574,0x7575,0x7576,0x7577, + 0x7578,0x7579,0x757a,0x757b,0x757c,0x757d,0x757e,0x757f, + 0x7580,0x7581,0x7582,0x7583,0x7584,0x7585,0x7586,0x7587, + 0x7588,0x7589,0x758a,0x758b,0x758c,0x758d,0x758e,0x758f, + 0x7590,0x7591,0x7592,0x7593,0x7594,0x7595,0x7596,0x7597, + 0x7598,0x7599,0x759a,0x759b,0x759c,0x759d,0x759e,0x759f, + 0x75a0,0x75a1,0x75a2,0x75a3,0x75a4,0x75a5,0x75a6,0x75a7, + 0x75a8,0x75a9,0x75aa,0x75ab,0x75ac,0x75ad,0x75ae,0x75af, + 0x75b0,0x75b1,0x75b2,0x75b3,0x75b4,0x75b5,0x75b6,0x75b7, + 0x75b8,0x75b9,0x75ba,0x75bb,0x75bc,0x75bd,0x75be,0x75bf, + 0x75c0,0x75c1,0x75c2,0x75c3,0x75c4,0x75c5,0x75c6,0x75c7, + 0x75c8,0x75c9,0x75ca,0x75cb,0x75cc,0x75cd,0x75ce,0x75cf, + 0x75d0,0x75d1,0x75d2,0x75d3,0x75d4,0x75d5,0x75d6,0x75d7, + 0x75d8,0x75d9,0x75da,0x75db,0x75dc,0x75dd,0x75de,0x75df, + 0x75e0,0x75e1,0x75e2,0x75e3,0x75e4,0x75e5,0x75e6,0x75e7, + 0x75e8,0x75e9,0x75ea,0x75eb,0x75ec,0x75ed,0x75ee,0x75ef, + 0x75f0,0x75f1,0x75f2,0x75f3,0x75f4,0x75f5,0x75f6,0x75f7, + 0x75f8,0x75f9,0x75fa,0x75fb,0x75fc,0x75fd,0x75fe,0x75ff, + 0x7600,0x7601,0x7602,0x7603,0x7604,0x7605,0x7606,0x7607, + 0x7608,0x7609,0x760a,0x760b,0x760c,0x760d,0x760e,0x760f, + 0x7610,0x7611,0x7612,0x7613,0x7614,0x7615,0x7616,0x7617, + 0x7618,0x7619,0x761a,0x761b,0x761c,0x761d,0x761e,0x761f, + 0x7620,0x7621,0x7622,0x7623,0x7624,0x7625,0x7626,0x7627, + 0x7628,0x7629,0x762a,0x762b,0x762c,0x762d,0x762e,0x762f, + 0x7630,0x7631,0x7632,0x7633,0x7634,0x7635,0x7636,0x7637, + 0x7638,0x7639,0x763a,0x763b,0x763c,0x763d,0x763e,0x763f, + 0x7640,0x7641,0x7642,0x7643,0x7644,0x7645,0x7646,0x7647, + 0x7648,0x7649,0x764a,0x764b,0x764c,0x764d,0x764e,0x764f, + 0x7650,0x7651,0x7652,0x7653,0x7654,0x7655,0x7656,0x7657, + 0x7658,0x7659,0x765a,0x765b,0x765c,0x765d,0x765e,0x765f, + 0x7660,0x7661,0x7662,0x7663,0x7664,0x7665,0x7666,0x7667, + 0x7668,0x7669,0x766a,0x766b,0x766c,0x766d,0x766e,0x766f, + 0x7670,0x7671,0x7672,0x7673,0x7674,0x7675,0x7676,0x7677, + 0x7678,0x7679,0x767a,0x767b,0x767c,0x767d,0x767e,0x767f, + 0x7680,0x7681,0x7682,0x7683,0x7684,0x7685,0x7686,0x7687, + 0x7688,0x7689,0x768a,0x768b,0x768c,0x768d,0x768e,0x768f, + 0x7690,0x7691,0x7692,0x7693,0x7694,0x7695,0x7696,0x7697, + 0x7698,0x7699,0x769a,0x769b,0x769c,0x769d,0x769e,0x769f, + 0x76a0,0x76a1,0x76a2,0x76a3,0x76a4,0x76a5,0x76a6,0x76a7, + 0x76a8,0x76a9,0x76aa,0x76ab,0x76ac,0x76ad,0x76ae,0x76af, + 0x76b0,0x76b1,0x76b2,0x76b3,0x76b4,0x76b5,0x76b6,0x76b7, + 0x76b8,0x76b9,0x76ba,0x76bb,0x76bc,0x76bd,0x76be,0x76bf, + 0x76c0,0x76c1,0x76c2,0x76c3,0x76c4,0x76c5,0x76c6,0x76c7, + 0x76c8,0x76c9,0x76ca,0x76cb,0x76cc,0x76cd,0x76ce,0x76cf, + 0x76d0,0x76d1,0x76d2,0x76d3,0x76d4,0x76d5,0x76d6,0x76d7, + 0x76d8,0x76d9,0x76da,0x76db,0x76dc,0x76dd,0x76de,0x76df, + 0x76e0,0x76e1,0x76e2,0x76e3,0x76e4,0x76e5,0x76e6,0x76e7, + 0x76e8,0x76e9,0x76ea,0x76eb,0x76ec,0x76ed,0x76ee,0x76ef, + 0x76f0,0x76f1,0x76f2,0x76f3,0x76f4,0x76f5,0x76f6,0x76f7, + 0x76f8,0x76f9,0x76fa,0x76fb,0x76fc,0x76fd,0x76fe,0x76ff, + 0x7700,0x7701,0x7702,0x7703,0x7704,0x7705,0x7706,0x7707, + 0x7708,0x7709,0x770a,0x770b,0x770c,0x770d,0x770e,0x770f, + 0x7710,0x7711,0x7712,0x7713,0x7714,0x7715,0x7716,0x7717, + 0x7718,0x7719,0x771a,0x771b,0x771c,0x771d,0x771e,0x771f, + 0x7720,0x7721,0x7722,0x7723,0x7724,0x7725,0x7726,0x7727, + 0x7728,0x7729,0x772a,0x772b,0x772c,0x772d,0x772e,0x772f, + 0x7730,0x7731,0x7732,0x7733,0x7734,0x7735,0x7736,0x7737, + 0x7738,0x7739,0x773a,0x773b,0x773c,0x773d,0x773e,0x773f, + 0x7740,0x7741,0x7742,0x7743,0x7744,0x7745,0x7746,0x7747, + 0x7748,0x7749,0x774a,0x774b,0x774c,0x774d,0x774e,0x774f, + 0x7750,0x7751,0x7752,0x7753,0x7754,0x7755,0x7756,0x7757, + 0x7758,0x7759,0x775a,0x775b,0x775c,0x775d,0x775e,0x775f, + 0x7760,0x7761,0x7762,0x7763,0x7764,0x7765,0x7766,0x7767, + 0x7768,0x7769,0x776a,0x776b,0x776c,0x776d,0x776e,0x776f, + 0x7770,0x7771,0x7772,0x7773,0x7774,0x7775,0x7776,0x7777, + 0x7778,0x7779,0x777a,0x777b,0x777c,0x777d,0x777e,0x777f, + 0x7780,0x7781,0x7782,0x7783,0x7784,0x7785,0x7786,0x7787, + 0x7788,0x7789,0x778a,0x778b,0x778c,0x778d,0x778e,0x778f, + 0x7790,0x7791,0x7792,0x7793,0x7794,0x7795,0x7796,0x7797, + 0x7798,0x7799,0x779a,0x779b,0x779c,0x779d,0x779e,0x779f, + 0x77a0,0x77a1,0x77a2,0x77a3,0x77a4,0x77a5,0x77a6,0x77a7, + 0x77a8,0x77a9,0x77aa,0x77ab,0x77ac,0x77ad,0x77ae,0x77af, + 0x77b0,0x77b1,0x77b2,0x77b3,0x77b4,0x77b5,0x77b6,0x77b7, + 0x77b8,0x77b9,0x77ba,0x77bb,0x77bc,0x77bd,0x77be,0x77bf, + 0x77c0,0x77c1,0x77c2,0x77c3,0x77c4,0x77c5,0x77c6,0x77c7, + 0x77c8,0x77c9,0x77ca,0x77cb,0x77cc,0x77cd,0x77ce,0x77cf, + 0x77d0,0x77d1,0x77d2,0x77d3,0x77d4,0x77d5,0x77d6,0x77d7, + 0x77d8,0x77d9,0x77da,0x77db,0x77dc,0x77dd,0x77de,0x77df, + 0x77e0,0x77e1,0x77e2,0x77e3,0x77e4,0x77e5,0x77e6,0x77e7, + 0x77e8,0x77e9,0x77ea,0x77eb,0x77ec,0x77ed,0x77ee,0x77ef, + 0x77f0,0x77f1,0x77f2,0x77f3,0x77f4,0x77f5,0x77f6,0x77f7, + 0x77f8,0x77f9,0x77fa,0x77fb,0x77fc,0x77fd,0x77fe,0x77ff, + 0x7800,0x7801,0x7802,0x7803,0x7804,0x7805,0x7806,0x7807, + 0x7808,0x7809,0x780a,0x780b,0x780c,0x780d,0x780e,0x780f, + 0x7810,0x7811,0x7812,0x7813,0x7814,0x7815,0x7816,0x7817, + 0x7818,0x7819,0x781a,0x781b,0x781c,0x781d,0x781e,0x781f, + 0x7820,0x7821,0x7822,0x7823,0x7824,0x7825,0x7826,0x7827, + 0x7828,0x7829,0x782a,0x782b,0x782c,0x782d,0x782e,0x782f, + 0x7830,0x7831,0x7832,0x7833,0x7834,0x7835,0x7836,0x7837, + 0x7838,0x7839,0x783a,0x783b,0x783c,0x783d,0x783e,0x783f, + 0x7840,0x7841,0x7842,0x7843,0x7844,0x7845,0x7846,0x7847, + 0x7848,0x7849,0x784a,0x784b,0x784c,0x784d,0x784e,0x784f, + 0x7850,0x7851,0x7852,0x7853,0x7854,0x7855,0x7856,0x7857, + 0x7858,0x7859,0x785a,0x785b,0x785c,0x785d,0x785e,0x785f, + 0x7860,0x7861,0x7862,0x7863,0x7864,0x7865,0x7866,0x7867, + 0x7868,0x7869,0x786a,0x786b,0x786c,0x786d,0x786e,0x786f, + 0x7870,0x7871,0x7872,0x7873,0x7874,0x7875,0x7876,0x7877, + 0x7878,0x7879,0x787a,0x787b,0x787c,0x787d,0x787e,0x787f, + 0x7880,0x7881,0x7882,0x7883,0x7884,0x7885,0x7886,0x7887, + 0x7888,0x7889,0x788a,0x788b,0x788c,0x788d,0x788e,0x788f, + 0x7890,0x7891,0x7892,0x7893,0x7894,0x7895,0x7896,0x7897, + 0x7898,0x7899,0x789a,0x789b,0x789c,0x789d,0x789e,0x789f, + 0x78a0,0x78a1,0x78a2,0x78a3,0x78a4,0x78a5,0x78a6,0x78a7, + 0x78a8,0x78a9,0x78aa,0x78ab,0x78ac,0x78ad,0x78ae,0x78af, + 0x78b0,0x78b1,0x78b2,0x78b3,0x78b4,0x78b5,0x78b6,0x78b7, + 0x78b8,0x78b9,0x78ba,0x78bb,0x78bc,0x78bd,0x78be,0x78bf, + 0x78c0,0x78c1,0x78c2,0x78c3,0x78c4,0x78c5,0x78c6,0x78c7, + 0x78c8,0x78c9,0x78ca,0x78cb,0x78cc,0x78cd,0x78ce,0x78cf, + 0x78d0,0x78d1,0x78d2,0x78d3,0x78d4,0x78d5,0x78d6,0x78d7, + 0x78d8,0x78d9,0x78da,0x78db,0x78dc,0x78dd,0x78de,0x78df, + 0x78e0,0x78e1,0x78e2,0x78e3,0x78e4,0x78e5,0x78e6,0x78e7, + 0x78e8,0x78e9,0x78ea,0x78eb,0x78ec,0x78ed,0x78ee,0x78ef, + 0x78f0,0x78f1,0x78f2,0x78f3,0x78f4,0x78f5,0x78f6,0x78f7, + 0x78f8,0x78f9,0x78fa,0x78fb,0x78fc,0x78fd,0x78fe,0x78ff, + 0x7900,0x7901,0x7902,0x7903,0x7904,0x7905,0x7906,0x7907, + 0x7908,0x7909,0x790a,0x790b,0x790c,0x790d,0x790e,0x790f, + 0x7910,0x7911,0x7912,0x7913,0x7914,0x7915,0x7916,0x7917, + 0x7918,0x7919,0x791a,0x791b,0x791c,0x791d,0x791e,0x791f, + 0x7920,0x7921,0x7922,0x7923,0x7924,0x7925,0x7926,0x7927, + 0x7928,0x7929,0x792a,0x792b,0x792c,0x792d,0x792e,0x792f, + 0x7930,0x7931,0x7932,0x7933,0x7934,0x7935,0x7936,0x7937, + 0x7938,0x7939,0x793a,0x793b,0x793c,0x793d,0x793e,0x793f, + 0x7940,0x7941,0x7942,0x7943,0x7944,0x7945,0x7946,0x7947, + 0x7948,0x7949,0x794a,0x794b,0x794c,0x794d,0x794e,0x794f, + 0x7950,0x7951,0x7952,0x7953,0x7954,0x7955,0x7956,0x7957, + 0x7958,0x7959,0x795a,0x795b,0x795c,0x795d,0x795e,0x795f, + 0x7960,0x7961,0x7962,0x7963,0x7964,0x7965,0x7966,0x7967, + 0x7968,0x7969,0x796a,0x796b,0x796c,0x796d,0x796e,0x796f, + 0x7970,0x7971,0x7972,0x7973,0x7974,0x7975,0x7976,0x7977, + 0x7978,0x7979,0x797a,0x797b,0x797c,0x797d,0x797e,0x797f, + 0x7980,0x7981,0x7982,0x7983,0x7984,0x7985,0x7986,0x7987, + 0x7988,0x7989,0x798a,0x798b,0x798c,0x798d,0x798e,0x798f, + 0x7990,0x7991,0x7992,0x7993,0x7994,0x7995,0x7996,0x7997, + 0x7998,0x7999,0x799a,0x799b,0x799c,0x799d,0x799e,0x799f, + 0x79a0,0x79a1,0x79a2,0x79a3,0x79a4,0x79a5,0x79a6,0x79a7, + 0x79a8,0x79a9,0x79aa,0x79ab,0x79ac,0x79ad,0x79ae,0x79af, + 0x79b0,0x79b1,0x79b2,0x79b3,0x79b4,0x79b5,0x79b6,0x79b7, + 0x79b8,0x79b9,0x79ba,0x79bb,0x79bc,0x79bd,0x79be,0x79bf, + 0x79c0,0x79c1,0x79c2,0x79c3,0x79c4,0x79c5,0x79c6,0x79c7, + 0x79c8,0x79c9,0x79ca,0x79cb,0x79cc,0x79cd,0x79ce,0x79cf, + 0x79d0,0x79d1,0x79d2,0x79d3,0x79d4,0x79d5,0x79d6,0x79d7, + 0x79d8,0x79d9,0x79da,0x79db,0x79dc,0x79dd,0x79de,0x79df, + 0x79e0,0x79e1,0x79e2,0x79e3,0x79e4,0x79e5,0x79e6,0x79e7, + 0x79e8,0x79e9,0x79ea,0x79eb,0x79ec,0x79ed,0x79ee,0x79ef, + 0x79f0,0x79f1,0x79f2,0x79f3,0x79f4,0x79f5,0x79f6,0x79f7, + 0x79f8,0x79f9,0x79fa,0x79fb,0x79fc,0x79fd,0x79fe,0x79ff, + 0x7a00,0x7a01,0x7a02,0x7a03,0x7a04,0x7a05,0x7a06,0x7a07, + 0x7a08,0x7a09,0x7a0a,0x7a0b,0x7a0c,0x7a0d,0x7a0e,0x7a0f, + 0x7a10,0x7a11,0x7a12,0x7a13,0x7a14,0x7a15,0x7a16,0x7a17, + 0x7a18,0x7a19,0x7a1a,0x7a1b,0x7a1c,0x7a1d,0x7a1e,0x7a1f, + 0x7a20,0x7a21,0x7a22,0x7a23,0x7a24,0x7a25,0x7a26,0x7a27, + 0x7a28,0x7a29,0x7a2a,0x7a2b,0x7a2c,0x7a2d,0x7a2e,0x7a2f, + 0x7a30,0x7a31,0x7a32,0x7a33,0x7a34,0x7a35,0x7a36,0x7a37, + 0x7a38,0x7a39,0x7a3a,0x7a3b,0x7a3c,0x7a3d,0x7a3e,0x7a3f, + 0x7a40,0x7a41,0x7a42,0x7a43,0x7a44,0x7a45,0x7a46,0x7a47, + 0x7a48,0x7a49,0x7a4a,0x7a4b,0x7a4c,0x7a4d,0x7a4e,0x7a4f, + 0x7a50,0x7a51,0x7a52,0x7a53,0x7a54,0x7a55,0x7a56,0x7a57, + 0x7a58,0x7a59,0x7a5a,0x7a5b,0x7a5c,0x7a5d,0x7a5e,0x7a5f, + 0x7a60,0x7a61,0x7a62,0x7a63,0x7a64,0x7a65,0x7a66,0x7a67, + 0x7a68,0x7a69,0x7a6a,0x7a6b,0x7a6c,0x7a6d,0x7a6e,0x7a6f, + 0x7a70,0x7a71,0x7a72,0x7a73,0x7a74,0x7a75,0x7a76,0x7a77, + 0x7a78,0x7a79,0x7a7a,0x7a7b,0x7a7c,0x7a7d,0x7a7e,0x7a7f, + 0x7a80,0x7a81,0x7a82,0x7a83,0x7a84,0x7a85,0x7a86,0x7a87, + 0x7a88,0x7a89,0x7a8a,0x7a8b,0x7a8c,0x7a8d,0x7a8e,0x7a8f, + 0x7a90,0x7a91,0x7a92,0x7a93,0x7a94,0x7a95,0x7a96,0x7a97, + 0x7a98,0x7a99,0x7a9a,0x7a9b,0x7a9c,0x7a9d,0x7a9e,0x7a9f, + 0x7aa0,0x7aa1,0x7aa2,0x7aa3,0x7aa4,0x7aa5,0x7aa6,0x7aa7, + 0x7aa8,0x7aa9,0x7aaa,0x7aab,0x7aac,0x7aad,0x7aae,0x7aaf, + 0x7ab0,0x7ab1,0x7ab2,0x7ab3,0x7ab4,0x7ab5,0x7ab6,0x7ab7, + 0x7ab8,0x7ab9,0x7aba,0x7abb,0x7abc,0x7abd,0x7abe,0x7abf, + 0x7ac0,0x7ac1,0x7ac2,0x7ac3,0x7ac4,0x7ac5,0x7ac6,0x7ac7, + 0x7ac8,0x7ac9,0x7aca,0x7acb,0x7acc,0x7acd,0x7ace,0x7acf, + 0x7ad0,0x7ad1,0x7ad2,0x7ad3,0x7ad4,0x7ad5,0x7ad6,0x7ad7, + 0x7ad8,0x7ad9,0x7ada,0x7adb,0x7adc,0x7add,0x7ade,0x7adf, + 0x7ae0,0x7ae1,0x7ae2,0x7ae3,0x7ae4,0x7ae5,0x7ae6,0x7ae7, + 0x7ae8,0x7ae9,0x7aea,0x7aeb,0x7aec,0x7aed,0x7aee,0x7aef, + 0x7af0,0x7af1,0x7af2,0x7af3,0x7af4,0x7af5,0x7af6,0x7af7, + 0x7af8,0x7af9,0x7afa,0x7afb,0x7afc,0x7afd,0x7afe,0x7aff, + 0x7b00,0x7b01,0x7b02,0x7b03,0x7b04,0x7b05,0x7b06,0x7b07, + 0x7b08,0x7b09,0x7b0a,0x7b0b,0x7b0c,0x7b0d,0x7b0e,0x7b0f, + 0x7b10,0x7b11,0x7b12,0x7b13,0x7b14,0x7b15,0x7b16,0x7b17, + 0x7b18,0x7b19,0x7b1a,0x7b1b,0x7b1c,0x7b1d,0x7b1e,0x7b1f, + 0x7b20,0x7b21,0x7b22,0x7b23,0x7b24,0x7b25,0x7b26,0x7b27, + 0x7b28,0x7b29,0x7b2a,0x7b2b,0x7b2c,0x7b2d,0x7b2e,0x7b2f, + 0x7b30,0x7b31,0x7b32,0x7b33,0x7b34,0x7b35,0x7b36,0x7b37, + 0x7b38,0x7b39,0x7b3a,0x7b3b,0x7b3c,0x7b3d,0x7b3e,0x7b3f, + 0x7b40,0x7b41,0x7b42,0x7b43,0x7b44,0x7b45,0x7b46,0x7b47, + 0x7b48,0x7b49,0x7b4a,0x7b4b,0x7b4c,0x7b4d,0x7b4e,0x7b4f, + 0x7b50,0x7b51,0x7b52,0x7b53,0x7b54,0x7b55,0x7b56,0x7b57, + 0x7b58,0x7b59,0x7b5a,0x7b5b,0x7b5c,0x7b5d,0x7b5e,0x7b5f, + 0x7b60,0x7b61,0x7b62,0x7b63,0x7b64,0x7b65,0x7b66,0x7b67, + 0x7b68,0x7b69,0x7b6a,0x7b6b,0x7b6c,0x7b6d,0x7b6e,0x7b6f, + 0x7b70,0x7b71,0x7b72,0x7b73,0x7b74,0x7b75,0x7b76,0x7b77, + 0x7b78,0x7b79,0x7b7a,0x7b7b,0x7b7c,0x7b7d,0x7b7e,0x7b7f, + 0x7b80,0x7b81,0x7b82,0x7b83,0x7b84,0x7b85,0x7b86,0x7b87, + 0x7b88,0x7b89,0x7b8a,0x7b8b,0x7b8c,0x7b8d,0x7b8e,0x7b8f, + 0x7b90,0x7b91,0x7b92,0x7b93,0x7b94,0x7b95,0x7b96,0x7b97, + 0x7b98,0x7b99,0x7b9a,0x7b9b,0x7b9c,0x7b9d,0x7b9e,0x7b9f, + 0x7ba0,0x7ba1,0x7ba2,0x7ba3,0x7ba4,0x7ba5,0x7ba6,0x7ba7, + 0x7ba8,0x7ba9,0x7baa,0x7bab,0x7bac,0x7bad,0x7bae,0x7baf, + 0x7bb0,0x7bb1,0x7bb2,0x7bb3,0x7bb4,0x7bb5,0x7bb6,0x7bb7, + 0x7bb8,0x7bb9,0x7bba,0x7bbb,0x7bbc,0x7bbd,0x7bbe,0x7bbf, + 0x7bc0,0x7bc1,0x7bc2,0x7bc3,0x7bc4,0x7bc5,0x7bc6,0x7bc7, + 0x7bc8,0x7bc9,0x7bca,0x7bcb,0x7bcc,0x7bcd,0x7bce,0x7bcf, + 0x7bd0,0x7bd1,0x7bd2,0x7bd3,0x7bd4,0x7bd5,0x7bd6,0x7bd7, + 0x7bd8,0x7bd9,0x7bda,0x7bdb,0x7bdc,0x7bdd,0x7bde,0x7bdf, + 0x7be0,0x7be1,0x7be2,0x7be3,0x7be4,0x7be5,0x7be6,0x7be7, + 0x7be8,0x7be9,0x7bea,0x7beb,0x7bec,0x7bed,0x7bee,0x7bef, + 0x7bf0,0x7bf1,0x7bf2,0x7bf3,0x7bf4,0x7bf5,0x7bf6,0x7bf7, + 0x7bf8,0x7bf9,0x7bfa,0x7bfb,0x7bfc,0x7bfd,0x7bfe,0x7bff, + 0x7c00,0x7c01,0x7c02,0x7c03,0x7c04,0x7c05,0x7c06,0x7c07, + 0x7c08,0x7c09,0x7c0a,0x7c0b,0x7c0c,0x7c0d,0x7c0e,0x7c0f, + 0x7c10,0x7c11,0x7c12,0x7c13,0x7c14,0x7c15,0x7c16,0x7c17, + 0x7c18,0x7c19,0x7c1a,0x7c1b,0x7c1c,0x7c1d,0x7c1e,0x7c1f, + 0x7c20,0x7c21,0x7c22,0x7c23,0x7c24,0x7c25,0x7c26,0x7c27, + 0x7c28,0x7c29,0x7c2a,0x7c2b,0x7c2c,0x7c2d,0x7c2e,0x7c2f, + 0x7c30,0x7c31,0x7c32,0x7c33,0x7c34,0x7c35,0x7c36,0x7c37, + 0x7c38,0x7c39,0x7c3a,0x7c3b,0x7c3c,0x7c3d,0x7c3e,0x7c3f, + 0x7c40,0x7c41,0x7c42,0x7c43,0x7c44,0x7c45,0x7c46,0x7c47, + 0x7c48,0x7c49,0x7c4a,0x7c4b,0x7c4c,0x7c4d,0x7c4e,0x7c4f, + 0x7c50,0x7c51,0x7c52,0x7c53,0x7c54,0x7c55,0x7c56,0x7c57, + 0x7c58,0x7c59,0x7c5a,0x7c5b,0x7c5c,0x7c5d,0x7c5e,0x7c5f, + 0x7c60,0x7c61,0x7c62,0x7c63,0x7c64,0x7c65,0x7c66,0x7c67, + 0x7c68,0x7c69,0x7c6a,0x7c6b,0x7c6c,0x7c6d,0x7c6e,0x7c6f, + 0x7c70,0x7c71,0x7c72,0x7c73,0x7c74,0x7c75,0x7c76,0x7c77, + 0x7c78,0x7c79,0x7c7a,0x7c7b,0x7c7c,0x7c7d,0x7c7e,0x7c7f, + 0x7c80,0x7c81,0x7c82,0x7c83,0x7c84,0x7c85,0x7c86,0x7c87, + 0x7c88,0x7c89,0x7c8a,0x7c8b,0x7c8c,0x7c8d,0x7c8e,0x7c8f, + 0x7c90,0x7c91,0x7c92,0x7c93,0x7c94,0x7c95,0x7c96,0x7c97, + 0x7c98,0x7c99,0x7c9a,0x7c9b,0x7c9c,0x7c9d,0x7c9e,0x7c9f, + 0x7ca0,0x7ca1,0x7ca2,0x7ca3,0x7ca4,0x7ca5,0x7ca6,0x7ca7, + 0x7ca8,0x7ca9,0x7caa,0x7cab,0x7cac,0x7cad,0x7cae,0x7caf, + 0x7cb0,0x7cb1,0x7cb2,0x7cb3,0x7cb4,0x7cb5,0x7cb6,0x7cb7, + 0x7cb8,0x7cb9,0x7cba,0x7cbb,0x7cbc,0x7cbd,0x7cbe,0x7cbf, + 0x7cc0,0x7cc1,0x7cc2,0x7cc3,0x7cc4,0x7cc5,0x7cc6,0x7cc7, + 0x7cc8,0x7cc9,0x7cca,0x7ccb,0x7ccc,0x7ccd,0x7cce,0x7ccf, + 0x7cd0,0x7cd1,0x7cd2,0x7cd3,0x7cd4,0x7cd5,0x7cd6,0x7cd7, + 0x7cd8,0x7cd9,0x7cda,0x7cdb,0x7cdc,0x7cdd,0x7cde,0x7cdf, + 0x7ce0,0x7ce1,0x7ce2,0x7ce3,0x7ce4,0x7ce5,0x7ce6,0x7ce7, + 0x7ce8,0x7ce9,0x7cea,0x7ceb,0x7cec,0x7ced,0x7cee,0x7cef, + 0x7cf0,0x7cf1,0x7cf2,0x7cf3,0x7cf4,0x7cf5,0x7cf6,0x7cf7, + 0x7cf8,0x7cf9,0x7cfa,0x7cfb,0x7cfc,0x7cfd,0x7cfe,0x7cff, + 0x7d00,0x7d01,0x7d02,0x7d03,0x7d04,0x7d05,0x7d06,0x7d07, + 0x7d08,0x7d09,0x7d0a,0x7d0b,0x7d0c,0x7d0d,0x7d0e,0x7d0f, + 0x7d10,0x7d11,0x7d12,0x7d13,0x7d14,0x7d15,0x7d16,0x7d17, + 0x7d18,0x7d19,0x7d1a,0x7d1b,0x7d1c,0x7d1d,0x7d1e,0x7d1f, + 0x7d20,0x7d21,0x7d22,0x7d23,0x7d24,0x7d25,0x7d26,0x7d27, + 0x7d28,0x7d29,0x7d2a,0x7d2b,0x7d2c,0x7d2d,0x7d2e,0x7d2f, + 0x7d30,0x7d31,0x7d32,0x7d33,0x7d34,0x7d35,0x7d36,0x7d37, + 0x7d38,0x7d39,0x7d3a,0x7d3b,0x7d3c,0x7d3d,0x7d3e,0x7d3f, + 0x7d40,0x7d41,0x7d42,0x7d43,0x7d44,0x7d45,0x7d46,0x7d47, + 0x7d48,0x7d49,0x7d4a,0x7d4b,0x7d4c,0x7d4d,0x7d4e,0x7d4f, + 0x7d50,0x7d51,0x7d52,0x7d53,0x7d54,0x7d55,0x7d56,0x7d57, + 0x7d58,0x7d59,0x7d5a,0x7d5b,0x7d5c,0x7d5d,0x7d5e,0x7d5f, + 0x7d60,0x7d61,0x7d62,0x7d63,0x7d64,0x7d65,0x7d66,0x7d67, + 0x7d68,0x7d69,0x7d6a,0x7d6b,0x7d6c,0x7d6d,0x7d6e,0x7d6f, + 0x7d70,0x7d71,0x7d72,0x7d73,0x7d74,0x7d75,0x7d76,0x7d77, + 0x7d78,0x7d79,0x7d7a,0x7d7b,0x7d7c,0x7d7d,0x7d7e,0x7d7f, + 0x7d80,0x7d81,0x7d82,0x7d83,0x7d84,0x7d85,0x7d86,0x7d87, + 0x7d88,0x7d89,0x7d8a,0x7d8b,0x7d8c,0x7d8d,0x7d8e,0x7d8f, + 0x7d90,0x7d91,0x7d92,0x7d93,0x7d94,0x7d95,0x7d96,0x7d97, + 0x7d98,0x7d99,0x7d9a,0x7d9b,0x7d9c,0x7d9d,0x7d9e,0x7d9f, + 0x7da0,0x7da1,0x7da2,0x7da3,0x7da4,0x7da5,0x7da6,0x7da7, + 0x7da8,0x7da9,0x7daa,0x7dab,0x7dac,0x7dad,0x7dae,0x7daf, + 0x7db0,0x7db1,0x7db2,0x7db3,0x7db4,0x7db5,0x7db6,0x7db7, + 0x7db8,0x7db9,0x7dba,0x7dbb,0x7dbc,0x7dbd,0x7dbe,0x7dbf, + 0x7dc0,0x7dc1,0x7dc2,0x7dc3,0x7dc4,0x7dc5,0x7dc6,0x7dc7, + 0x7dc8,0x7dc9,0x7dca,0x7dcb,0x7dcc,0x7dcd,0x7dce,0x7dcf, + 0x7dd0,0x7dd1,0x7dd2,0x7dd3,0x7dd4,0x7dd5,0x7dd6,0x7dd7, + 0x7dd8,0x7dd9,0x7dda,0x7ddb,0x7ddc,0x7ddd,0x7dde,0x7ddf, + 0x7de0,0x7de1,0x7de2,0x7de3,0x7de4,0x7de5,0x7de6,0x7de7, + 0x7de8,0x7de9,0x7dea,0x7deb,0x7dec,0x7ded,0x7dee,0x7def, + 0x7df0,0x7df1,0x7df2,0x7df3,0x7df4,0x7df5,0x7df6,0x7df7, + 0x7df8,0x7df9,0x7dfa,0x7dfb,0x7dfc,0x7dfd,0x7dfe,0x7dff, + 0x7e00,0x7e01,0x7e02,0x7e03,0x7e04,0x7e05,0x7e06,0x7e07, + 0x7e08,0x7e09,0x7e0a,0x7e0b,0x7e0c,0x7e0d,0x7e0e,0x7e0f, + 0x7e10,0x7e11,0x7e12,0x7e13,0x7e14,0x7e15,0x7e16,0x7e17, + 0x7e18,0x7e19,0x7e1a,0x7e1b,0x7e1c,0x7e1d,0x7e1e,0x7e1f, + 0x7e20,0x7e21,0x7e22,0x7e23,0x7e24,0x7e25,0x7e26,0x7e27, + 0x7e28,0x7e29,0x7e2a,0x7e2b,0x7e2c,0x7e2d,0x7e2e,0x7e2f, + 0x7e30,0x7e31,0x7e32,0x7e33,0x7e34,0x7e35,0x7e36,0x7e37, + 0x7e38,0x7e39,0x7e3a,0x7e3b,0x7e3c,0x7e3d,0x7e3e,0x7e3f, + 0x7e40,0x7e41,0x7e42,0x7e43,0x7e44,0x7e45,0x7e46,0x7e47, + 0x7e48,0x7e49,0x7e4a,0x7e4b,0x7e4c,0x7e4d,0x7e4e,0x7e4f, + 0x7e50,0x7e51,0x7e52,0x7e53,0x7e54,0x7e55,0x7e56,0x7e57, + 0x7e58,0x7e59,0x7e5a,0x7e5b,0x7e5c,0x7e5d,0x7e5e,0x7e5f, + 0x7e60,0x7e61,0x7e62,0x7e63,0x7e64,0x7e65,0x7e66,0x7e67, + 0x7e68,0x7e69,0x7e6a,0x7e6b,0x7e6c,0x7e6d,0x7e6e,0x7e6f, + 0x7e70,0x7e71,0x7e72,0x7e73,0x7e74,0x7e75,0x7e76,0x7e77, + 0x7e78,0x7e79,0x7e7a,0x7e7b,0x7e7c,0x7e7d,0x7e7e,0x7e7f, + 0x7e80,0x7e81,0x7e82,0x7e83,0x7e84,0x7e85,0x7e86,0x7e87, + 0x7e88,0x7e89,0x7e8a,0x7e8b,0x7e8c,0x7e8d,0x7e8e,0x7e8f, + 0x7e90,0x7e91,0x7e92,0x7e93,0x7e94,0x7e95,0x7e96,0x7e97, + 0x7e98,0x7e99,0x7e9a,0x7e9b,0x7e9c,0x7e9d,0x7e9e,0x7e9f, + 0x7ea0,0x7ea1,0x7ea2,0x7ea3,0x7ea4,0x7ea5,0x7ea6,0x7ea7, + 0x7ea8,0x7ea9,0x7eaa,0x7eab,0x7eac,0x7ead,0x7eae,0x7eaf, + 0x7eb0,0x7eb1,0x7eb2,0x7eb3,0x7eb4,0x7eb5,0x7eb6,0x7eb7, + 0x7eb8,0x7eb9,0x7eba,0x7ebb,0x7ebc,0x7ebd,0x7ebe,0x7ebf, + 0x7ec0,0x7ec1,0x7ec2,0x7ec3,0x7ec4,0x7ec5,0x7ec6,0x7ec7, + 0x7ec8,0x7ec9,0x7eca,0x7ecb,0x7ecc,0x7ecd,0x7ece,0x7ecf, + 0x7ed0,0x7ed1,0x7ed2,0x7ed3,0x7ed4,0x7ed5,0x7ed6,0x7ed7, + 0x7ed8,0x7ed9,0x7eda,0x7edb,0x7edc,0x7edd,0x7ede,0x7edf, + 0x7ee0,0x7ee1,0x7ee2,0x7ee3,0x7ee4,0x7ee5,0x7ee6,0x7ee7, + 0x7ee8,0x7ee9,0x7eea,0x7eeb,0x7eec,0x7eed,0x7eee,0x7eef, + 0x7ef0,0x7ef1,0x7ef2,0x7ef3,0x7ef4,0x7ef5,0x7ef6,0x7ef7, + 0x7ef8,0x7ef9,0x7efa,0x7efb,0x7efc,0x7efd,0x7efe,0x7eff, + 0x7f00,0x7f01,0x7f02,0x7f03,0x7f04,0x7f05,0x7f06,0x7f07, + 0x7f08,0x7f09,0x7f0a,0x7f0b,0x7f0c,0x7f0d,0x7f0e,0x7f0f, + 0x7f10,0x7f11,0x7f12,0x7f13,0x7f14,0x7f15,0x7f16,0x7f17, + 0x7f18,0x7f19,0x7f1a,0x7f1b,0x7f1c,0x7f1d,0x7f1e,0x7f1f, + 0x7f20,0x7f21,0x7f22,0x7f23,0x7f24,0x7f25,0x7f26,0x7f27, + 0x7f28,0x7f29,0x7f2a,0x7f2b,0x7f2c,0x7f2d,0x7f2e,0x7f2f, + 0x7f30,0x7f31,0x7f32,0x7f33,0x7f34,0x7f35,0x7f36,0x7f37, + 0x7f38,0x7f39,0x7f3a,0x7f3b,0x7f3c,0x7f3d,0x7f3e,0x7f3f, + 0x7f40,0x7f41,0x7f42,0x7f43,0x7f44,0x7f45,0x7f46,0x7f47, + 0x7f48,0x7f49,0x7f4a,0x7f4b,0x7f4c,0x7f4d,0x7f4e,0x7f4f, + 0x7f50,0x7f51,0x7f52,0x7f53,0x7f54,0x7f55,0x7f56,0x7f57, + 0x7f58,0x7f59,0x7f5a,0x7f5b,0x7f5c,0x7f5d,0x7f5e,0x7f5f, + 0x7f60,0x7f61,0x7f62,0x7f63,0x7f64,0x7f65,0x7f66,0x7f67, + 0x7f68,0x7f69,0x7f6a,0x7f6b,0x7f6c,0x7f6d,0x7f6e,0x7f6f, + 0x7f70,0x7f71,0x7f72,0x7f73,0x7f74,0x7f75,0x7f76,0x7f77, + 0x7f78,0x7f79,0x7f7a,0x7f7b,0x7f7c,0x7f7d,0x7f7e,0x7f7f, + 0x7f80,0x7f81,0x7f82,0x7f83,0x7f84,0x7f85,0x7f86,0x7f87, + 0x7f88,0x7f89,0x7f8a,0x7f8b,0x7f8c,0x7f8d,0x7f8e,0x7f8f, + 0x7f90,0x7f91,0x7f92,0x7f93,0x7f94,0x7f95,0x7f96,0x7f97, + 0x7f98,0x7f99,0x7f9a,0x7f9b,0x7f9c,0x7f9d,0x7f9e,0x7f9f, + 0x7fa0,0x7fa1,0x7fa2,0x7fa3,0x7fa4,0x7fa5,0x7fa6,0x7fa7, + 0x7fa8,0x7fa9,0x7faa,0x7fab,0x7fac,0x7fad,0x7fae,0x7faf, + 0x7fb0,0x7fb1,0x7fb2,0x7fb3,0x7fb4,0x7fb5,0x7fb6,0x7fb7, + 0x7fb8,0x7fb9,0x7fba,0x7fbb,0x7fbc,0x7fbd,0x7fbe,0x7fbf, + 0x7fc0,0x7fc1,0x7fc2,0x7fc3,0x7fc4,0x7fc5,0x7fc6,0x7fc7, + 0x7fc8,0x7fc9,0x7fca,0x7fcb,0x7fcc,0x7fcd,0x7fce,0x7fcf, + 0x7fd0,0x7fd1,0x7fd2,0x7fd3,0x7fd4,0x7fd5,0x7fd6,0x7fd7, + 0x7fd8,0x7fd9,0x7fda,0x7fdb,0x7fdc,0x7fdd,0x7fde,0x7fdf, + 0x7fe0,0x7fe1,0x7fe2,0x7fe3,0x7fe4,0x7fe5,0x7fe6,0x7fe7, + 0x7fe8,0x7fe9,0x7fea,0x7feb,0x7fec,0x7fed,0x7fee,0x7fef, + 0x7ff0,0x7ff1,0x7ff2,0x7ff3,0x7ff4,0x7ff5,0x7ff6,0x7ff7, + 0x7ff8,0x7ff9,0x7ffa,0x7ffb,0x7ffc,0x7ffd,0x7ffe,0x7fff, + 0x8000,0x8001,0x8002,0x8003,0x8004,0x8005,0x8006,0x8007, + 0x8008,0x8009,0x800a,0x800b,0x800c,0x800d,0x800e,0x800f, + 0x8010,0x8011,0x8012,0x8013,0x8014,0x8015,0x8016,0x8017, + 0x8018,0x8019,0x801a,0x801b,0x801c,0x801d,0x801e,0x801f, + 0x8020,0x8021,0x8022,0x8023,0x8024,0x8025,0x8026,0x8027, + 0x8028,0x8029,0x802a,0x802b,0x802c,0x802d,0x802e,0x802f, + 0x8030,0x8031,0x8032,0x8033,0x8034,0x8035,0x8036,0x8037, + 0x8038,0x8039,0x803a,0x803b,0x803c,0x803d,0x803e,0x803f, + 0x8040,0x8041,0x8042,0x8043,0x8044,0x8045,0x8046,0x8047, + 0x8048,0x8049,0x804a,0x804b,0x804c,0x804d,0x804e,0x804f, + 0x8050,0x8051,0x8052,0x8053,0x8054,0x8055,0x8056,0x8057, + 0x8058,0x8059,0x805a,0x805b,0x805c,0x805d,0x805e,0x805f, + 0x8060,0x8061,0x8062,0x8063,0x8064,0x8065,0x8066,0x8067, + 0x8068,0x8069,0x806a,0x806b,0x806c,0x806d,0x806e,0x806f, + 0x8070,0x8071,0x8072,0x8073,0x8074,0x8075,0x8076,0x8077, + 0x8078,0x8079,0x807a,0x807b,0x807c,0x807d,0x807e,0x807f, + 0x8080,0x8081,0x8082,0x8083,0x8084,0x8085,0x8086,0x8087, + 0x8088,0x8089,0x808a,0x808b,0x808c,0x808d,0x808e,0x808f, + 0x8090,0x8091,0x8092,0x8093,0x8094,0x8095,0x8096,0x8097, + 0x8098,0x8099,0x809a,0x809b,0x809c,0x809d,0x809e,0x809f, + 0x80a0,0x80a1,0x80a2,0x80a3,0x80a4,0x80a5,0x80a6,0x80a7, + 0x80a8,0x80a9,0x80aa,0x80ab,0x80ac,0x80ad,0x80ae,0x80af, + 0x80b0,0x80b1,0x80b2,0x80b3,0x80b4,0x80b5,0x80b6,0x80b7, + 0x80b8,0x80b9,0x80ba,0x80bb,0x80bc,0x80bd,0x80be,0x80bf, + 0x80c0,0x80c1,0x80c2,0x80c3,0x80c4,0x80c5,0x80c6,0x80c7, + 0x80c8,0x80c9,0x80ca,0x80cb,0x80cc,0x80cd,0x80ce,0x80cf, + 0x80d0,0x80d1,0x80d2,0x80d3,0x80d4,0x80d5,0x80d6,0x80d7, + 0x80d8,0x80d9,0x80da,0x80db,0x80dc,0x80dd,0x80de,0x80df, + 0x80e0,0x80e1,0x80e2,0x80e3,0x80e4,0x80e5,0x80e6,0x80e7, + 0x80e8,0x80e9,0x80ea,0x80eb,0x80ec,0x80ed,0x80ee,0x80ef, + 0x80f0,0x80f1,0x80f2,0x80f3,0x80f4,0x80f5,0x80f6,0x80f7, + 0x80f8,0x80f9,0x80fa,0x80fb,0x80fc,0x80fd,0x80fe,0x80ff, + 0x8100,0x8101,0x8102,0x8103,0x8104,0x8105,0x8106,0x8107, + 0x8108,0x8109,0x810a,0x810b,0x810c,0x810d,0x810e,0x810f, + 0x8110,0x8111,0x8112,0x8113,0x8114,0x8115,0x8116,0x8117, + 0x8118,0x8119,0x811a,0x811b,0x811c,0x811d,0x811e,0x811f, + 0x8120,0x8121,0x8122,0x8123,0x8124,0x8125,0x8126,0x8127, + 0x8128,0x8129,0x812a,0x812b,0x812c,0x812d,0x812e,0x812f, + 0x8130,0x8131,0x8132,0x8133,0x8134,0x8135,0x8136,0x8137, + 0x8138,0x8139,0x813a,0x813b,0x813c,0x813d,0x813e,0x813f, + 0x8140,0x8141,0x8142,0x8143,0x8144,0x8145,0x8146,0x8147, + 0x8148,0x8149,0x814a,0x814b,0x814c,0x814d,0x814e,0x814f, + 0x8150,0x8151,0x8152,0x8153,0x8154,0x8155,0x8156,0x8157, + 0x8158,0x8159,0x815a,0x815b,0x815c,0x815d,0x815e,0x815f, + 0x8160,0x8161,0x8162,0x8163,0x8164,0x8165,0x8166,0x8167, + 0x8168,0x8169,0x816a,0x816b,0x816c,0x816d,0x816e,0x816f, + 0x8170,0x8171,0x8172,0x8173,0x8174,0x8175,0x8176,0x8177, + 0x8178,0x8179,0x817a,0x817b,0x817c,0x817d,0x817e,0x817f, + 0x8180,0x8181,0x8182,0x8183,0x8184,0x8185,0x8186,0x8187, + 0x8188,0x8189,0x818a,0x818b,0x818c,0x818d,0x818e,0x818f, + 0x8190,0x8191,0x8192,0x8193,0x8194,0x8195,0x8196,0x8197, + 0x8198,0x8199,0x819a,0x819b,0x819c,0x819d,0x819e,0x819f, + 0x81a0,0x81a1,0x81a2,0x81a3,0x81a4,0x81a5,0x81a6,0x81a7, + 0x81a8,0x81a9,0x81aa,0x81ab,0x81ac,0x81ad,0x81ae,0x81af, + 0x81b0,0x81b1,0x81b2,0x81b3,0x81b4,0x81b5,0x81b6,0x81b7, + 0x81b8,0x81b9,0x81ba,0x81bb,0x81bc,0x81bd,0x81be,0x81bf, + 0x81c0,0x81c1,0x81c2,0x81c3,0x81c4,0x81c5,0x81c6,0x81c7, + 0x81c8,0x81c9,0x81ca,0x81cb,0x81cc,0x81cd,0x81ce,0x81cf, + 0x81d0,0x81d1,0x81d2,0x81d3,0x81d4,0x81d5,0x81d6,0x81d7, + 0x81d8,0x81d9,0x81da,0x81db,0x81dc,0x81dd,0x81de,0x81df, + 0x81e0,0x81e1,0x81e2,0x81e3,0x81e4,0x81e5,0x81e6,0x81e7, + 0x81e8,0x81e9,0x81ea,0x81eb,0x81ec,0x81ed,0x81ee,0x81ef, + 0x81f0,0x81f1,0x81f2,0x81f3,0x81f4,0x81f5,0x81f6,0x81f7, + 0x81f8,0x81f9,0x81fa,0x81fb,0x81fc,0x81fd,0x81fe,0x81ff, + 0x8200,0x8201,0x8202,0x8203,0x8204,0x8205,0x8206,0x8207, + 0x8208,0x8209,0x820a,0x820b,0x820c,0x820d,0x820e,0x820f, + 0x8210,0x8211,0x8212,0x8213,0x8214,0x8215,0x8216,0x8217, + 0x8218,0x8219,0x821a,0x821b,0x821c,0x821d,0x821e,0x821f, + 0x8220,0x8221,0x8222,0x8223,0x8224,0x8225,0x8226,0x8227, + 0x8228,0x8229,0x822a,0x822b,0x822c,0x822d,0x822e,0x822f, + 0x8230,0x8231,0x8232,0x8233,0x8234,0x8235,0x8236,0x8237, + 0x8238,0x8239,0x823a,0x823b,0x823c,0x823d,0x823e,0x823f, + 0x8240,0x8241,0x8242,0x8243,0x8244,0x8245,0x8246,0x8247, + 0x8248,0x8249,0x824a,0x824b,0x824c,0x824d,0x824e,0x824f, + 0x8250,0x8251,0x8252,0x8253,0x8254,0x8255,0x8256,0x8257, + 0x8258,0x8259,0x825a,0x825b,0x825c,0x825d,0x825e,0x825f, + 0x8260,0x8261,0x8262,0x8263,0x8264,0x8265,0x8266,0x8267, + 0x8268,0x8269,0x826a,0x826b,0x826c,0x826d,0x826e,0x826f, + 0x8270,0x8271,0x8272,0x8273,0x8274,0x8275,0x8276,0x8277, + 0x8278,0x8279,0x827a,0x827b,0x827c,0x827d,0x827e,0x827f, + 0x8280,0x8281,0x8282,0x8283,0x8284,0x8285,0x8286,0x8287, + 0x8288,0x8289,0x828a,0x828b,0x828c,0x828d,0x828e,0x828f, + 0x8290,0x8291,0x8292,0x8293,0x8294,0x8295,0x8296,0x8297, + 0x8298,0x8299,0x829a,0x829b,0x829c,0x829d,0x829e,0x829f, + 0x82a0,0x82a1,0x82a2,0x82a3,0x82a4,0x82a5,0x82a6,0x82a7, + 0x82a8,0x82a9,0x82aa,0x82ab,0x82ac,0x82ad,0x82ae,0x82af, + 0x82b0,0x82b1,0x82b2,0x82b3,0x82b4,0x82b5,0x82b6,0x82b7, + 0x82b8,0x82b9,0x82ba,0x82bb,0x82bc,0x82bd,0x82be,0x82bf, + 0x82c0,0x82c1,0x82c2,0x82c3,0x82c4,0x82c5,0x82c6,0x82c7, + 0x82c8,0x82c9,0x82ca,0x82cb,0x82cc,0x82cd,0x82ce,0x82cf, + 0x82d0,0x82d1,0x82d2,0x82d3,0x82d4,0x82d5,0x82d6,0x82d7, + 0x82d8,0x82d9,0x82da,0x82db,0x82dc,0x82dd,0x82de,0x82df, + 0x82e0,0x82e1,0x82e2,0x82e3,0x82e4,0x82e5,0x82e6,0x82e7, + 0x82e8,0x82e9,0x82ea,0x82eb,0x82ec,0x82ed,0x82ee,0x82ef, + 0x82f0,0x82f1,0x82f2,0x82f3,0x82f4,0x82f5,0x82f6,0x82f7, + 0x82f8,0x82f9,0x82fa,0x82fb,0x82fc,0x82fd,0x82fe,0x82ff, + 0x8300,0x8301,0x8302,0x8303,0x8304,0x8305,0x8306,0x8307, + 0x8308,0x8309,0x830a,0x830b,0x830c,0x830d,0x830e,0x830f, + 0x8310,0x8311,0x8312,0x8313,0x8314,0x8315,0x8316,0x8317, + 0x8318,0x8319,0x831a,0x831b,0x831c,0x831d,0x831e,0x831f, + 0x8320,0x8321,0x8322,0x8323,0x8324,0x8325,0x8326,0x8327, + 0x8328,0x8329,0x832a,0x832b,0x832c,0x832d,0x832e,0x832f, + 0x8330,0x8331,0x8332,0x8333,0x8334,0x8335,0x8336,0x8337, + 0x8338,0x8339,0x833a,0x833b,0x833c,0x833d,0x833e,0x833f, + 0x8340,0x8341,0x8342,0x8343,0x8344,0x8345,0x8346,0x8347, + 0x8348,0x8349,0x834a,0x834b,0x834c,0x834d,0x834e,0x834f, + 0x8350,0x8351,0x8352,0x8353,0x8354,0x8355,0x8356,0x8357, + 0x8358,0x8359,0x835a,0x835b,0x835c,0x835d,0x835e,0x835f, + 0x8360,0x8361,0x8362,0x8363,0x8364,0x8365,0x8366,0x8367, + 0x8368,0x8369,0x836a,0x836b,0x836c,0x836d,0x836e,0x836f, + 0x8370,0x8371,0x8372,0x8373,0x8374,0x8375,0x8376,0x8377, + 0x8378,0x8379,0x837a,0x837b,0x837c,0x837d,0x837e,0x837f, + 0x8380,0x8381,0x8382,0x8383,0x8384,0x8385,0x8386,0x8387, + 0x8388,0x8389,0x838a,0x838b,0x838c,0x838d,0x838e,0x838f, + 0x8390,0x8391,0x8392,0x8393,0x8394,0x8395,0x8396,0x8397, + 0x8398,0x8399,0x839a,0x839b,0x839c,0x839d,0x839e,0x839f, + 0x83a0,0x83a1,0x83a2,0x83a3,0x83a4,0x83a5,0x83a6,0x83a7, + 0x83a8,0x83a9,0x83aa,0x83ab,0x83ac,0x83ad,0x83ae,0x83af, + 0x83b0,0x83b1,0x83b2,0x83b3,0x83b4,0x83b5,0x83b6,0x83b7, + 0x83b8,0x83b9,0x83ba,0x83bb,0x83bc,0x83bd,0x83be,0x83bf, + 0x83c0,0x83c1,0x83c2,0x83c3,0x83c4,0x83c5,0x83c6,0x83c7, + 0x83c8,0x83c9,0x83ca,0x83cb,0x83cc,0x83cd,0x83ce,0x83cf, + 0x83d0,0x83d1,0x83d2,0x83d3,0x83d4,0x83d5,0x83d6,0x83d7, + 0x83d8,0x83d9,0x83da,0x83db,0x83dc,0x83dd,0x83de,0x83df, + 0x83e0,0x83e1,0x83e2,0x83e3,0x83e4,0x83e5,0x83e6,0x83e7, + 0x83e8,0x83e9,0x83ea,0x83eb,0x83ec,0x83ed,0x83ee,0x83ef, + 0x83f0,0x83f1,0x83f2,0x83f3,0x83f4,0x83f5,0x83f6,0x83f7, + 0x83f8,0x83f9,0x83fa,0x83fb,0x83fc,0x83fd,0x83fe,0x83ff, + 0x8400,0x8401,0x8402,0x8403,0x8404,0x8405,0x8406,0x8407, + 0x8408,0x8409,0x840a,0x840b,0x840c,0x840d,0x840e,0x840f, + 0x8410,0x8411,0x8412,0x8413,0x8414,0x8415,0x8416,0x8417, + 0x8418,0x8419,0x841a,0x841b,0x841c,0x841d,0x841e,0x841f, + 0x8420,0x8421,0x8422,0x8423,0x8424,0x8425,0x8426,0x8427, + 0x8428,0x8429,0x842a,0x842b,0x842c,0x842d,0x842e,0x842f, + 0x8430,0x8431,0x8432,0x8433,0x8434,0x8435,0x8436,0x8437, + 0x8438,0x8439,0x843a,0x843b,0x843c,0x843d,0x843e,0x843f, + 0x8440,0x8441,0x8442,0x8443,0x8444,0x8445,0x8446,0x8447, + 0x8448,0x8449,0x844a,0x844b,0x844c,0x844d,0x844e,0x844f, + 0x8450,0x8451,0x8452,0x8453,0x8454,0x8455,0x8456,0x8457, + 0x8458,0x8459,0x845a,0x845b,0x845c,0x845d,0x845e,0x845f, + 0x8460,0x8461,0x8462,0x8463,0x8464,0x8465,0x8466,0x8467, + 0x8468,0x8469,0x846a,0x846b,0x846c,0x846d,0x846e,0x846f, + 0x8470,0x8471,0x8472,0x8473,0x8474,0x8475,0x8476,0x8477, + 0x8478,0x8479,0x847a,0x847b,0x847c,0x847d,0x847e,0x847f, + 0x8480,0x8481,0x8482,0x8483,0x8484,0x8485,0x8486,0x8487, + 0x8488,0x8489,0x848a,0x848b,0x848c,0x848d,0x848e,0x848f, + 0x8490,0x8491,0x8492,0x8493,0x8494,0x8495,0x8496,0x8497, + 0x8498,0x8499,0x849a,0x849b,0x849c,0x849d,0x849e,0x849f, + 0x84a0,0x84a1,0x84a2,0x84a3,0x84a4,0x84a5,0x84a6,0x84a7, + 0x84a8,0x84a9,0x84aa,0x84ab,0x84ac,0x84ad,0x84ae,0x84af, + 0x84b0,0x84b1,0x84b2,0x84b3,0x84b4,0x84b5,0x84b6,0x84b7, + 0x84b8,0x84b9,0x84ba,0x84bb,0x84bc,0x84bd,0x84be,0x84bf, + 0x84c0,0x84c1,0x84c2,0x84c3,0x84c4,0x84c5,0x84c6,0x84c7, + 0x84c8,0x84c9,0x84ca,0x84cb,0x84cc,0x84cd,0x84ce,0x84cf, + 0x84d0,0x84d1,0x84d2,0x84d3,0x84d4,0x84d5,0x84d6,0x84d7, + 0x84d8,0x84d9,0x84da,0x84db,0x84dc,0x84dd,0x84de,0x84df, + 0x84e0,0x84e1,0x84e2,0x84e3,0x84e4,0x84e5,0x84e6,0x84e7, + 0x84e8,0x84e9,0x84ea,0x84eb,0x84ec,0x84ed,0x84ee,0x84ef, + 0x84f0,0x84f1,0x84f2,0x84f3,0x84f4,0x84f5,0x84f6,0x84f7, + 0x84f8,0x84f9,0x84fa,0x84fb,0x84fc,0x84fd,0x84fe,0x84ff, + 0x8500,0x8501,0x8502,0x8503,0x8504,0x8505,0x8506,0x8507, + 0x8508,0x8509,0x850a,0x850b,0x850c,0x850d,0x850e,0x850f, + 0x8510,0x8511,0x8512,0x8513,0x8514,0x8515,0x8516,0x8517, + 0x8518,0x8519,0x851a,0x851b,0x851c,0x851d,0x851e,0x851f, + 0x8520,0x8521,0x8522,0x8523,0x8524,0x8525,0x8526,0x8527, + 0x8528,0x8529,0x852a,0x852b,0x852c,0x852d,0x852e,0x852f, + 0x8530,0x8531,0x8532,0x8533,0x8534,0x8535,0x8536,0x8537, + 0x8538,0x8539,0x853a,0x853b,0x853c,0x853d,0x853e,0x853f, + 0x8540,0x8541,0x8542,0x8543,0x8544,0x8545,0x8546,0x8547, + 0x8548,0x8549,0x854a,0x854b,0x854c,0x854d,0x854e,0x854f, + 0x8550,0x8551,0x8552,0x8553,0x8554,0x8555,0x8556,0x8557, + 0x8558,0x8559,0x855a,0x855b,0x855c,0x855d,0x855e,0x855f, + 0x8560,0x8561,0x8562,0x8563,0x8564,0x8565,0x8566,0x8567, + 0x8568,0x8569,0x856a,0x856b,0x856c,0x856d,0x856e,0x856f, + 0x8570,0x8571,0x8572,0x8573,0x8574,0x8575,0x8576,0x8577, + 0x8578,0x8579,0x857a,0x857b,0x857c,0x857d,0x857e,0x857f, + 0x8580,0x8581,0x8582,0x8583,0x8584,0x8585,0x8586,0x8587, + 0x8588,0x8589,0x858a,0x858b,0x858c,0x858d,0x858e,0x858f, + 0x8590,0x8591,0x8592,0x8593,0x8594,0x8595,0x8596,0x8597, + 0x8598,0x8599,0x859a,0x859b,0x859c,0x859d,0x859e,0x859f, + 0x85a0,0x85a1,0x85a2,0x85a3,0x85a4,0x85a5,0x85a6,0x85a7, + 0x85a8,0x85a9,0x85aa,0x85ab,0x85ac,0x85ad,0x85ae,0x85af, + 0x85b0,0x85b1,0x85b2,0x85b3,0x85b4,0x85b5,0x85b6,0x85b7, + 0x85b8,0x85b9,0x85ba,0x85bb,0x85bc,0x85bd,0x85be,0x85bf, + 0x85c0,0x85c1,0x85c2,0x85c3,0x85c4,0x85c5,0x85c6,0x85c7, + 0x85c8,0x85c9,0x85ca,0x85cb,0x85cc,0x85cd,0x85ce,0x85cf, + 0x85d0,0x85d1,0x85d2,0x85d3,0x85d4,0x85d5,0x85d6,0x85d7, + 0x85d8,0x85d9,0x85da,0x85db,0x85dc,0x85dd,0x85de,0x85df, + 0x85e0,0x85e1,0x85e2,0x85e3,0x85e4,0x85e5,0x85e6,0x85e7, + 0x85e8,0x85e9,0x85ea,0x85eb,0x85ec,0x85ed,0x85ee,0x85ef, + 0x85f0,0x85f1,0x85f2,0x85f3,0x85f4,0x85f5,0x85f6,0x85f7, + 0x85f8,0x85f9,0x85fa,0x85fb,0x85fc,0x85fd,0x85fe,0x85ff, + 0x8600,0x8601,0x8602,0x8603,0x8604,0x8605,0x8606,0x8607, + 0x8608,0x8609,0x860a,0x860b,0x860c,0x860d,0x860e,0x860f, + 0x8610,0x8611,0x8612,0x8613,0x8614,0x8615,0x8616,0x8617, + 0x8618,0x8619,0x861a,0x861b,0x861c,0x861d,0x861e,0x861f, + 0x8620,0x8621,0x8622,0x8623,0x8624,0x8625,0x8626,0x8627, + 0x8628,0x8629,0x862a,0x862b,0x862c,0x862d,0x862e,0x862f, + 0x8630,0x8631,0x8632,0x8633,0x8634,0x8635,0x8636,0x8637, + 0x8638,0x8639,0x863a,0x863b,0x863c,0x863d,0x863e,0x863f, + 0x8640,0x8641,0x8642,0x8643,0x8644,0x8645,0x8646,0x8647, + 0x8648,0x8649,0x864a,0x864b,0x864c,0x864d,0x864e,0x864f, + 0x8650,0x8651,0x8652,0x8653,0x8654,0x8655,0x8656,0x8657, + 0x8658,0x8659,0x865a,0x865b,0x865c,0x865d,0x865e,0x865f, + 0x8660,0x8661,0x8662,0x8663,0x8664,0x8665,0x8666,0x8667, + 0x8668,0x8669,0x866a,0x866b,0x866c,0x866d,0x866e,0x866f, + 0x8670,0x8671,0x8672,0x8673,0x8674,0x8675,0x8676,0x8677, + 0x8678,0x8679,0x867a,0x867b,0x867c,0x867d,0x867e,0x867f, + 0x8680,0x8681,0x8682,0x8683,0x8684,0x8685,0x8686,0x8687, + 0x8688,0x8689,0x868a,0x868b,0x868c,0x868d,0x868e,0x868f, + 0x8690,0x8691,0x8692,0x8693,0x8694,0x8695,0x8696,0x8697, + 0x8698,0x8699,0x869a,0x869b,0x869c,0x869d,0x869e,0x869f, + 0x86a0,0x86a1,0x86a2,0x86a3,0x86a4,0x86a5,0x86a6,0x86a7, + 0x86a8,0x86a9,0x86aa,0x86ab,0x86ac,0x86ad,0x86ae,0x86af, + 0x86b0,0x86b1,0x86b2,0x86b3,0x86b4,0x86b5,0x86b6,0x86b7, + 0x86b8,0x86b9,0x86ba,0x86bb,0x86bc,0x86bd,0x86be,0x86bf, + 0x86c0,0x86c1,0x86c2,0x86c3,0x86c4,0x86c5,0x86c6,0x86c7, + 0x86c8,0x86c9,0x86ca,0x86cb,0x86cc,0x86cd,0x86ce,0x86cf, + 0x86d0,0x86d1,0x86d2,0x86d3,0x86d4,0x86d5,0x86d6,0x86d7, + 0x86d8,0x86d9,0x86da,0x86db,0x86dc,0x86dd,0x86de,0x86df, + 0x86e0,0x86e1,0x86e2,0x86e3,0x86e4,0x86e5,0x86e6,0x86e7, + 0x86e8,0x86e9,0x86ea,0x86eb,0x86ec,0x86ed,0x86ee,0x86ef, + 0x86f0,0x86f1,0x86f2,0x86f3,0x86f4,0x86f5,0x86f6,0x86f7, + 0x86f8,0x86f9,0x86fa,0x86fb,0x86fc,0x86fd,0x86fe,0x86ff, + 0x8700,0x8701,0x8702,0x8703,0x8704,0x8705,0x8706,0x8707, + 0x8708,0x8709,0x870a,0x870b,0x870c,0x870d,0x870e,0x870f, + 0x8710,0x8711,0x8712,0x8713,0x8714,0x8715,0x8716,0x8717, + 0x8718,0x8719,0x871a,0x871b,0x871c,0x871d,0x871e,0x871f, + 0x8720,0x8721,0x8722,0x8723,0x8724,0x8725,0x8726,0x8727, + 0x8728,0x8729,0x872a,0x872b,0x872c,0x872d,0x872e,0x872f, + 0x8730,0x8731,0x8732,0x8733,0x8734,0x8735,0x8736,0x8737, + 0x8738,0x8739,0x873a,0x873b,0x873c,0x873d,0x873e,0x873f, + 0x8740,0x8741,0x8742,0x8743,0x8744,0x8745,0x8746,0x8747, + 0x8748,0x8749,0x874a,0x874b,0x874c,0x874d,0x874e,0x874f, + 0x8750,0x8751,0x8752,0x8753,0x8754,0x8755,0x8756,0x8757, + 0x8758,0x8759,0x875a,0x875b,0x875c,0x875d,0x875e,0x875f, + 0x8760,0x8761,0x8762,0x8763,0x8764,0x8765,0x8766,0x8767, + 0x8768,0x8769,0x876a,0x876b,0x876c,0x876d,0x876e,0x876f, + 0x8770,0x8771,0x8772,0x8773,0x8774,0x8775,0x8776,0x8777, + 0x8778,0x8779,0x877a,0x877b,0x877c,0x877d,0x877e,0x877f, + 0x8780,0x8781,0x8782,0x8783,0x8784,0x8785,0x8786,0x8787, + 0x8788,0x8789,0x878a,0x878b,0x878c,0x878d,0x878e,0x878f, + 0x8790,0x8791,0x8792,0x8793,0x8794,0x8795,0x8796,0x8797, + 0x8798,0x8799,0x879a,0x879b,0x879c,0x879d,0x879e,0x879f, + 0x87a0,0x87a1,0x87a2,0x87a3,0x87a4,0x87a5,0x87a6,0x87a7, + 0x87a8,0x87a9,0x87aa,0x87ab,0x87ac,0x87ad,0x87ae,0x87af, + 0x87b0,0x87b1,0x87b2,0x87b3,0x87b4,0x87b5,0x87b6,0x87b7, + 0x87b8,0x87b9,0x87ba,0x87bb,0x87bc,0x87bd,0x87be,0x87bf, + 0x87c0,0x87c1,0x87c2,0x87c3,0x87c4,0x87c5,0x87c6,0x87c7, + 0x87c8,0x87c9,0x87ca,0x87cb,0x87cc,0x87cd,0x87ce,0x87cf, + 0x87d0,0x87d1,0x87d2,0x87d3,0x87d4,0x87d5,0x87d6,0x87d7, + 0x87d8,0x87d9,0x87da,0x87db,0x87dc,0x87dd,0x87de,0x87df, + 0x87e0,0x87e1,0x87e2,0x87e3,0x87e4,0x87e5,0x87e6,0x87e7, + 0x87e8,0x87e9,0x87ea,0x87eb,0x87ec,0x87ed,0x87ee,0x87ef, + 0x87f0,0x87f1,0x87f2,0x87f3,0x87f4,0x87f5,0x87f6,0x87f7, + 0x87f8,0x87f9,0x87fa,0x87fb,0x87fc,0x87fd,0x87fe,0x87ff, + 0x8800,0x8801,0x8802,0x8803,0x8804,0x8805,0x8806,0x8807, + 0x8808,0x8809,0x880a,0x880b,0x880c,0x880d,0x880e,0x880f, + 0x8810,0x8811,0x8812,0x8813,0x8814,0x8815,0x8816,0x8817, + 0x8818,0x8819,0x881a,0x881b,0x881c,0x881d,0x881e,0x881f, + 0x8820,0x8821,0x8822,0x8823,0x8824,0x8825,0x8826,0x8827, + 0x8828,0x8829,0x882a,0x882b,0x882c,0x882d,0x882e,0x882f, + 0x8830,0x8831,0x8832,0x8833,0x8834,0x8835,0x8836,0x8837, + 0x8838,0x8839,0x883a,0x883b,0x883c,0x883d,0x883e,0x883f, + 0x8840,0x8841,0x8842,0x8843,0x8844,0x8845,0x8846,0x8847, + 0x8848,0x8849,0x884a,0x884b,0x884c,0x884d,0x884e,0x884f, + 0x8850,0x8851,0x8852,0x8853,0x8854,0x8855,0x8856,0x8857, + 0x8858,0x8859,0x885a,0x885b,0x885c,0x885d,0x885e,0x885f, + 0x8860,0x8861,0x8862,0x8863,0x8864,0x8865,0x8866,0x8867, + 0x8868,0x8869,0x886a,0x886b,0x886c,0x886d,0x886e,0x886f, + 0x8870,0x8871,0x8872,0x8873,0x8874,0x8875,0x8876,0x8877, + 0x8878,0x8879,0x887a,0x887b,0x887c,0x887d,0x887e,0x887f, + 0x8880,0x8881,0x8882,0x8883,0x8884,0x8885,0x8886,0x8887, + 0x8888,0x8889,0x888a,0x888b,0x888c,0x888d,0x888e,0x888f, + 0x8890,0x8891,0x8892,0x8893,0x8894,0x8895,0x8896,0x8897, + 0x8898,0x8899,0x889a,0x889b,0x889c,0x889d,0x889e,0x889f, + 0x88a0,0x88a1,0x88a2,0x88a3,0x88a4,0x88a5,0x88a6,0x88a7, + 0x88a8,0x88a9,0x88aa,0x88ab,0x88ac,0x88ad,0x88ae,0x88af, + 0x88b0,0x88b1,0x88b2,0x88b3,0x88b4,0x88b5,0x88b6,0x88b7, + 0x88b8,0x88b9,0x88ba,0x88bb,0x88bc,0x88bd,0x88be,0x88bf, + 0x88c0,0x88c1,0x88c2,0x88c3,0x88c4,0x88c5,0x88c6,0x88c7, + 0x88c8,0x88c9,0x88ca,0x88cb,0x88cc,0x88cd,0x88ce,0x88cf, + 0x88d0,0x88d1,0x88d2,0x88d3,0x88d4,0x88d5,0x88d6,0x88d7, + 0x88d8,0x88d9,0x88da,0x88db,0x88dc,0x88dd,0x88de,0x88df, + 0x88e0,0x88e1,0x88e2,0x88e3,0x88e4,0x88e5,0x88e6,0x88e7, + 0x88e8,0x88e9,0x88ea,0x88eb,0x88ec,0x88ed,0x88ee,0x88ef, + 0x88f0,0x88f1,0x88f2,0x88f3,0x88f4,0x88f5,0x88f6,0x88f7, + 0x88f8,0x88f9,0x88fa,0x88fb,0x88fc,0x88fd,0x88fe,0x88ff, + 0x8900,0x8901,0x8902,0x8903,0x8904,0x8905,0x8906,0x8907, + 0x8908,0x8909,0x890a,0x890b,0x890c,0x890d,0x890e,0x890f, + 0x8910,0x8911,0x8912,0x8913,0x8914,0x8915,0x8916,0x8917, + 0x8918,0x8919,0x891a,0x891b,0x891c,0x891d,0x891e,0x891f, + 0x8920,0x8921,0x8922,0x8923,0x8924,0x8925,0x8926,0x8927, + 0x8928,0x8929,0x892a,0x892b,0x892c,0x892d,0x892e,0x892f, + 0x8930,0x8931,0x8932,0x8933,0x8934,0x8935,0x8936,0x8937, + 0x8938,0x8939,0x893a,0x893b,0x893c,0x893d,0x893e,0x893f, + 0x8940,0x8941,0x8942,0x8943,0x8944,0x8945,0x8946,0x8947, + 0x8948,0x8949,0x894a,0x894b,0x894c,0x894d,0x894e,0x894f, + 0x8950,0x8951,0x8952,0x8953,0x8954,0x8955,0x8956,0x8957, + 0x8958,0x8959,0x895a,0x895b,0x895c,0x895d,0x895e,0x895f, + 0x8960,0x8961,0x8962,0x8963,0x8964,0x8965,0x8966,0x8967, + 0x8968,0x8969,0x896a,0x896b,0x896c,0x896d,0x896e,0x896f, + 0x8970,0x8971,0x8972,0x8973,0x8974,0x8975,0x8976,0x8977, + 0x8978,0x8979,0x897a,0x897b,0x897c,0x897d,0x897e,0x897f, + 0x8980,0x8981,0x8982,0x8983,0x8984,0x8985,0x8986,0x8987, + 0x8988,0x8989,0x898a,0x898b,0x898c,0x898d,0x898e,0x898f, + 0x8990,0x8991,0x8992,0x8993,0x8994,0x8995,0x8996,0x8997, + 0x8998,0x8999,0x899a,0x899b,0x899c,0x899d,0x899e,0x899f, + 0x89a0,0x89a1,0x89a2,0x89a3,0x89a4,0x89a5,0x89a6,0x89a7, + 0x89a8,0x89a9,0x89aa,0x89ab,0x89ac,0x89ad,0x89ae,0x89af, + 0x89b0,0x89b1,0x89b2,0x89b3,0x89b4,0x89b5,0x89b6,0x89b7, + 0x89b8,0x89b9,0x89ba,0x89bb,0x89bc,0x89bd,0x89be,0x89bf, + 0x89c0,0x89c1,0x89c2,0x89c3,0x89c4,0x89c5,0x89c6,0x89c7, + 0x89c8,0x89c9,0x89ca,0x89cb,0x89cc,0x89cd,0x89ce,0x89cf, + 0x89d0,0x89d1,0x89d2,0x89d3,0x89d4,0x89d5,0x89d6,0x89d7, + 0x89d8,0x89d9,0x89da,0x89db,0x89dc,0x89dd,0x89de,0x89df, + 0x89e0,0x89e1,0x89e2,0x89e3,0x89e4,0x89e5,0x89e6,0x89e7, + 0x89e8,0x89e9,0x89ea,0x89eb,0x89ec,0x89ed,0x89ee,0x89ef, + 0x89f0,0x89f1,0x89f2,0x89f3,0x89f4,0x89f5,0x89f6,0x89f7, + 0x89f8,0x89f9,0x89fa,0x89fb,0x89fc,0x89fd,0x89fe,0x89ff, + 0x8a00,0x8a01,0x8a02,0x8a03,0x8a04,0x8a05,0x8a06,0x8a07, + 0x8a08,0x8a09,0x8a0a,0x8a0b,0x8a0c,0x8a0d,0x8a0e,0x8a0f, + 0x8a10,0x8a11,0x8a12,0x8a13,0x8a14,0x8a15,0x8a16,0x8a17, + 0x8a18,0x8a19,0x8a1a,0x8a1b,0x8a1c,0x8a1d,0x8a1e,0x8a1f, + 0x8a20,0x8a21,0x8a22,0x8a23,0x8a24,0x8a25,0x8a26,0x8a27, + 0x8a28,0x8a29,0x8a2a,0x8a2b,0x8a2c,0x8a2d,0x8a2e,0x8a2f, + 0x8a30,0x8a31,0x8a32,0x8a33,0x8a34,0x8a35,0x8a36,0x8a37, + 0x8a38,0x8a39,0x8a3a,0x8a3b,0x8a3c,0x8a3d,0x8a3e,0x8a3f, + 0x8a40,0x8a41,0x8a42,0x8a43,0x8a44,0x8a45,0x8a46,0x8a47, + 0x8a48,0x8a49,0x8a4a,0x8a4b,0x8a4c,0x8a4d,0x8a4e,0x8a4f, + 0x8a50,0x8a51,0x8a52,0x8a53,0x8a54,0x8a55,0x8a56,0x8a57, + 0x8a58,0x8a59,0x8a5a,0x8a5b,0x8a5c,0x8a5d,0x8a5e,0x8a5f, + 0x8a60,0x8a61,0x8a62,0x8a63,0x8a64,0x8a65,0x8a66,0x8a67, + 0x8a68,0x8a69,0x8a6a,0x8a6b,0x8a6c,0x8a6d,0x8a6e,0x8a6f, + 0x8a70,0x8a71,0x8a72,0x8a73,0x8a74,0x8a75,0x8a76,0x8a77, + 0x8a78,0x8a79,0x8a7a,0x8a7b,0x8a7c,0x8a7d,0x8a7e,0x8a7f, + 0x8a80,0x8a81,0x8a82,0x8a83,0x8a84,0x8a85,0x8a86,0x8a87, + 0x8a88,0x8a89,0x8a8a,0x8a8b,0x8a8c,0x8a8d,0x8a8e,0x8a8f, + 0x8a90,0x8a91,0x8a92,0x8a93,0x8a94,0x8a95,0x8a96,0x8a97, + 0x8a98,0x8a99,0x8a9a,0x8a9b,0x8a9c,0x8a9d,0x8a9e,0x8a9f, + 0x8aa0,0x8aa1,0x8aa2,0x8aa3,0x8aa4,0x8aa5,0x8aa6,0x8aa7, + 0x8aa8,0x8aa9,0x8aaa,0x8aab,0x8aac,0x8aad,0x8aae,0x8aaf, + 0x8ab0,0x8ab1,0x8ab2,0x8ab3,0x8ab4,0x8ab5,0x8ab6,0x8ab7, + 0x8ab8,0x8ab9,0x8aba,0x8abb,0x8abc,0x8abd,0x8abe,0x8abf, + 0x8ac0,0x8ac1,0x8ac2,0x8ac3,0x8ac4,0x8ac5,0x8ac6,0x8ac7, + 0x8ac8,0x8ac9,0x8aca,0x8acb,0x8acc,0x8acd,0x8ace,0x8acf, + 0x8ad0,0x8ad1,0x8ad2,0x8ad3,0x8ad4,0x8ad5,0x8ad6,0x8ad7, + 0x8ad8,0x8ad9,0x8ada,0x8adb,0x8adc,0x8add,0x8ade,0x8adf, + 0x8ae0,0x8ae1,0x8ae2,0x8ae3,0x8ae4,0x8ae5,0x8ae6,0x8ae7, + 0x8ae8,0x8ae9,0x8aea,0x8aeb,0x8aec,0x8aed,0x8aee,0x8aef, + 0x8af0,0x8af1,0x8af2,0x8af3,0x8af4,0x8af5,0x8af6,0x8af7, + 0x8af8,0x8af9,0x8afa,0x8afb,0x8afc,0x8afd,0x8afe,0x8aff, + 0x8b00,0x8b01,0x8b02,0x8b03,0x8b04,0x8b05,0x8b06,0x8b07, + 0x8b08,0x8b09,0x8b0a,0x8b0b,0x8b0c,0x8b0d,0x8b0e,0x8b0f, + 0x8b10,0x8b11,0x8b12,0x8b13,0x8b14,0x8b15,0x8b16,0x8b17, + 0x8b18,0x8b19,0x8b1a,0x8b1b,0x8b1c,0x8b1d,0x8b1e,0x8b1f, + 0x8b20,0x8b21,0x8b22,0x8b23,0x8b24,0x8b25,0x8b26,0x8b27, + 0x8b28,0x8b29,0x8b2a,0x8b2b,0x8b2c,0x8b2d,0x8b2e,0x8b2f, + 0x8b30,0x8b31,0x8b32,0x8b33,0x8b34,0x8b35,0x8b36,0x8b37, + 0x8b38,0x8b39,0x8b3a,0x8b3b,0x8b3c,0x8b3d,0x8b3e,0x8b3f, + 0x8b40,0x8b41,0x8b42,0x8b43,0x8b44,0x8b45,0x8b46,0x8b47, + 0x8b48,0x8b49,0x8b4a,0x8b4b,0x8b4c,0x8b4d,0x8b4e,0x8b4f, + 0x8b50,0x8b51,0x8b52,0x8b53,0x8b54,0x8b55,0x8b56,0x8b57, + 0x8b58,0x8b59,0x8b5a,0x8b5b,0x8b5c,0x8b5d,0x8b5e,0x8b5f, + 0x8b60,0x8b61,0x8b62,0x8b63,0x8b64,0x8b65,0x8b66,0x8b67, + 0x8b68,0x8b69,0x8b6a,0x8b6b,0x8b6c,0x8b6d,0x8b6e,0x8b6f, + 0x8b70,0x8b71,0x8b72,0x8b73,0x8b74,0x8b75,0x8b76,0x8b77, + 0x8b78,0x8b79,0x8b7a,0x8b7b,0x8b7c,0x8b7d,0x8b7e,0x8b7f, + 0x8b80,0x8b81,0x8b82,0x8b83,0x8b84,0x8b85,0x8b86,0x8b87, + 0x8b88,0x8b89,0x8b8a,0x8b8b,0x8b8c,0x8b8d,0x8b8e,0x8b8f, + 0x8b90,0x8b91,0x8b92,0x8b93,0x8b94,0x8b95,0x8b96,0x8b97, + 0x8b98,0x8b99,0x8b9a,0x8b9b,0x8b9c,0x8b9d,0x8b9e,0x8b9f, + 0x8ba0,0x8ba1,0x8ba2,0x8ba3,0x8ba4,0x8ba5,0x8ba6,0x8ba7, + 0x8ba8,0x8ba9,0x8baa,0x8bab,0x8bac,0x8bad,0x8bae,0x8baf, + 0x8bb0,0x8bb1,0x8bb2,0x8bb3,0x8bb4,0x8bb5,0x8bb6,0x8bb7, + 0x8bb8,0x8bb9,0x8bba,0x8bbb,0x8bbc,0x8bbd,0x8bbe,0x8bbf, + 0x8bc0,0x8bc1,0x8bc2,0x8bc3,0x8bc4,0x8bc5,0x8bc6,0x8bc7, + 0x8bc8,0x8bc9,0x8bca,0x8bcb,0x8bcc,0x8bcd,0x8bce,0x8bcf, + 0x8bd0,0x8bd1,0x8bd2,0x8bd3,0x8bd4,0x8bd5,0x8bd6,0x8bd7, + 0x8bd8,0x8bd9,0x8bda,0x8bdb,0x8bdc,0x8bdd,0x8bde,0x8bdf, + 0x8be0,0x8be1,0x8be2,0x8be3,0x8be4,0x8be5,0x8be6,0x8be7, + 0x8be8,0x8be9,0x8bea,0x8beb,0x8bec,0x8bed,0x8bee,0x8bef, + 0x8bf0,0x8bf1,0x8bf2,0x8bf3,0x8bf4,0x8bf5,0x8bf6,0x8bf7, + 0x8bf8,0x8bf9,0x8bfa,0x8bfb,0x8bfc,0x8bfd,0x8bfe,0x8bff, + 0x8c00,0x8c01,0x8c02,0x8c03,0x8c04,0x8c05,0x8c06,0x8c07, + 0x8c08,0x8c09,0x8c0a,0x8c0b,0x8c0c,0x8c0d,0x8c0e,0x8c0f, + 0x8c10,0x8c11,0x8c12,0x8c13,0x8c14,0x8c15,0x8c16,0x8c17, + 0x8c18,0x8c19,0x8c1a,0x8c1b,0x8c1c,0x8c1d,0x8c1e,0x8c1f, + 0x8c20,0x8c21,0x8c22,0x8c23,0x8c24,0x8c25,0x8c26,0x8c27, + 0x8c28,0x8c29,0x8c2a,0x8c2b,0x8c2c,0x8c2d,0x8c2e,0x8c2f, + 0x8c30,0x8c31,0x8c32,0x8c33,0x8c34,0x8c35,0x8c36,0x8c37, + 0x8c38,0x8c39,0x8c3a,0x8c3b,0x8c3c,0x8c3d,0x8c3e,0x8c3f, + 0x8c40,0x8c41,0x8c42,0x8c43,0x8c44,0x8c45,0x8c46,0x8c47, + 0x8c48,0x8c49,0x8c4a,0x8c4b,0x8c4c,0x8c4d,0x8c4e,0x8c4f, + 0x8c50,0x8c51,0x8c52,0x8c53,0x8c54,0x8c55,0x8c56,0x8c57, + 0x8c58,0x8c59,0x8c5a,0x8c5b,0x8c5c,0x8c5d,0x8c5e,0x8c5f, + 0x8c60,0x8c61,0x8c62,0x8c63,0x8c64,0x8c65,0x8c66,0x8c67, + 0x8c68,0x8c69,0x8c6a,0x8c6b,0x8c6c,0x8c6d,0x8c6e,0x8c6f, + 0x8c70,0x8c71,0x8c72,0x8c73,0x8c74,0x8c75,0x8c76,0x8c77, + 0x8c78,0x8c79,0x8c7a,0x8c7b,0x8c7c,0x8c7d,0x8c7e,0x8c7f, + 0x8c80,0x8c81,0x8c82,0x8c83,0x8c84,0x8c85,0x8c86,0x8c87, + 0x8c88,0x8c89,0x8c8a,0x8c8b,0x8c8c,0x8c8d,0x8c8e,0x8c8f, + 0x8c90,0x8c91,0x8c92,0x8c93,0x8c94,0x8c95,0x8c96,0x8c97, + 0x8c98,0x8c99,0x8c9a,0x8c9b,0x8c9c,0x8c9d,0x8c9e,0x8c9f, + 0x8ca0,0x8ca1,0x8ca2,0x8ca3,0x8ca4,0x8ca5,0x8ca6,0x8ca7, + 0x8ca8,0x8ca9,0x8caa,0x8cab,0x8cac,0x8cad,0x8cae,0x8caf, + 0x8cb0,0x8cb1,0x8cb2,0x8cb3,0x8cb4,0x8cb5,0x8cb6,0x8cb7, + 0x8cb8,0x8cb9,0x8cba,0x8cbb,0x8cbc,0x8cbd,0x8cbe,0x8cbf, + 0x8cc0,0x8cc1,0x8cc2,0x8cc3,0x8cc4,0x8cc5,0x8cc6,0x8cc7, + 0x8cc8,0x8cc9,0x8cca,0x8ccb,0x8ccc,0x8ccd,0x8cce,0x8ccf, + 0x8cd0,0x8cd1,0x8cd2,0x8cd3,0x8cd4,0x8cd5,0x8cd6,0x8cd7, + 0x8cd8,0x8cd9,0x8cda,0x8cdb,0x8cdc,0x8cdd,0x8cde,0x8cdf, + 0x8ce0,0x8ce1,0x8ce2,0x8ce3,0x8ce4,0x8ce5,0x8ce6,0x8ce7, + 0x8ce8,0x8ce9,0x8cea,0x8ceb,0x8cec,0x8ced,0x8cee,0x8cef, + 0x8cf0,0x8cf1,0x8cf2,0x8cf3,0x8cf4,0x8cf5,0x8cf6,0x8cf7, + 0x8cf8,0x8cf9,0x8cfa,0x8cfb,0x8cfc,0x8cfd,0x8cfe,0x8cff, + 0x8d00,0x8d01,0x8d02,0x8d03,0x8d04,0x8d05,0x8d06,0x8d07, + 0x8d08,0x8d09,0x8d0a,0x8d0b,0x8d0c,0x8d0d,0x8d0e,0x8d0f, + 0x8d10,0x8d11,0x8d12,0x8d13,0x8d14,0x8d15,0x8d16,0x8d17, + 0x8d18,0x8d19,0x8d1a,0x8d1b,0x8d1c,0x8d1d,0x8d1e,0x8d1f, + 0x8d20,0x8d21,0x8d22,0x8d23,0x8d24,0x8d25,0x8d26,0x8d27, + 0x8d28,0x8d29,0x8d2a,0x8d2b,0x8d2c,0x8d2d,0x8d2e,0x8d2f, + 0x8d30,0x8d31,0x8d32,0x8d33,0x8d34,0x8d35,0x8d36,0x8d37, + 0x8d38,0x8d39,0x8d3a,0x8d3b,0x8d3c,0x8d3d,0x8d3e,0x8d3f, + 0x8d40,0x8d41,0x8d42,0x8d43,0x8d44,0x8d45,0x8d46,0x8d47, + 0x8d48,0x8d49,0x8d4a,0x8d4b,0x8d4c,0x8d4d,0x8d4e,0x8d4f, + 0x8d50,0x8d51,0x8d52,0x8d53,0x8d54,0x8d55,0x8d56,0x8d57, + 0x8d58,0x8d59,0x8d5a,0x8d5b,0x8d5c,0x8d5d,0x8d5e,0x8d5f, + 0x8d60,0x8d61,0x8d62,0x8d63,0x8d64,0x8d65,0x8d66,0x8d67, + 0x8d68,0x8d69,0x8d6a,0x8d6b,0x8d6c,0x8d6d,0x8d6e,0x8d6f, + 0x8d70,0x8d71,0x8d72,0x8d73,0x8d74,0x8d75,0x8d76,0x8d77, + 0x8d78,0x8d79,0x8d7a,0x8d7b,0x8d7c,0x8d7d,0x8d7e,0x8d7f, + 0x8d80,0x8d81,0x8d82,0x8d83,0x8d84,0x8d85,0x8d86,0x8d87, + 0x8d88,0x8d89,0x8d8a,0x8d8b,0x8d8c,0x8d8d,0x8d8e,0x8d8f, + 0x8d90,0x8d91,0x8d92,0x8d93,0x8d94,0x8d95,0x8d96,0x8d97, + 0x8d98,0x8d99,0x8d9a,0x8d9b,0x8d9c,0x8d9d,0x8d9e,0x8d9f, + 0x8da0,0x8da1,0x8da2,0x8da3,0x8da4,0x8da5,0x8da6,0x8da7, + 0x8da8,0x8da9,0x8daa,0x8dab,0x8dac,0x8dad,0x8dae,0x8daf, + 0x8db0,0x8db1,0x8db2,0x8db3,0x8db4,0x8db5,0x8db6,0x8db7, + 0x8db8,0x8db9,0x8dba,0x8dbb,0x8dbc,0x8dbd,0x8dbe,0x8dbf, + 0x8dc0,0x8dc1,0x8dc2,0x8dc3,0x8dc4,0x8dc5,0x8dc6,0x8dc7, + 0x8dc8,0x8dc9,0x8dca,0x8dcb,0x8dcc,0x8dcd,0x8dce,0x8dcf, + 0x8dd0,0x8dd1,0x8dd2,0x8dd3,0x8dd4,0x8dd5,0x8dd6,0x8dd7, + 0x8dd8,0x8dd9,0x8dda,0x8ddb,0x8ddc,0x8ddd,0x8dde,0x8ddf, + 0x8de0,0x8de1,0x8de2,0x8de3,0x8de4,0x8de5,0x8de6,0x8de7, + 0x8de8,0x8de9,0x8dea,0x8deb,0x8dec,0x8ded,0x8dee,0x8def, + 0x8df0,0x8df1,0x8df2,0x8df3,0x8df4,0x8df5,0x8df6,0x8df7, + 0x8df8,0x8df9,0x8dfa,0x8dfb,0x8dfc,0x8dfd,0x8dfe,0x8dff, + 0x8e00,0x8e01,0x8e02,0x8e03,0x8e04,0x8e05,0x8e06,0x8e07, + 0x8e08,0x8e09,0x8e0a,0x8e0b,0x8e0c,0x8e0d,0x8e0e,0x8e0f, + 0x8e10,0x8e11,0x8e12,0x8e13,0x8e14,0x8e15,0x8e16,0x8e17, + 0x8e18,0x8e19,0x8e1a,0x8e1b,0x8e1c,0x8e1d,0x8e1e,0x8e1f, + 0x8e20,0x8e21,0x8e22,0x8e23,0x8e24,0x8e25,0x8e26,0x8e27, + 0x8e28,0x8e29,0x8e2a,0x8e2b,0x8e2c,0x8e2d,0x8e2e,0x8e2f, + 0x8e30,0x8e31,0x8e32,0x8e33,0x8e34,0x8e35,0x8e36,0x8e37, + 0x8e38,0x8e39,0x8e3a,0x8e3b,0x8e3c,0x8e3d,0x8e3e,0x8e3f, + 0x8e40,0x8e41,0x8e42,0x8e43,0x8e44,0x8e45,0x8e46,0x8e47, + 0x8e48,0x8e49,0x8e4a,0x8e4b,0x8e4c,0x8e4d,0x8e4e,0x8e4f, + 0x8e50,0x8e51,0x8e52,0x8e53,0x8e54,0x8e55,0x8e56,0x8e57, + 0x8e58,0x8e59,0x8e5a,0x8e5b,0x8e5c,0x8e5d,0x8e5e,0x8e5f, + 0x8e60,0x8e61,0x8e62,0x8e63,0x8e64,0x8e65,0x8e66,0x8e67, + 0x8e68,0x8e69,0x8e6a,0x8e6b,0x8e6c,0x8e6d,0x8e6e,0x8e6f, + 0x8e70,0x8e71,0x8e72,0x8e73,0x8e74,0x8e75,0x8e76,0x8e77, + 0x8e78,0x8e79,0x8e7a,0x8e7b,0x8e7c,0x8e7d,0x8e7e,0x8e7f, + 0x8e80,0x8e81,0x8e82,0x8e83,0x8e84,0x8e85,0x8e86,0x8e87, + 0x8e88,0x8e89,0x8e8a,0x8e8b,0x8e8c,0x8e8d,0x8e8e,0x8e8f, + 0x8e90,0x8e91,0x8e92,0x8e93,0x8e94,0x8e95,0x8e96,0x8e97, + 0x8e98,0x8e99,0x8e9a,0x8e9b,0x8e9c,0x8e9d,0x8e9e,0x8e9f, + 0x8ea0,0x8ea1,0x8ea2,0x8ea3,0x8ea4,0x8ea5,0x8ea6,0x8ea7, + 0x8ea8,0x8ea9,0x8eaa,0x8eab,0x8eac,0x8ead,0x8eae,0x8eaf, + 0x8eb0,0x8eb1,0x8eb2,0x8eb3,0x8eb4,0x8eb5,0x8eb6,0x8eb7, + 0x8eb8,0x8eb9,0x8eba,0x8ebb,0x8ebc,0x8ebd,0x8ebe,0x8ebf, + 0x8ec0,0x8ec1,0x8ec2,0x8ec3,0x8ec4,0x8ec5,0x8ec6,0x8ec7, + 0x8ec8,0x8ec9,0x8eca,0x8ecb,0x8ecc,0x8ecd,0x8ece,0x8ecf, + 0x8ed0,0x8ed1,0x8ed2,0x8ed3,0x8ed4,0x8ed5,0x8ed6,0x8ed7, + 0x8ed8,0x8ed9,0x8eda,0x8edb,0x8edc,0x8edd,0x8ede,0x8edf, + 0x8ee0,0x8ee1,0x8ee2,0x8ee3,0x8ee4,0x8ee5,0x8ee6,0x8ee7, + 0x8ee8,0x8ee9,0x8eea,0x8eeb,0x8eec,0x8eed,0x8eee,0x8eef, + 0x8ef0,0x8ef1,0x8ef2,0x8ef3,0x8ef4,0x8ef5,0x8ef6,0x8ef7, + 0x8ef8,0x8ef9,0x8efa,0x8efb,0x8efc,0x8efd,0x8efe,0x8eff, + 0x8f00,0x8f01,0x8f02,0x8f03,0x8f04,0x8f05,0x8f06,0x8f07, + 0x8f08,0x8f09,0x8f0a,0x8f0b,0x8f0c,0x8f0d,0x8f0e,0x8f0f, + 0x8f10,0x8f11,0x8f12,0x8f13,0x8f14,0x8f15,0x8f16,0x8f17, + 0x8f18,0x8f19,0x8f1a,0x8f1b,0x8f1c,0x8f1d,0x8f1e,0x8f1f, + 0x8f20,0x8f21,0x8f22,0x8f23,0x8f24,0x8f25,0x8f26,0x8f27, + 0x8f28,0x8f29,0x8f2a,0x8f2b,0x8f2c,0x8f2d,0x8f2e,0x8f2f, + 0x8f30,0x8f31,0x8f32,0x8f33,0x8f34,0x8f35,0x8f36,0x8f37, + 0x8f38,0x8f39,0x8f3a,0x8f3b,0x8f3c,0x8f3d,0x8f3e,0x8f3f, + 0x8f40,0x8f41,0x8f42,0x8f43,0x8f44,0x8f45,0x8f46,0x8f47, + 0x8f48,0x8f49,0x8f4a,0x8f4b,0x8f4c,0x8f4d,0x8f4e,0x8f4f, + 0x8f50,0x8f51,0x8f52,0x8f53,0x8f54,0x8f55,0x8f56,0x8f57, + 0x8f58,0x8f59,0x8f5a,0x8f5b,0x8f5c,0x8f5d,0x8f5e,0x8f5f, + 0x8f60,0x8f61,0x8f62,0x8f63,0x8f64,0x8f65,0x8f66,0x8f67, + 0x8f68,0x8f69,0x8f6a,0x8f6b,0x8f6c,0x8f6d,0x8f6e,0x8f6f, + 0x8f70,0x8f71,0x8f72,0x8f73,0x8f74,0x8f75,0x8f76,0x8f77, + 0x8f78,0x8f79,0x8f7a,0x8f7b,0x8f7c,0x8f7d,0x8f7e,0x8f7f, + 0x8f80,0x8f81,0x8f82,0x8f83,0x8f84,0x8f85,0x8f86,0x8f87, + 0x8f88,0x8f89,0x8f8a,0x8f8b,0x8f8c,0x8f8d,0x8f8e,0x8f8f, + 0x8f90,0x8f91,0x8f92,0x8f93,0x8f94,0x8f95,0x8f96,0x8f97, + 0x8f98,0x8f99,0x8f9a,0x8f9b,0x8f9c,0x8f9d,0x8f9e,0x8f9f, + 0x8fa0,0x8fa1,0x8fa2,0x8fa3,0x8fa4,0x8fa5,0x8fa6,0x8fa7, + 0x8fa8,0x8fa9,0x8faa,0x8fab,0x8fac,0x8fad,0x8fae,0x8faf, + 0x8fb0,0x8fb1,0x8fb2,0x8fb3,0x8fb4,0x8fb5,0x8fb6,0x8fb7, + 0x8fb8,0x8fb9,0x8fba,0x8fbb,0x8fbc,0x8fbd,0x8fbe,0x8fbf, + 0x8fc0,0x8fc1,0x8fc2,0x8fc3,0x8fc4,0x8fc5,0x8fc6,0x8fc7, + 0x8fc8,0x8fc9,0x8fca,0x8fcb,0x8fcc,0x8fcd,0x8fce,0x8fcf, + 0x8fd0,0x8fd1,0x8fd2,0x8fd3,0x8fd4,0x8fd5,0x8fd6,0x8fd7, + 0x8fd8,0x8fd9,0x8fda,0x8fdb,0x8fdc,0x8fdd,0x8fde,0x8fdf, + 0x8fe0,0x8fe1,0x8fe2,0x8fe3,0x8fe4,0x8fe5,0x8fe6,0x8fe7, + 0x8fe8,0x8fe9,0x8fea,0x8feb,0x8fec,0x8fed,0x8fee,0x8fef, + 0x8ff0,0x8ff1,0x8ff2,0x8ff3,0x8ff4,0x8ff5,0x8ff6,0x8ff7, + 0x8ff8,0x8ff9,0x8ffa,0x8ffb,0x8ffc,0x8ffd,0x8ffe,0x8fff, + 0x9000,0x9001,0x9002,0x9003,0x9004,0x9005,0x9006,0x9007, + 0x9008,0x9009,0x900a,0x900b,0x900c,0x900d,0x900e,0x900f, + 0x9010,0x9011,0x9012,0x9013,0x9014,0x9015,0x9016,0x9017, + 0x9018,0x9019,0x901a,0x901b,0x901c,0x901d,0x901e,0x901f, + 0x9020,0x9021,0x9022,0x9023,0x9024,0x9025,0x9026,0x9027, + 0x9028,0x9029,0x902a,0x902b,0x902c,0x902d,0x902e,0x902f, + 0x9030,0x9031,0x9032,0x9033,0x9034,0x9035,0x9036,0x9037, + 0x9038,0x9039,0x903a,0x903b,0x903c,0x903d,0x903e,0x903f, + 0x9040,0x9041,0x9042,0x9043,0x9044,0x9045,0x9046,0x9047, + 0x9048,0x9049,0x904a,0x904b,0x904c,0x904d,0x904e,0x904f, + 0x9050,0x9051,0x9052,0x9053,0x9054,0x9055,0x9056,0x9057, + 0x9058,0x9059,0x905a,0x905b,0x905c,0x905d,0x905e,0x905f, + 0x9060,0x9061,0x9062,0x9063,0x9064,0x9065,0x9066,0x9067, + 0x9068,0x9069,0x906a,0x906b,0x906c,0x906d,0x906e,0x906f, + 0x9070,0x9071,0x9072,0x9073,0x9074,0x9075,0x9076,0x9077, + 0x9078,0x9079,0x907a,0x907b,0x907c,0x907d,0x907e,0x907f, + 0x9080,0x9081,0x9082,0x9083,0x9084,0x9085,0x9086,0x9087, + 0x9088,0x9089,0x908a,0x908b,0x908c,0x908d,0x908e,0x908f, + 0x9090,0x9091,0x9092,0x9093,0x9094,0x9095,0x9096,0x9097, + 0x9098,0x9099,0x909a,0x909b,0x909c,0x909d,0x909e,0x909f, + 0x90a0,0x90a1,0x90a2,0x90a3,0x90a4,0x90a5,0x90a6,0x90a7, + 0x90a8,0x90a9,0x90aa,0x90ab,0x90ac,0x90ad,0x90ae,0x90af, + 0x90b0,0x90b1,0x90b2,0x90b3,0x90b4,0x90b5,0x90b6,0x90b7, + 0x90b8,0x90b9,0x90ba,0x90bb,0x90bc,0x90bd,0x90be,0x90bf, + 0x90c0,0x90c1,0x90c2,0x90c3,0x90c4,0x90c5,0x90c6,0x90c7, + 0x90c8,0x90c9,0x90ca,0x90cb,0x90cc,0x90cd,0x90ce,0x90cf, + 0x90d0,0x90d1,0x90d2,0x90d3,0x90d4,0x90d5,0x90d6,0x90d7, + 0x90d8,0x90d9,0x90da,0x90db,0x90dc,0x90dd,0x90de,0x90df, + 0x90e0,0x90e1,0x90e2,0x90e3,0x90e4,0x90e5,0x90e6,0x90e7, + 0x90e8,0x90e9,0x90ea,0x90eb,0x90ec,0x90ed,0x90ee,0x90ef, + 0x90f0,0x90f1,0x90f2,0x90f3,0x90f4,0x90f5,0x90f6,0x90f7, + 0x90f8,0x90f9,0x90fa,0x90fb,0x90fc,0x90fd,0x90fe,0x90ff, + 0x9100,0x9101,0x9102,0x9103,0x9104,0x9105,0x9106,0x9107, + 0x9108,0x9109,0x910a,0x910b,0x910c,0x910d,0x910e,0x910f, + 0x9110,0x9111,0x9112,0x9113,0x9114,0x9115,0x9116,0x9117, + 0x9118,0x9119,0x911a,0x911b,0x911c,0x911d,0x911e,0x911f, + 0x9120,0x9121,0x9122,0x9123,0x9124,0x9125,0x9126,0x9127, + 0x9128,0x9129,0x912a,0x912b,0x912c,0x912d,0x912e,0x912f, + 0x9130,0x9131,0x9132,0x9133,0x9134,0x9135,0x9136,0x9137, + 0x9138,0x9139,0x913a,0x913b,0x913c,0x913d,0x913e,0x913f, + 0x9140,0x9141,0x9142,0x9143,0x9144,0x9145,0x9146,0x9147, + 0x9148,0x9149,0x914a,0x914b,0x914c,0x914d,0x914e,0x914f, + 0x9150,0x9151,0x9152,0x9153,0x9154,0x9155,0x9156,0x9157, + 0x9158,0x9159,0x915a,0x915b,0x915c,0x915d,0x915e,0x915f, + 0x9160,0x9161,0x9162,0x9163,0x9164,0x9165,0x9166,0x9167, + 0x9168,0x9169,0x916a,0x916b,0x916c,0x916d,0x916e,0x916f, + 0x9170,0x9171,0x9172,0x9173,0x9174,0x9175,0x9176,0x9177, + 0x9178,0x9179,0x917a,0x917b,0x917c,0x917d,0x917e,0x917f, + 0x9180,0x9181,0x9182,0x9183,0x9184,0x9185,0x9186,0x9187, + 0x9188,0x9189,0x918a,0x918b,0x918c,0x918d,0x918e,0x918f, + 0x9190,0x9191,0x9192,0x9193,0x9194,0x9195,0x9196,0x9197, + 0x9198,0x9199,0x919a,0x919b,0x919c,0x919d,0x919e,0x919f, + 0x91a0,0x91a1,0x91a2,0x91a3,0x91a4,0x91a5,0x91a6,0x91a7, + 0x91a8,0x91a9,0x91aa,0x91ab,0x91ac,0x91ad,0x91ae,0x91af, + 0x91b0,0x91b1,0x91b2,0x91b3,0x91b4,0x91b5,0x91b6,0x91b7, + 0x91b8,0x91b9,0x91ba,0x91bb,0x91bc,0x91bd,0x91be,0x91bf, + 0x91c0,0x91c1,0x91c2,0x91c3,0x91c4,0x91c5,0x91c6,0x91c7, + 0x91c8,0x91c9,0x91ca,0x91cb,0x91cc,0x91cd,0x91ce,0x91cf, + 0x91d0,0x91d1,0x91d2,0x91d3,0x91d4,0x91d5,0x91d6,0x91d7, + 0x91d8,0x91d9,0x91da,0x91db,0x91dc,0x91dd,0x91de,0x91df, + 0x91e0,0x91e1,0x91e2,0x91e3,0x91e4,0x91e5,0x91e6,0x91e7, + 0x91e8,0x91e9,0x91ea,0x91eb,0x91ec,0x91ed,0x91ee,0x91ef, + 0x91f0,0x91f1,0x91f2,0x91f3,0x91f4,0x91f5,0x91f6,0x91f7, + 0x91f8,0x91f9,0x91fa,0x91fb,0x91fc,0x91fd,0x91fe,0x91ff, + 0x9200,0x9201,0x9202,0x9203,0x9204,0x9205,0x9206,0x9207, + 0x9208,0x9209,0x920a,0x920b,0x920c,0x920d,0x920e,0x920f, + 0x9210,0x9211,0x9212,0x9213,0x9214,0x9215,0x9216,0x9217, + 0x9218,0x9219,0x921a,0x921b,0x921c,0x921d,0x921e,0x921f, + 0x9220,0x9221,0x9222,0x9223,0x9224,0x9225,0x9226,0x9227, + 0x9228,0x9229,0x922a,0x922b,0x922c,0x922d,0x922e,0x922f, + 0x9230,0x9231,0x9232,0x9233,0x9234,0x9235,0x9236,0x9237, + 0x9238,0x9239,0x923a,0x923b,0x923c,0x923d,0x923e,0x923f, + 0x9240,0x9241,0x9242,0x9243,0x9244,0x9245,0x9246,0x9247, + 0x9248,0x9249,0x924a,0x924b,0x924c,0x924d,0x924e,0x924f, + 0x9250,0x9251,0x9252,0x9253,0x9254,0x9255,0x9256,0x9257, + 0x9258,0x9259,0x925a,0x925b,0x925c,0x925d,0x925e,0x925f, + 0x9260,0x9261,0x9262,0x9263,0x9264,0x9265,0x9266,0x9267, + 0x9268,0x9269,0x926a,0x926b,0x926c,0x926d,0x926e,0x926f, + 0x9270,0x9271,0x9272,0x9273,0x9274,0x9275,0x9276,0x9277, + 0x9278,0x9279,0x927a,0x927b,0x927c,0x927d,0x927e,0x927f, + 0x9280,0x9281,0x9282,0x9283,0x9284,0x9285,0x9286,0x9287, + 0x9288,0x9289,0x928a,0x928b,0x928c,0x928d,0x928e,0x928f, + 0x9290,0x9291,0x9292,0x9293,0x9294,0x9295,0x9296,0x9297, + 0x9298,0x9299,0x929a,0x929b,0x929c,0x929d,0x929e,0x929f, + 0x92a0,0x92a1,0x92a2,0x92a3,0x92a4,0x92a5,0x92a6,0x92a7, + 0x92a8,0x92a9,0x92aa,0x92ab,0x92ac,0x92ad,0x92ae,0x92af, + 0x92b0,0x92b1,0x92b2,0x92b3,0x92b4,0x92b5,0x92b6,0x92b7, + 0x92b8,0x92b9,0x92ba,0x92bb,0x92bc,0x92bd,0x92be,0x92bf, + 0x92c0,0x92c1,0x92c2,0x92c3,0x92c4,0x92c5,0x92c6,0x92c7, + 0x92c8,0x92c9,0x92ca,0x92cb,0x92cc,0x92cd,0x92ce,0x92cf, + 0x92d0,0x92d1,0x92d2,0x92d3,0x92d4,0x92d5,0x92d6,0x92d7, + 0x92d8,0x92d9,0x92da,0x92db,0x92dc,0x92dd,0x92de,0x92df, + 0x92e0,0x92e1,0x92e2,0x92e3,0x92e4,0x92e5,0x92e6,0x92e7, + 0x92e8,0x92e9,0x92ea,0x92eb,0x92ec,0x92ed,0x92ee,0x92ef, + 0x92f0,0x92f1,0x92f2,0x92f3,0x92f4,0x92f5,0x92f6,0x92f7, + 0x92f8,0x92f9,0x92fa,0x92fb,0x92fc,0x92fd,0x92fe,0x92ff, + 0x9300,0x9301,0x9302,0x9303,0x9304,0x9305,0x9306,0x9307, + 0x9308,0x9309,0x930a,0x930b,0x930c,0x930d,0x930e,0x930f, + 0x9310,0x9311,0x9312,0x9313,0x9314,0x9315,0x9316,0x9317, + 0x9318,0x9319,0x931a,0x931b,0x931c,0x931d,0x931e,0x931f, + 0x9320,0x9321,0x9322,0x9323,0x9324,0x9325,0x9326,0x9327, + 0x9328,0x9329,0x932a,0x932b,0x932c,0x932d,0x932e,0x932f, + 0x9330,0x9331,0x9332,0x9333,0x9334,0x9335,0x9336,0x9337, + 0x9338,0x9339,0x933a,0x933b,0x933c,0x933d,0x933e,0x933f, + 0x9340,0x9341,0x9342,0x9343,0x9344,0x9345,0x9346,0x9347, + 0x9348,0x9349,0x934a,0x934b,0x934c,0x934d,0x934e,0x934f, + 0x9350,0x9351,0x9352,0x9353,0x9354,0x9355,0x9356,0x9357, + 0x9358,0x9359,0x935a,0x935b,0x935c,0x935d,0x935e,0x935f, + 0x9360,0x9361,0x9362,0x9363,0x9364,0x9365,0x9366,0x9367, + 0x9368,0x9369,0x936a,0x936b,0x936c,0x936d,0x936e,0x936f, + 0x9370,0x9371,0x9372,0x9373,0x9374,0x9375,0x9376,0x9377, + 0x9378,0x9379,0x937a,0x937b,0x937c,0x937d,0x937e,0x937f, + 0x9380,0x9381,0x9382,0x9383,0x9384,0x9385,0x9386,0x9387, + 0x9388,0x9389,0x938a,0x938b,0x938c,0x938d,0x938e,0x938f, + 0x9390,0x9391,0x9392,0x9393,0x9394,0x9395,0x9396,0x9397, + 0x9398,0x9399,0x939a,0x939b,0x939c,0x939d,0x939e,0x939f, + 0x93a0,0x93a1,0x93a2,0x93a3,0x93a4,0x93a5,0x93a6,0x93a7, + 0x93a8,0x93a9,0x93aa,0x93ab,0x93ac,0x93ad,0x93ae,0x93af, + 0x93b0,0x93b1,0x93b2,0x93b3,0x93b4,0x93b5,0x93b6,0x93b7, + 0x93b8,0x93b9,0x93ba,0x93bb,0x93bc,0x93bd,0x93be,0x93bf, + 0x93c0,0x93c1,0x93c2,0x93c3,0x93c4,0x93c5,0x93c6,0x93c7, + 0x93c8,0x93c9,0x93ca,0x93cb,0x93cc,0x93cd,0x93ce,0x93cf, + 0x93d0,0x93d1,0x93d2,0x93d3,0x93d4,0x93d5,0x93d6,0x93d7, + 0x93d8,0x93d9,0x93da,0x93db,0x93dc,0x93dd,0x93de,0x93df, + 0x93e0,0x93e1,0x93e2,0x93e3,0x93e4,0x93e5,0x93e6,0x93e7, + 0x93e8,0x93e9,0x93ea,0x93eb,0x93ec,0x93ed,0x93ee,0x93ef, + 0x93f0,0x93f1,0x93f2,0x93f3,0x93f4,0x93f5,0x93f6,0x93f7, + 0x93f8,0x93f9,0x93fa,0x93fb,0x93fc,0x93fd,0x93fe,0x93ff, + 0x9400,0x9401,0x9402,0x9403,0x9404,0x9405,0x9406,0x9407, + 0x9408,0x9409,0x940a,0x940b,0x940c,0x940d,0x940e,0x940f, + 0x9410,0x9411,0x9412,0x9413,0x9414,0x9415,0x9416,0x9417, + 0x9418,0x9419,0x941a,0x941b,0x941c,0x941d,0x941e,0x941f, + 0x9420,0x9421,0x9422,0x9423,0x9424,0x9425,0x9426,0x9427, + 0x9428,0x9429,0x942a,0x942b,0x942c,0x942d,0x942e,0x942f, + 0x9430,0x9431,0x9432,0x9433,0x9434,0x9435,0x9436,0x9437, + 0x9438,0x9439,0x943a,0x943b,0x943c,0x943d,0x943e,0x943f, + 0x9440,0x9441,0x9442,0x9443,0x9444,0x9445,0x9446,0x9447, + 0x9448,0x9449,0x944a,0x944b,0x944c,0x944d,0x944e,0x944f, + 0x9450,0x9451,0x9452,0x9453,0x9454,0x9455,0x9456,0x9457, + 0x9458,0x9459,0x945a,0x945b,0x945c,0x945d,0x945e,0x945f, + 0x9460,0x9461,0x9462,0x9463,0x9464,0x9465,0x9466,0x9467, + 0x9468,0x9469,0x946a,0x946b,0x946c,0x946d,0x946e,0x946f, + 0x9470,0x9471,0x9472,0x9473,0x9474,0x9475,0x9476,0x9477, + 0x9478,0x9479,0x947a,0x947b,0x947c,0x947d,0x947e,0x947f, + 0x9480,0x9481,0x9482,0x9483,0x9484,0x9485,0x9486,0x9487, + 0x9488,0x9489,0x948a,0x948b,0x948c,0x948d,0x948e,0x948f, + 0x9490,0x9491,0x9492,0x9493,0x9494,0x9495,0x9496,0x9497, + 0x9498,0x9499,0x949a,0x949b,0x949c,0x949d,0x949e,0x949f, + 0x94a0,0x94a1,0x94a2,0x94a3,0x94a4,0x94a5,0x94a6,0x94a7, + 0x94a8,0x94a9,0x94aa,0x94ab,0x94ac,0x94ad,0x94ae,0x94af, + 0x94b0,0x94b1,0x94b2,0x94b3,0x94b4,0x94b5,0x94b6,0x94b7, + 0x94b8,0x94b9,0x94ba,0x94bb,0x94bc,0x94bd,0x94be,0x94bf, + 0x94c0,0x94c1,0x94c2,0x94c3,0x94c4,0x94c5,0x94c6,0x94c7, + 0x94c8,0x94c9,0x94ca,0x94cb,0x94cc,0x94cd,0x94ce,0x94cf, + 0x94d0,0x94d1,0x94d2,0x94d3,0x94d4,0x94d5,0x94d6,0x94d7, + 0x94d8,0x94d9,0x94da,0x94db,0x94dc,0x94dd,0x94de,0x94df, + 0x94e0,0x94e1,0x94e2,0x94e3,0x94e4,0x94e5,0x94e6,0x94e7, + 0x94e8,0x94e9,0x94ea,0x94eb,0x94ec,0x94ed,0x94ee,0x94ef, + 0x94f0,0x94f1,0x94f2,0x94f3,0x94f4,0x94f5,0x94f6,0x94f7, + 0x94f8,0x94f9,0x94fa,0x94fb,0x94fc,0x94fd,0x94fe,0x94ff, + 0x9500,0x9501,0x9502,0x9503,0x9504,0x9505,0x9506,0x9507, + 0x9508,0x9509,0x950a,0x950b,0x950c,0x950d,0x950e,0x950f, + 0x9510,0x9511,0x9512,0x9513,0x9514,0x9515,0x9516,0x9517, + 0x9518,0x9519,0x951a,0x951b,0x951c,0x951d,0x951e,0x951f, + 0x9520,0x9521,0x9522,0x9523,0x9524,0x9525,0x9526,0x9527, + 0x9528,0x9529,0x952a,0x952b,0x952c,0x952d,0x952e,0x952f, + 0x9530,0x9531,0x9532,0x9533,0x9534,0x9535,0x9536,0x9537, + 0x9538,0x9539,0x953a,0x953b,0x953c,0x953d,0x953e,0x953f, + 0x9540,0x9541,0x9542,0x9543,0x9544,0x9545,0x9546,0x9547, + 0x9548,0x9549,0x954a,0x954b,0x954c,0x954d,0x954e,0x954f, + 0x9550,0x9551,0x9552,0x9553,0x9554,0x9555,0x9556,0x9557, + 0x9558,0x9559,0x955a,0x955b,0x955c,0x955d,0x955e,0x955f, + 0x9560,0x9561,0x9562,0x9563,0x9564,0x9565,0x9566,0x9567, + 0x9568,0x9569,0x956a,0x956b,0x956c,0x956d,0x956e,0x956f, + 0x9570,0x9571,0x9572,0x9573,0x9574,0x9575,0x9576,0x9577, + 0x9578,0x9579,0x957a,0x957b,0x957c,0x957d,0x957e,0x957f, + 0x9580,0x9581,0x9582,0x9583,0x9584,0x9585,0x9586,0x9587, + 0x9588,0x9589,0x958a,0x958b,0x958c,0x958d,0x958e,0x958f, + 0x9590,0x9591,0x9592,0x9593,0x9594,0x9595,0x9596,0x9597, + 0x9598,0x9599,0x959a,0x959b,0x959c,0x959d,0x959e,0x959f, + 0x95a0,0x95a1,0x95a2,0x95a3,0x95a4,0x95a5,0x95a6,0x95a7, + 0x95a8,0x95a9,0x95aa,0x95ab,0x95ac,0x95ad,0x95ae,0x95af, + 0x95b0,0x95b1,0x95b2,0x95b3,0x95b4,0x95b5,0x95b6,0x95b7, + 0x95b8,0x95b9,0x95ba,0x95bb,0x95bc,0x95bd,0x95be,0x95bf, + 0x95c0,0x95c1,0x95c2,0x95c3,0x95c4,0x95c5,0x95c6,0x95c7, + 0x95c8,0x95c9,0x95ca,0x95cb,0x95cc,0x95cd,0x95ce,0x95cf, + 0x95d0,0x95d1,0x95d2,0x95d3,0x95d4,0x95d5,0x95d6,0x95d7, + 0x95d8,0x95d9,0x95da,0x95db,0x95dc,0x95dd,0x95de,0x95df, + 0x95e0,0x95e1,0x95e2,0x95e3,0x95e4,0x95e5,0x95e6,0x95e7, + 0x95e8,0x95e9,0x95ea,0x95eb,0x95ec,0x95ed,0x95ee,0x95ef, + 0x95f0,0x95f1,0x95f2,0x95f3,0x95f4,0x95f5,0x95f6,0x95f7, + 0x95f8,0x95f9,0x95fa,0x95fb,0x95fc,0x95fd,0x95fe,0x95ff, + 0x9600,0x9601,0x9602,0x9603,0x9604,0x9605,0x9606,0x9607, + 0x9608,0x9609,0x960a,0x960b,0x960c,0x960d,0x960e,0x960f, + 0x9610,0x9611,0x9612,0x9613,0x9614,0x9615,0x9616,0x9617, + 0x9618,0x9619,0x961a,0x961b,0x961c,0x961d,0x961e,0x961f, + 0x9620,0x9621,0x9622,0x9623,0x9624,0x9625,0x9626,0x9627, + 0x9628,0x9629,0x962a,0x962b,0x962c,0x962d,0x962e,0x962f, + 0x9630,0x9631,0x9632,0x9633,0x9634,0x9635,0x9636,0x9637, + 0x9638,0x9639,0x963a,0x963b,0x963c,0x963d,0x963e,0x963f, + 0x9640,0x9641,0x9642,0x9643,0x9644,0x9645,0x9646,0x9647, + 0x9648,0x9649,0x964a,0x964b,0x964c,0x964d,0x964e,0x964f, + 0x9650,0x9651,0x9652,0x9653,0x9654,0x9655,0x9656,0x9657, + 0x9658,0x9659,0x965a,0x965b,0x965c,0x965d,0x965e,0x965f, + 0x9660,0x9661,0x9662,0x9663,0x9664,0x9665,0x9666,0x9667, + 0x9668,0x9669,0x966a,0x966b,0x966c,0x966d,0x966e,0x966f, + 0x9670,0x9671,0x9672,0x9673,0x9674,0x9675,0x9676,0x9677, + 0x9678,0x9679,0x967a,0x967b,0x967c,0x967d,0x967e,0x967f, + 0x9680,0x9681,0x9682,0x9683,0x9684,0x9685,0x9686,0x9687, + 0x9688,0x9689,0x968a,0x968b,0x968c,0x968d,0x968e,0x968f, + 0x9690,0x9691,0x9692,0x9693,0x9694,0x9695,0x9696,0x9697, + 0x9698,0x9699,0x969a,0x969b,0x969c,0x969d,0x969e,0x969f, + 0x96a0,0x96a1,0x96a2,0x96a3,0x96a4,0x96a5,0x96a6,0x96a7, + 0x96a8,0x96a9,0x96aa,0x96ab,0x96ac,0x96ad,0x96ae,0x96af, + 0x96b0,0x96b1,0x96b2,0x96b3,0x96b4,0x96b5,0x96b6,0x96b7, + 0x96b8,0x96b9,0x96ba,0x96bb,0x96bc,0x96bd,0x96be,0x96bf, + 0x96c0,0x96c1,0x96c2,0x96c3,0x96c4,0x96c5,0x96c6,0x96c7, + 0x96c8,0x96c9,0x96ca,0x96cb,0x96cc,0x96cd,0x96ce,0x96cf, + 0x96d0,0x96d1,0x96d2,0x96d3,0x96d4,0x96d5,0x96d6,0x96d7, + 0x96d8,0x96d9,0x96da,0x96db,0x96dc,0x96dd,0x96de,0x96df, + 0x96e0,0x96e1,0x96e2,0x96e3,0x96e4,0x96e5,0x96e6,0x96e7, + 0x96e8,0x96e9,0x96ea,0x96eb,0x96ec,0x96ed,0x96ee,0x96ef, + 0x96f0,0x96f1,0x96f2,0x96f3,0x96f4,0x96f5,0x96f6,0x96f7, + 0x96f8,0x96f9,0x96fa,0x96fb,0x96fc,0x96fd,0x96fe,0x96ff, + 0x9700,0x9701,0x9702,0x9703,0x9704,0x9705,0x9706,0x9707, + 0x9708,0x9709,0x970a,0x970b,0x970c,0x970d,0x970e,0x970f, + 0x9710,0x9711,0x9712,0x9713,0x9714,0x9715,0x9716,0x9717, + 0x9718,0x9719,0x971a,0x971b,0x971c,0x971d,0x971e,0x971f, + 0x9720,0x9721,0x9722,0x9723,0x9724,0x9725,0x9726,0x9727, + 0x9728,0x9729,0x972a,0x972b,0x972c,0x972d,0x972e,0x972f, + 0x9730,0x9731,0x9732,0x9733,0x9734,0x9735,0x9736,0x9737, + 0x9738,0x9739,0x973a,0x973b,0x973c,0x973d,0x973e,0x973f, + 0x9740,0x9741,0x9742,0x9743,0x9744,0x9745,0x9746,0x9747, + 0x9748,0x9749,0x974a,0x974b,0x974c,0x974d,0x974e,0x974f, + 0x9750,0x9751,0x9752,0x9753,0x9754,0x9755,0x9756,0x9757, + 0x9758,0x9759,0x975a,0x975b,0x975c,0x975d,0x975e,0x975f, + 0x9760,0x9761,0x9762,0x9763,0x9764,0x9765,0x9766,0x9767, + 0x9768,0x9769,0x976a,0x976b,0x976c,0x976d,0x976e,0x976f, + 0x9770,0x9771,0x9772,0x9773,0x9774,0x9775,0x9776,0x9777, + 0x9778,0x9779,0x977a,0x977b,0x977c,0x977d,0x977e,0x977f, + 0x9780,0x9781,0x9782,0x9783,0x9784,0x9785,0x9786,0x9787, + 0x9788,0x9789,0x978a,0x978b,0x978c,0x978d,0x978e,0x978f, + 0x9790,0x9791,0x9792,0x9793,0x9794,0x9795,0x9796,0x9797, + 0x9798,0x9799,0x979a,0x979b,0x979c,0x979d,0x979e,0x979f, + 0x97a0,0x97a1,0x97a2,0x97a3,0x97a4,0x97a5,0x97a6,0x97a7, + 0x97a8,0x97a9,0x97aa,0x97ab,0x97ac,0x97ad,0x97ae,0x97af, + 0x97b0,0x97b1,0x97b2,0x97b3,0x97b4,0x97b5,0x97b6,0x97b7, + 0x97b8,0x97b9,0x97ba,0x97bb,0x97bc,0x97bd,0x97be,0x97bf, + 0x97c0,0x97c1,0x97c2,0x97c3,0x97c4,0x97c5,0x97c6,0x97c7, + 0x97c8,0x97c9,0x97ca,0x97cb,0x97cc,0x97cd,0x97ce,0x97cf, + 0x97d0,0x97d1,0x97d2,0x97d3,0x97d4,0x97d5,0x97d6,0x97d7, + 0x97d8,0x97d9,0x97da,0x97db,0x97dc,0x97dd,0x97de,0x97df, + 0x97e0,0x97e1,0x97e2,0x97e3,0x97e4,0x97e5,0x97e6,0x97e7, + 0x97e8,0x97e9,0x97ea,0x97eb,0x97ec,0x97ed,0x97ee,0x97ef, + 0x97f0,0x97f1,0x97f2,0x97f3,0x97f4,0x97f5,0x97f6,0x97f7, + 0x97f8,0x97f9,0x97fa,0x97fb,0x97fc,0x97fd,0x97fe,0x97ff, + 0x9800,0x9801,0x9802,0x9803,0x9804,0x9805,0x9806,0x9807, + 0x9808,0x9809,0x980a,0x980b,0x980c,0x980d,0x980e,0x980f, + 0x9810,0x9811,0x9812,0x9813,0x9814,0x9815,0x9816,0x9817, + 0x9818,0x9819,0x981a,0x981b,0x981c,0x981d,0x981e,0x981f, + 0x9820,0x9821,0x9822,0x9823,0x9824,0x9825,0x9826,0x9827, + 0x9828,0x9829,0x982a,0x982b,0x982c,0x982d,0x982e,0x982f, + 0x9830,0x9831,0x9832,0x9833,0x9834,0x9835,0x9836,0x9837, + 0x9838,0x9839,0x983a,0x983b,0x983c,0x983d,0x983e,0x983f, + 0x9840,0x9841,0x9842,0x9843,0x9844,0x9845,0x9846,0x9847, + 0x9848,0x9849,0x984a,0x984b,0x984c,0x984d,0x984e,0x984f, + 0x9850,0x9851,0x9852,0x9853,0x9854,0x9855,0x9856,0x9857, + 0x9858,0x9859,0x985a,0x985b,0x985c,0x985d,0x985e,0x985f, + 0x9860,0x9861,0x9862,0x9863,0x9864,0x9865,0x9866,0x9867, + 0x9868,0x9869,0x986a,0x986b,0x986c,0x986d,0x986e,0x986f, + 0x9870,0x9871,0x9872,0x9873,0x9874,0x9875,0x9876,0x9877, + 0x9878,0x9879,0x987a,0x987b,0x987c,0x987d,0x987e,0x987f, + 0x9880,0x9881,0x9882,0x9883,0x9884,0x9885,0x9886,0x9887, + 0x9888,0x9889,0x988a,0x988b,0x988c,0x988d,0x988e,0x988f, + 0x9890,0x9891,0x9892,0x9893,0x9894,0x9895,0x9896,0x9897, + 0x9898,0x9899,0x989a,0x989b,0x989c,0x989d,0x989e,0x989f, + 0x98a0,0x98a1,0x98a2,0x98a3,0x98a4,0x98a5,0x98a6,0x98a7, + 0x98a8,0x98a9,0x98aa,0x98ab,0x98ac,0x98ad,0x98ae,0x98af, + 0x98b0,0x98b1,0x98b2,0x98b3,0x98b4,0x98b5,0x98b6,0x98b7, + 0x98b8,0x98b9,0x98ba,0x98bb,0x98bc,0x98bd,0x98be,0x98bf, + 0x98c0,0x98c1,0x98c2,0x98c3,0x98c4,0x98c5,0x98c6,0x98c7, + 0x98c8,0x98c9,0x98ca,0x98cb,0x98cc,0x98cd,0x98ce,0x98cf, + 0x98d0,0x98d1,0x98d2,0x98d3,0x98d4,0x98d5,0x98d6,0x98d7, + 0x98d8,0x98d9,0x98da,0x98db,0x98dc,0x98dd,0x98de,0x98df, + 0x98e0,0x98e1,0x98e2,0x98e3,0x98e4,0x98e5,0x98e6,0x98e7, + 0x98e8,0x98e9,0x98ea,0x98eb,0x98ec,0x98ed,0x98ee,0x98ef, + 0x98f0,0x98f1,0x98f2,0x98f3,0x98f4,0x98f5,0x98f6,0x98f7, + 0x98f8,0x98f9,0x98fa,0x98fb,0x98fc,0x98fd,0x98fe,0x98ff, + 0x9900,0x9901,0x9902,0x9903,0x9904,0x9905,0x9906,0x9907, + 0x9908,0x9909,0x990a,0x990b,0x990c,0x990d,0x990e,0x990f, + 0x9910,0x9911,0x9912,0x9913,0x9914,0x9915,0x9916,0x9917, + 0x9918,0x9919,0x991a,0x991b,0x991c,0x991d,0x991e,0x991f, + 0x9920,0x9921,0x9922,0x9923,0x9924,0x9925,0x9926,0x9927, + 0x9928,0x9929,0x992a,0x992b,0x992c,0x992d,0x992e,0x992f, + 0x9930,0x9931,0x9932,0x9933,0x9934,0x9935,0x9936,0x9937, + 0x9938,0x9939,0x993a,0x993b,0x993c,0x993d,0x993e,0x993f, + 0x9940,0x9941,0x9942,0x9943,0x9944,0x9945,0x9946,0x9947, + 0x9948,0x9949,0x994a,0x994b,0x994c,0x994d,0x994e,0x994f, + 0x9950,0x9951,0x9952,0x9953,0x9954,0x9955,0x9956,0x9957, + 0x9958,0x9959,0x995a,0x995b,0x995c,0x995d,0x995e,0x995f, + 0x9960,0x9961,0x9962,0x9963,0x9964,0x9965,0x9966,0x9967, + 0x9968,0x9969,0x996a,0x996b,0x996c,0x996d,0x996e,0x996f, + 0x9970,0x9971,0x9972,0x9973,0x9974,0x9975,0x9976,0x9977, + 0x9978,0x9979,0x997a,0x997b,0x997c,0x997d,0x997e,0x997f, + 0x9980,0x9981,0x9982,0x9983,0x9984,0x9985,0x9986,0x9987, + 0x9988,0x9989,0x998a,0x998b,0x998c,0x998d,0x998e,0x998f, + 0x9990,0x9991,0x9992,0x9993,0x9994,0x9995,0x9996,0x9997, + 0x9998,0x9999,0x999a,0x999b,0x999c,0x999d,0x999e,0x999f, + 0x99a0,0x99a1,0x99a2,0x99a3,0x99a4,0x99a5,0x99a6,0x99a7, + 0x99a8,0x99a9,0x99aa,0x99ab,0x99ac,0x99ad,0x99ae,0x99af, + 0x99b0,0x99b1,0x99b2,0x99b3,0x99b4,0x99b5,0x99b6,0x99b7, + 0x99b8,0x99b9,0x99ba,0x99bb,0x99bc,0x99bd,0x99be,0x99bf, + 0x99c0,0x99c1,0x99c2,0x99c3,0x99c4,0x99c5,0x99c6,0x99c7, + 0x99c8,0x99c9,0x99ca,0x99cb,0x99cc,0x99cd,0x99ce,0x99cf, + 0x99d0,0x99d1,0x99d2,0x99d3,0x99d4,0x99d5,0x99d6,0x99d7, + 0x99d8,0x99d9,0x99da,0x99db,0x99dc,0x99dd,0x99de,0x99df, + 0x99e0,0x99e1,0x99e2,0x99e3,0x99e4,0x99e5,0x99e6,0x99e7, + 0x99e8,0x99e9,0x99ea,0x99eb,0x99ec,0x99ed,0x99ee,0x99ef, + 0x99f0,0x99f1,0x99f2,0x99f3,0x99f4,0x99f5,0x99f6,0x99f7, + 0x99f8,0x99f9,0x99fa,0x99fb,0x99fc,0x99fd,0x99fe,0x99ff, + 0x9a00,0x9a01,0x9a02,0x9a03,0x9a04,0x9a05,0x9a06,0x9a07, + 0x9a08,0x9a09,0x9a0a,0x9a0b,0x9a0c,0x9a0d,0x9a0e,0x9a0f, + 0x9a10,0x9a11,0x9a12,0x9a13,0x9a14,0x9a15,0x9a16,0x9a17, + 0x9a18,0x9a19,0x9a1a,0x9a1b,0x9a1c,0x9a1d,0x9a1e,0x9a1f, + 0x9a20,0x9a21,0x9a22,0x9a23,0x9a24,0x9a25,0x9a26,0x9a27, + 0x9a28,0x9a29,0x9a2a,0x9a2b,0x9a2c,0x9a2d,0x9a2e,0x9a2f, + 0x9a30,0x9a31,0x9a32,0x9a33,0x9a34,0x9a35,0x9a36,0x9a37, + 0x9a38,0x9a39,0x9a3a,0x9a3b,0x9a3c,0x9a3d,0x9a3e,0x9a3f, + 0x9a40,0x9a41,0x9a42,0x9a43,0x9a44,0x9a45,0x9a46,0x9a47, + 0x9a48,0x9a49,0x9a4a,0x9a4b,0x9a4c,0x9a4d,0x9a4e,0x9a4f, + 0x9a50,0x9a51,0x9a52,0x9a53,0x9a54,0x9a55,0x9a56,0x9a57, + 0x9a58,0x9a59,0x9a5a,0x9a5b,0x9a5c,0x9a5d,0x9a5e,0x9a5f, + 0x9a60,0x9a61,0x9a62,0x9a63,0x9a64,0x9a65,0x9a66,0x9a67, + 0x9a68,0x9a69,0x9a6a,0x9a6b,0x9a6c,0x9a6d,0x9a6e,0x9a6f, + 0x9a70,0x9a71,0x9a72,0x9a73,0x9a74,0x9a75,0x9a76,0x9a77, + 0x9a78,0x9a79,0x9a7a,0x9a7b,0x9a7c,0x9a7d,0x9a7e,0x9a7f, + 0x9a80,0x9a81,0x9a82,0x9a83,0x9a84,0x9a85,0x9a86,0x9a87, + 0x9a88,0x9a89,0x9a8a,0x9a8b,0x9a8c,0x9a8d,0x9a8e,0x9a8f, + 0x9a90,0x9a91,0x9a92,0x9a93,0x9a94,0x9a95,0x9a96,0x9a97, + 0x9a98,0x9a99,0x9a9a,0x9a9b,0x9a9c,0x9a9d,0x9a9e,0x9a9f, + 0x9aa0,0x9aa1,0x9aa2,0x9aa3,0x9aa4,0x9aa5,0x9aa6,0x9aa7, + 0x9aa8,0x9aa9,0x9aaa,0x9aab,0x9aac,0x9aad,0x9aae,0x9aaf, + 0x9ab0,0x9ab1,0x9ab2,0x9ab3,0x9ab4,0x9ab5,0x9ab6,0x9ab7, + 0x9ab8,0x9ab9,0x9aba,0x9abb,0x9abc,0x9abd,0x9abe,0x9abf, + 0x9ac0,0x9ac1,0x9ac2,0x9ac3,0x9ac4,0x9ac5,0x9ac6,0x9ac7, + 0x9ac8,0x9ac9,0x9aca,0x9acb,0x9acc,0x9acd,0x9ace,0x9acf, + 0x9ad0,0x9ad1,0x9ad2,0x9ad3,0x9ad4,0x9ad5,0x9ad6,0x9ad7, + 0x9ad8,0x9ad9,0x9ada,0x9adb,0x9adc,0x9add,0x9ade,0x9adf, + 0x9ae0,0x9ae1,0x9ae2,0x9ae3,0x9ae4,0x9ae5,0x9ae6,0x9ae7, + 0x9ae8,0x9ae9,0x9aea,0x9aeb,0x9aec,0x9aed,0x9aee,0x9aef, + 0x9af0,0x9af1,0x9af2,0x9af3,0x9af4,0x9af5,0x9af6,0x9af7, + 0x9af8,0x9af9,0x9afa,0x9afb,0x9afc,0x9afd,0x9afe,0x9aff, + 0x9b00,0x9b01,0x9b02,0x9b03,0x9b04,0x9b05,0x9b06,0x9b07, + 0x9b08,0x9b09,0x9b0a,0x9b0b,0x9b0c,0x9b0d,0x9b0e,0x9b0f, + 0x9b10,0x9b11,0x9b12,0x9b13,0x9b14,0x9b15,0x9b16,0x9b17, + 0x9b18,0x9b19,0x9b1a,0x9b1b,0x9b1c,0x9b1d,0x9b1e,0x9b1f, + 0x9b20,0x9b21,0x9b22,0x9b23,0x9b24,0x9b25,0x9b26,0x9b27, + 0x9b28,0x9b29,0x9b2a,0x9b2b,0x9b2c,0x9b2d,0x9b2e,0x9b2f, + 0x9b30,0x9b31,0x9b32,0x9b33,0x9b34,0x9b35,0x9b36,0x9b37, + 0x9b38,0x9b39,0x9b3a,0x9b3b,0x9b3c,0x9b3d,0x9b3e,0x9b3f, + 0x9b40,0x9b41,0x9b42,0x9b43,0x9b44,0x9b45,0x9b46,0x9b47, + 0x9b48,0x9b49,0x9b4a,0x9b4b,0x9b4c,0x9b4d,0x9b4e,0x9b4f, + 0x9b50,0x9b51,0x9b52,0x9b53,0x9b54,0x9b55,0x9b56,0x9b57, + 0x9b58,0x9b59,0x9b5a,0x9b5b,0x9b5c,0x9b5d,0x9b5e,0x9b5f, + 0x9b60,0x9b61,0x9b62,0x9b63,0x9b64,0x9b65,0x9b66,0x9b67, + 0x9b68,0x9b69,0x9b6a,0x9b6b,0x9b6c,0x9b6d,0x9b6e,0x9b6f, + 0x9b70,0x9b71,0x9b72,0x9b73,0x9b74,0x9b75,0x9b76,0x9b77, + 0x9b78,0x9b79,0x9b7a,0x9b7b,0x9b7c,0x9b7d,0x9b7e,0x9b7f, + 0x9b80,0x9b81,0x9b82,0x9b83,0x9b84,0x9b85,0x9b86,0x9b87, + 0x9b88,0x9b89,0x9b8a,0x9b8b,0x9b8c,0x9b8d,0x9b8e,0x9b8f, + 0x9b90,0x9b91,0x9b92,0x9b93,0x9b94,0x9b95,0x9b96,0x9b97, + 0x9b98,0x9b99,0x9b9a,0x9b9b,0x9b9c,0x9b9d,0x9b9e,0x9b9f, + 0x9ba0,0x9ba1,0x9ba2,0x9ba3,0x9ba4,0x9ba5,0x9ba6,0x9ba7, + 0x9ba8,0x9ba9,0x9baa,0x9bab,0x9bac,0x9bad,0x9bae,0x9baf, + 0x9bb0,0x9bb1,0x9bb2,0x9bb3,0x9bb4,0x9bb5,0x9bb6,0x9bb7, + 0x9bb8,0x9bb9,0x9bba,0x9bbb,0x9bbc,0x9bbd,0x9bbe,0x9bbf, + 0x9bc0,0x9bc1,0x9bc2,0x9bc3,0x9bc4,0x9bc5,0x9bc6,0x9bc7, + 0x9bc8,0x9bc9,0x9bca,0x9bcb,0x9bcc,0x9bcd,0x9bce,0x9bcf, + 0x9bd0,0x9bd1,0x9bd2,0x9bd3,0x9bd4,0x9bd5,0x9bd6,0x9bd7, + 0x9bd8,0x9bd9,0x9bda,0x9bdb,0x9bdc,0x9bdd,0x9bde,0x9bdf, + 0x9be0,0x9be1,0x9be2,0x9be3,0x9be4,0x9be5,0x9be6,0x9be7, + 0x9be8,0x9be9,0x9bea,0x9beb,0x9bec,0x9bed,0x9bee,0x9bef, + 0x9bf0,0x9bf1,0x9bf2,0x9bf3,0x9bf4,0x9bf5,0x9bf6,0x9bf7, + 0x9bf8,0x9bf9,0x9bfa,0x9bfb,0x9bfc,0x9bfd,0x9bfe,0x9bff, + 0x9c00,0x9c01,0x9c02,0x9c03,0x9c04,0x9c05,0x9c06,0x9c07, + 0x9c08,0x9c09,0x9c0a,0x9c0b,0x9c0c,0x9c0d,0x9c0e,0x9c0f, + 0x9c10,0x9c11,0x9c12,0x9c13,0x9c14,0x9c15,0x9c16,0x9c17, + 0x9c18,0x9c19,0x9c1a,0x9c1b,0x9c1c,0x9c1d,0x9c1e,0x9c1f, + 0x9c20,0x9c21,0x9c22,0x9c23,0x9c24,0x9c25,0x9c26,0x9c27, + 0x9c28,0x9c29,0x9c2a,0x9c2b,0x9c2c,0x9c2d,0x9c2e,0x9c2f, + 0x9c30,0x9c31,0x9c32,0x9c33,0x9c34,0x9c35,0x9c36,0x9c37, + 0x9c38,0x9c39,0x9c3a,0x9c3b,0x9c3c,0x9c3d,0x9c3e,0x9c3f, + 0x9c40,0x9c41,0x9c42,0x9c43,0x9c44,0x9c45,0x9c46,0x9c47, + 0x9c48,0x9c49,0x9c4a,0x9c4b,0x9c4c,0x9c4d,0x9c4e,0x9c4f, + 0x9c50,0x9c51,0x9c52,0x9c53,0x9c54,0x9c55,0x9c56,0x9c57, + 0x9c58,0x9c59,0x9c5a,0x9c5b,0x9c5c,0x9c5d,0x9c5e,0x9c5f, + 0x9c60,0x9c61,0x9c62,0x9c63,0x9c64,0x9c65,0x9c66,0x9c67, + 0x9c68,0x9c69,0x9c6a,0x9c6b,0x9c6c,0x9c6d,0x9c6e,0x9c6f, + 0x9c70,0x9c71,0x9c72,0x9c73,0x9c74,0x9c75,0x9c76,0x9c77, + 0x9c78,0x9c79,0x9c7a,0x9c7b,0x9c7c,0x9c7d,0x9c7e,0x9c7f, + 0x9c80,0x9c81,0x9c82,0x9c83,0x9c84,0x9c85,0x9c86,0x9c87, + 0x9c88,0x9c89,0x9c8a,0x9c8b,0x9c8c,0x9c8d,0x9c8e,0x9c8f, + 0x9c90,0x9c91,0x9c92,0x9c93,0x9c94,0x9c95,0x9c96,0x9c97, + 0x9c98,0x9c99,0x9c9a,0x9c9b,0x9c9c,0x9c9d,0x9c9e,0x9c9f, + 0x9ca0,0x9ca1,0x9ca2,0x9ca3,0x9ca4,0x9ca5,0x9ca6,0x9ca7, + 0x9ca8,0x9ca9,0x9caa,0x9cab,0x9cac,0x9cad,0x9cae,0x9caf, + 0x9cb0,0x9cb1,0x9cb2,0x9cb3,0x9cb4,0x9cb5,0x9cb6,0x9cb7, + 0x9cb8,0x9cb9,0x9cba,0x9cbb,0x9cbc,0x9cbd,0x9cbe,0x9cbf, + 0x9cc0,0x9cc1,0x9cc2,0x9cc3,0x9cc4,0x9cc5,0x9cc6,0x9cc7, + 0x9cc8,0x9cc9,0x9cca,0x9ccb,0x9ccc,0x9ccd,0x9cce,0x9ccf, + 0x9cd0,0x9cd1,0x9cd2,0x9cd3,0x9cd4,0x9cd5,0x9cd6,0x9cd7, + 0x9cd8,0x9cd9,0x9cda,0x9cdb,0x9cdc,0x9cdd,0x9cde,0x9cdf, + 0x9ce0,0x9ce1,0x9ce2,0x9ce3,0x9ce4,0x9ce5,0x9ce6,0x9ce7, + 0x9ce8,0x9ce9,0x9cea,0x9ceb,0x9cec,0x9ced,0x9cee,0x9cef, + 0x9cf0,0x9cf1,0x9cf2,0x9cf3,0x9cf4,0x9cf5,0x9cf6,0x9cf7, + 0x9cf8,0x9cf9,0x9cfa,0x9cfb,0x9cfc,0x9cfd,0x9cfe,0x9cff, + 0x9d00,0x9d01,0x9d02,0x9d03,0x9d04,0x9d05,0x9d06,0x9d07, + 0x9d08,0x9d09,0x9d0a,0x9d0b,0x9d0c,0x9d0d,0x9d0e,0x9d0f, + 0x9d10,0x9d11,0x9d12,0x9d13,0x9d14,0x9d15,0x9d16,0x9d17, + 0x9d18,0x9d19,0x9d1a,0x9d1b,0x9d1c,0x9d1d,0x9d1e,0x9d1f, + 0x9d20,0x9d21,0x9d22,0x9d23,0x9d24,0x9d25,0x9d26,0x9d27, + 0x9d28,0x9d29,0x9d2a,0x9d2b,0x9d2c,0x9d2d,0x9d2e,0x9d2f, + 0x9d30,0x9d31,0x9d32,0x9d33,0x9d34,0x9d35,0x9d36,0x9d37, + 0x9d38,0x9d39,0x9d3a,0x9d3b,0x9d3c,0x9d3d,0x9d3e,0x9d3f, + 0x9d40,0x9d41,0x9d42,0x9d43,0x9d44,0x9d45,0x9d46,0x9d47, + 0x9d48,0x9d49,0x9d4a,0x9d4b,0x9d4c,0x9d4d,0x9d4e,0x9d4f, + 0x9d50,0x9d51,0x9d52,0x9d53,0x9d54,0x9d55,0x9d56,0x9d57, + 0x9d58,0x9d59,0x9d5a,0x9d5b,0x9d5c,0x9d5d,0x9d5e,0x9d5f, + 0x9d60,0x9d61,0x9d62,0x9d63,0x9d64,0x9d65,0x9d66,0x9d67, + 0x9d68,0x9d69,0x9d6a,0x9d6b,0x9d6c,0x9d6d,0x9d6e,0x9d6f, + 0x9d70,0x9d71,0x9d72,0x9d73,0x9d74,0x9d75,0x9d76,0x9d77, + 0x9d78,0x9d79,0x9d7a,0x9d7b,0x9d7c,0x9d7d,0x9d7e,0x9d7f, + 0x9d80,0x9d81,0x9d82,0x9d83,0x9d84,0x9d85,0x9d86,0x9d87, + 0x9d88,0x9d89,0x9d8a,0x9d8b,0x9d8c,0x9d8d,0x9d8e,0x9d8f, + 0x9d90,0x9d91,0x9d92,0x9d93,0x9d94,0x9d95,0x9d96,0x9d97, + 0x9d98,0x9d99,0x9d9a,0x9d9b,0x9d9c,0x9d9d,0x9d9e,0x9d9f, + 0x9da0,0x9da1,0x9da2,0x9da3,0x9da4,0x9da5,0x9da6,0x9da7, + 0x9da8,0x9da9,0x9daa,0x9dab,0x9dac,0x9dad,0x9dae,0x9daf, + 0x9db0,0x9db1,0x9db2,0x9db3,0x9db4,0x9db5,0x9db6,0x9db7, + 0x9db8,0x9db9,0x9dba,0x9dbb,0x9dbc,0x9dbd,0x9dbe,0x9dbf, + 0x9dc0,0x9dc1,0x9dc2,0x9dc3,0x9dc4,0x9dc5,0x9dc6,0x9dc7, + 0x9dc8,0x9dc9,0x9dca,0x9dcb,0x9dcc,0x9dcd,0x9dce,0x9dcf, + 0x9dd0,0x9dd1,0x9dd2,0x9dd3,0x9dd4,0x9dd5,0x9dd6,0x9dd7, + 0x9dd8,0x9dd9,0x9dda,0x9ddb,0x9ddc,0x9ddd,0x9dde,0x9ddf, + 0x9de0,0x9de1,0x9de2,0x9de3,0x9de4,0x9de5,0x9de6,0x9de7, + 0x9de8,0x9de9,0x9dea,0x9deb,0x9dec,0x9ded,0x9dee,0x9def, + 0x9df0,0x9df1,0x9df2,0x9df3,0x9df4,0x9df5,0x9df6,0x9df7, + 0x9df8,0x9df9,0x9dfa,0x9dfb,0x9dfc,0x9dfd,0x9dfe,0x9dff, + 0x9e00,0x9e01,0x9e02,0x9e03,0x9e04,0x9e05,0x9e06,0x9e07, + 0x9e08,0x9e09,0x9e0a,0x9e0b,0x9e0c,0x9e0d,0x9e0e,0x9e0f, + 0x9e10,0x9e11,0x9e12,0x9e13,0x9e14,0x9e15,0x9e16,0x9e17, + 0x9e18,0x9e19,0x9e1a,0x9e1b,0x9e1c,0x9e1d,0x9e1e,0x9e1f, + 0x9e20,0x9e21,0x9e22,0x9e23,0x9e24,0x9e25,0x9e26,0x9e27, + 0x9e28,0x9e29,0x9e2a,0x9e2b,0x9e2c,0x9e2d,0x9e2e,0x9e2f, + 0x9e30,0x9e31,0x9e32,0x9e33,0x9e34,0x9e35,0x9e36,0x9e37, + 0x9e38,0x9e39,0x9e3a,0x9e3b,0x9e3c,0x9e3d,0x9e3e,0x9e3f, + 0x9e40,0x9e41,0x9e42,0x9e43,0x9e44,0x9e45,0x9e46,0x9e47, + 0x9e48,0x9e49,0x9e4a,0x9e4b,0x9e4c,0x9e4d,0x9e4e,0x9e4f, + 0x9e50,0x9e51,0x9e52,0x9e53,0x9e54,0x9e55,0x9e56,0x9e57, + 0x9e58,0x9e59,0x9e5a,0x9e5b,0x9e5c,0x9e5d,0x9e5e,0x9e5f, + 0x9e60,0x9e61,0x9e62,0x9e63,0x9e64,0x9e65,0x9e66,0x9e67, + 0x9e68,0x9e69,0x9e6a,0x9e6b,0x9e6c,0x9e6d,0x9e6e,0x9e6f, + 0x9e70,0x9e71,0x9e72,0x9e73,0x9e74,0x9e75,0x9e76,0x9e77, + 0x9e78,0x9e79,0x9e7a,0x9e7b,0x9e7c,0x9e7d,0x9e7e,0x9e7f, + 0x9e80,0x9e81,0x9e82,0x9e83,0x9e84,0x9e85,0x9e86,0x9e87, + 0x9e88,0x9e89,0x9e8a,0x9e8b,0x9e8c,0x9e8d,0x9e8e,0x9e8f, + 0x9e90,0x9e91,0x9e92,0x9e93,0x9e94,0x9e95,0x9e96,0x9e97, + 0x9e98,0x9e99,0x9e9a,0x9e9b,0x9e9c,0x9e9d,0x9e9e,0x9e9f, + 0x9ea0,0x9ea1,0x9ea2,0x9ea3,0x9ea4,0x9ea5,0x9ea6,0x9ea7, + 0x9ea8,0x9ea9,0x9eaa,0x9eab,0x9eac,0x9ead,0x9eae,0x9eaf, + 0x9eb0,0x9eb1,0x9eb2,0x9eb3,0x9eb4,0x9eb5,0x9eb6,0x9eb7, + 0x9eb8,0x9eb9,0x9eba,0x9ebb,0x9ebc,0x9ebd,0x9ebe,0x9ebf, + 0x9ec0,0x9ec1,0x9ec2,0x9ec3,0x9ec4,0x9ec5,0x9ec6,0x9ec7, + 0x9ec8,0x9ec9,0x9eca,0x9ecb,0x9ecc,0x9ecd,0x9ece,0x9ecf, + 0x9ed0,0x9ed1,0x9ed2,0x9ed3,0x9ed4,0x9ed5,0x9ed6,0x9ed7, + 0x9ed8,0x9ed9,0x9eda,0x9edb,0x9edc,0x9edd,0x9ede,0x9edf, + 0x9ee0,0x9ee1,0x9ee2,0x9ee3,0x9ee4,0x9ee5,0x9ee6,0x9ee7, + 0x9ee8,0x9ee9,0x9eea,0x9eeb,0x9eec,0x9eed,0x9eee,0x9eef, + 0x9ef0,0x9ef1,0x9ef2,0x9ef3,0x9ef4,0x9ef5,0x9ef6,0x9ef7, + 0x9ef8,0x9ef9,0x9efa,0x9efb,0x9efc,0x9efd,0x9efe,0x9eff, + 0x9f00,0x9f01,0x9f02,0x9f03,0x9f04,0x9f05,0x9f06,0x9f07, + 0x9f08,0x9f09,0x9f0a,0x9f0b,0x9f0c,0x9f0d,0x9f0e,0x9f0f, + 0x9f10,0x9f11,0x9f12,0x9f13,0x9f14,0x9f15,0x9f16,0x9f17, + 0x9f18,0x9f19,0x9f1a,0x9f1b,0x9f1c,0x9f1d,0x9f1e,0x9f1f, + 0x9f20,0x9f21,0x9f22,0x9f23,0x9f24,0x9f25,0x9f26,0x9f27, + 0x9f28,0x9f29,0x9f2a,0x9f2b,0x9f2c,0x9f2d,0x9f2e,0x9f2f, + 0x9f30,0x9f31,0x9f32,0x9f33,0x9f34,0x9f35,0x9f36,0x9f37, + 0x9f38,0x9f39,0x9f3a,0x9f3b,0x9f3c,0x9f3d,0x9f3e,0x9f3f, + 0x9f40,0x9f41,0x9f42,0x9f43,0x9f44,0x9f45,0x9f46,0x9f47, + 0x9f48,0x9f49,0x9f4a,0x9f4b,0x9f4c,0x9f4d,0x9f4e,0x9f4f, + 0x9f50,0x9f51,0x9f52,0x9f53,0x9f54,0x9f55,0x9f56,0x9f57, + 0x9f58,0x9f59,0x9f5a,0x9f5b,0x9f5c,0x9f5d,0x9f5e,0x9f5f, + 0x9f60,0x9f61,0x9f62,0x9f63,0x9f64,0x9f65,0x9f66,0x9f67, + 0x9f68,0x9f69,0x9f6a,0x9f6b,0x9f6c,0x9f6d,0x9f6e,0x9f6f, + 0x9f70,0x9f71,0x9f72,0x9f73,0x9f74,0x9f75,0x9f76,0x9f77, + 0x9f78,0x9f79,0x9f7a,0x9f7b,0x9f7c,0x9f7d,0x9f7e,0x9f7f, + 0x9f80,0x9f81,0x9f82,0x9f83,0x9f84,0x9f85,0x9f86,0x9f87, + 0x9f88,0x9f89,0x9f8a,0x9f8b,0x9f8c,0x9f8d,0x9f8e,0x9f8f, + 0x9f90,0x9f91,0x9f92,0x9f93,0x9f94,0x9f95,0x9f96,0x9f97, + 0x9f98,0x9f99,0x9f9a,0x9f9b,0x9f9c,0x9f9d,0x9f9e,0x9f9f, + 0x9fa0,0x9fa1,0x9fa2,0x9fa3,0x9fa4,0x9fa5,0x9fa6,0x9fa7, + 0x9fa8,0x9fa9,0x9faa,0x9fab,0x9fac,0x9fad,0x9fae,0x9faf, + 0x9fb0,0x9fb1,0x9fb2,0x9fb3,0x9fb4,0x9fb5,0x9fb6,0x9fb7, + 0x9fb8,0x9fb9,0x9fba,0x9fbb,0x9fbc,0x9fbd,0x9fbe,0x9fbf, + 0x9fc0,0x9fc1,0x9fc2,0x9fc3,0x9fc4,0x9fc5,0x9fc6,0x9fc7, + 0x9fc8,0x9fc9,0x9fca,0x9fcb,0x9fcc,0x9fcd,0x9fce,0x9fcf, + 0x9fd0,0x9fd1,0x9fd2,0x9fd3,0x9fd4,0x9fd5,0x9fd6,0x9fd7, + 0x9fd8,0x9fd9,0x9fda,0x9fdb,0x9fdc,0x9fdd,0x9fde,0x9fdf, + 0x9fe0,0x9fe1,0x9fe2,0x9fe3,0x9fe4,0x9fe5,0x9fe6,0x9fe7, + 0x9fe8,0x9fe9,0x9fea,0x9feb,0x9fec,0x9fed,0x9fee,0x9fef, + 0x9ff0,0x9ff1,0x9ff2,0x9ff3,0x9ff4,0x9ff5,0x9ff6,0x9ff7, + 0x9ff8,0x9ff9,0x9ffa,0x9ffb,0x9ffc,0x9ffd,0x9ffe,0x9fff, + 0xa000,0xa001,0xa002,0xa003,0xa004,0xa005,0xa006,0xa007, + 0xa008,0xa009,0xa00a,0xa00b,0xa00c,0xa00d,0xa00e,0xa00f, + 0xa010,0xa011,0xa012,0xa013,0xa014,0xa015,0xa016,0xa017, + 0xa018,0xa019,0xa01a,0xa01b,0xa01c,0xa01d,0xa01e,0xa01f, + 0xa020,0xa021,0xa022,0xa023,0xa024,0xa025,0xa026,0xa027, + 0xa028,0xa029,0xa02a,0xa02b,0xa02c,0xa02d,0xa02e,0xa02f, + 0xa030,0xa031,0xa032,0xa033,0xa034,0xa035,0xa036,0xa037, + 0xa038,0xa039,0xa03a,0xa03b,0xa03c,0xa03d,0xa03e,0xa03f, + 0xa040,0xa041,0xa042,0xa043,0xa044,0xa045,0xa046,0xa047, + 0xa048,0xa049,0xa04a,0xa04b,0xa04c,0xa04d,0xa04e,0xa04f, + 0xa050,0xa051,0xa052,0xa053,0xa054,0xa055,0xa056,0xa057, + 0xa058,0xa059,0xa05a,0xa05b,0xa05c,0xa05d,0xa05e,0xa05f, + 0xa060,0xa061,0xa062,0xa063,0xa064,0xa065,0xa066,0xa067, + 0xa068,0xa069,0xa06a,0xa06b,0xa06c,0xa06d,0xa06e,0xa06f, + 0xa070,0xa071,0xa072,0xa073,0xa074,0xa075,0xa076,0xa077, + 0xa078,0xa079,0xa07a,0xa07b,0xa07c,0xa07d,0xa07e,0xa07f, + 0xa080,0xa081,0xa082,0xa083,0xa084,0xa085,0xa086,0xa087, + 0xa088,0xa089,0xa08a,0xa08b,0xa08c,0xa08d,0xa08e,0xa08f, + 0xa090,0xa091,0xa092,0xa093,0xa094,0xa095,0xa096,0xa097, + 0xa098,0xa099,0xa09a,0xa09b,0xa09c,0xa09d,0xa09e,0xa09f, + 0xa0a0,0xa0a1,0xa0a2,0xa0a3,0xa0a4,0xa0a5,0xa0a6,0xa0a7, + 0xa0a8,0xa0a9,0xa0aa,0xa0ab,0xa0ac,0xa0ad,0xa0ae,0xa0af, + 0xa0b0,0xa0b1,0xa0b2,0xa0b3,0xa0b4,0xa0b5,0xa0b6,0xa0b7, + 0xa0b8,0xa0b9,0xa0ba,0xa0bb,0xa0bc,0xa0bd,0xa0be,0xa0bf, + 0xa0c0,0xa0c1,0xa0c2,0xa0c3,0xa0c4,0xa0c5,0xa0c6,0xa0c7, + 0xa0c8,0xa0c9,0xa0ca,0xa0cb,0xa0cc,0xa0cd,0xa0ce,0xa0cf, + 0xa0d0,0xa0d1,0xa0d2,0xa0d3,0xa0d4,0xa0d5,0xa0d6,0xa0d7, + 0xa0d8,0xa0d9,0xa0da,0xa0db,0xa0dc,0xa0dd,0xa0de,0xa0df, + 0xa0e0,0xa0e1,0xa0e2,0xa0e3,0xa0e4,0xa0e5,0xa0e6,0xa0e7, + 0xa0e8,0xa0e9,0xa0ea,0xa0eb,0xa0ec,0xa0ed,0xa0ee,0xa0ef, + 0xa0f0,0xa0f1,0xa0f2,0xa0f3,0xa0f4,0xa0f5,0xa0f6,0xa0f7, + 0xa0f8,0xa0f9,0xa0fa,0xa0fb,0xa0fc,0xa0fd,0xa0fe,0xa0ff, + 0xa100,0xa101,0xa102,0xa103,0xa104,0xa105,0xa106,0xa107, + 0xa108,0xa109,0xa10a,0xa10b,0xa10c,0xa10d,0xa10e,0xa10f, + 0xa110,0xa111,0xa112,0xa113,0xa114,0xa115,0xa116,0xa117, + 0xa118,0xa119,0xa11a,0xa11b,0xa11c,0xa11d,0xa11e,0xa11f, + 0xa120,0xa121,0xa122,0xa123,0xa124,0xa125,0xa126,0xa127, + 0xa128,0xa129,0xa12a,0xa12b,0xa12c,0xa12d,0xa12e,0xa12f, + 0xa130,0xa131,0xa132,0xa133,0xa134,0xa135,0xa136,0xa137, + 0xa138,0xa139,0xa13a,0xa13b,0xa13c,0xa13d,0xa13e,0xa13f, + 0xa140,0xa141,0xa142,0xa143,0xa144,0xa145,0xa146,0xa147, + 0xa148,0xa149,0xa14a,0xa14b,0xa14c,0xa14d,0xa14e,0xa14f, + 0xa150,0xa151,0xa152,0xa153,0xa154,0xa155,0xa156,0xa157, + 0xa158,0xa159,0xa15a,0xa15b,0xa15c,0xa15d,0xa15e,0xa15f, + 0xa160,0xa161,0xa162,0xa163,0xa164,0xa165,0xa166,0xa167, + 0xa168,0xa169,0xa16a,0xa16b,0xa16c,0xa16d,0xa16e,0xa16f, + 0xa170,0xa171,0xa172,0xa173,0xa174,0xa175,0xa176,0xa177, + 0xa178,0xa179,0xa17a,0xa17b,0xa17c,0xa17d,0xa17e,0xa17f, + 0xa180,0xa181,0xa182,0xa183,0xa184,0xa185,0xa186,0xa187, + 0xa188,0xa189,0xa18a,0xa18b,0xa18c,0xa18d,0xa18e,0xa18f, + 0xa190,0xa191,0xa192,0xa193,0xa194,0xa195,0xa196,0xa197, + 0xa198,0xa199,0xa19a,0xa19b,0xa19c,0xa19d,0xa19e,0xa19f, + 0xa1a0,0xa1a1,0xa1a2,0xa1a3,0xa1a4,0xa1a5,0xa1a6,0xa1a7, + 0xa1a8,0xa1a9,0xa1aa,0xa1ab,0xa1ac,0xa1ad,0xa1ae,0xa1af, + 0xa1b0,0xa1b1,0xa1b2,0xa1b3,0xa1b4,0xa1b5,0xa1b6,0xa1b7, + 0xa1b8,0xa1b9,0xa1ba,0xa1bb,0xa1bc,0xa1bd,0xa1be,0xa1bf, + 0xa1c0,0xa1c1,0xa1c2,0xa1c3,0xa1c4,0xa1c5,0xa1c6,0xa1c7, + 0xa1c8,0xa1c9,0xa1ca,0xa1cb,0xa1cc,0xa1cd,0xa1ce,0xa1cf, + 0xa1d0,0xa1d1,0xa1d2,0xa1d3,0xa1d4,0xa1d5,0xa1d6,0xa1d7, + 0xa1d8,0xa1d9,0xa1da,0xa1db,0xa1dc,0xa1dd,0xa1de,0xa1df, + 0xa1e0,0xa1e1,0xa1e2,0xa1e3,0xa1e4,0xa1e5,0xa1e6,0xa1e7, + 0xa1e8,0xa1e9,0xa1ea,0xa1eb,0xa1ec,0xa1ed,0xa1ee,0xa1ef, + 0xa1f0,0xa1f1,0xa1f2,0xa1f3,0xa1f4,0xa1f5,0xa1f6,0xa1f7, + 0xa1f8,0xa1f9,0xa1fa,0xa1fb,0xa1fc,0xa1fd,0xa1fe,0xa1ff, + 0xa200,0xa201,0xa202,0xa203,0xa204,0xa205,0xa206,0xa207, + 0xa208,0xa209,0xa20a,0xa20b,0xa20c,0xa20d,0xa20e,0xa20f, + 0xa210,0xa211,0xa212,0xa213,0xa214,0xa215,0xa216,0xa217, + 0xa218,0xa219,0xa21a,0xa21b,0xa21c,0xa21d,0xa21e,0xa21f, + 0xa220,0xa221,0xa222,0xa223,0xa224,0xa225,0xa226,0xa227, + 0xa228,0xa229,0xa22a,0xa22b,0xa22c,0xa22d,0xa22e,0xa22f, + 0xa230,0xa231,0xa232,0xa233,0xa234,0xa235,0xa236,0xa237, + 0xa238,0xa239,0xa23a,0xa23b,0xa23c,0xa23d,0xa23e,0xa23f, + 0xa240,0xa241,0xa242,0xa243,0xa244,0xa245,0xa246,0xa247, + 0xa248,0xa249,0xa24a,0xa24b,0xa24c,0xa24d,0xa24e,0xa24f, + 0xa250,0xa251,0xa252,0xa253,0xa254,0xa255,0xa256,0xa257, + 0xa258,0xa259,0xa25a,0xa25b,0xa25c,0xa25d,0xa25e,0xa25f, + 0xa260,0xa261,0xa262,0xa263,0xa264,0xa265,0xa266,0xa267, + 0xa268,0xa269,0xa26a,0xa26b,0xa26c,0xa26d,0xa26e,0xa26f, + 0xa270,0xa271,0xa272,0xa273,0xa274,0xa275,0xa276,0xa277, + 0xa278,0xa279,0xa27a,0xa27b,0xa27c,0xa27d,0xa27e,0xa27f, + 0xa280,0xa281,0xa282,0xa283,0xa284,0xa285,0xa286,0xa287, + 0xa288,0xa289,0xa28a,0xa28b,0xa28c,0xa28d,0xa28e,0xa28f, + 0xa290,0xa291,0xa292,0xa293,0xa294,0xa295,0xa296,0xa297, + 0xa298,0xa299,0xa29a,0xa29b,0xa29c,0xa29d,0xa29e,0xa29f, + 0xa2a0,0xa2a1,0xa2a2,0xa2a3,0xa2a4,0xa2a5,0xa2a6,0xa2a7, + 0xa2a8,0xa2a9,0xa2aa,0xa2ab,0xa2ac,0xa2ad,0xa2ae,0xa2af, + 0xa2b0,0xa2b1,0xa2b2,0xa2b3,0xa2b4,0xa2b5,0xa2b6,0xa2b7, + 0xa2b8,0xa2b9,0xa2ba,0xa2bb,0xa2bc,0xa2bd,0xa2be,0xa2bf, + 0xa2c0,0xa2c1,0xa2c2,0xa2c3,0xa2c4,0xa2c5,0xa2c6,0xa2c7, + 0xa2c8,0xa2c9,0xa2ca,0xa2cb,0xa2cc,0xa2cd,0xa2ce,0xa2cf, + 0xa2d0,0xa2d1,0xa2d2,0xa2d3,0xa2d4,0xa2d5,0xa2d6,0xa2d7, + 0xa2d8,0xa2d9,0xa2da,0xa2db,0xa2dc,0xa2dd,0xa2de,0xa2df, + 0xa2e0,0xa2e1,0xa2e2,0xa2e3,0xa2e4,0xa2e5,0xa2e6,0xa2e7, + 0xa2e8,0xa2e9,0xa2ea,0xa2eb,0xa2ec,0xa2ed,0xa2ee,0xa2ef, + 0xa2f0,0xa2f1,0xa2f2,0xa2f3,0xa2f4,0xa2f5,0xa2f6,0xa2f7, + 0xa2f8,0xa2f9,0xa2fa,0xa2fb,0xa2fc,0xa2fd,0xa2fe,0xa2ff, + 0xa300,0xa301,0xa302,0xa303,0xa304,0xa305,0xa306,0xa307, + 0xa308,0xa309,0xa30a,0xa30b,0xa30c,0xa30d,0xa30e,0xa30f, + 0xa310,0xa311,0xa312,0xa313,0xa314,0xa315,0xa316,0xa317, + 0xa318,0xa319,0xa31a,0xa31b,0xa31c,0xa31d,0xa31e,0xa31f, + 0xa320,0xa321,0xa322,0xa323,0xa324,0xa325,0xa326,0xa327, + 0xa328,0xa329,0xa32a,0xa32b,0xa32c,0xa32d,0xa32e,0xa32f, + 0xa330,0xa331,0xa332,0xa333,0xa334,0xa335,0xa336,0xa337, + 0xa338,0xa339,0xa33a,0xa33b,0xa33c,0xa33d,0xa33e,0xa33f, + 0xa340,0xa341,0xa342,0xa343,0xa344,0xa345,0xa346,0xa347, + 0xa348,0xa349,0xa34a,0xa34b,0xa34c,0xa34d,0xa34e,0xa34f, + 0xa350,0xa351,0xa352,0xa353,0xa354,0xa355,0xa356,0xa357, + 0xa358,0xa359,0xa35a,0xa35b,0xa35c,0xa35d,0xa35e,0xa35f, + 0xa360,0xa361,0xa362,0xa363,0xa364,0xa365,0xa366,0xa367, + 0xa368,0xa369,0xa36a,0xa36b,0xa36c,0xa36d,0xa36e,0xa36f, + 0xa370,0xa371,0xa372,0xa373,0xa374,0xa375,0xa376,0xa377, + 0xa378,0xa379,0xa37a,0xa37b,0xa37c,0xa37d,0xa37e,0xa37f, + 0xa380,0xa381,0xa382,0xa383,0xa384,0xa385,0xa386,0xa387, + 0xa388,0xa389,0xa38a,0xa38b,0xa38c,0xa38d,0xa38e,0xa38f, + 0xa390,0xa391,0xa392,0xa393,0xa394,0xa395,0xa396,0xa397, + 0xa398,0xa399,0xa39a,0xa39b,0xa39c,0xa39d,0xa39e,0xa39f, + 0xa3a0,0xa3a1,0xa3a2,0xa3a3,0xa3a4,0xa3a5,0xa3a6,0xa3a7, + 0xa3a8,0xa3a9,0xa3aa,0xa3ab,0xa3ac,0xa3ad,0xa3ae,0xa3af, + 0xa3b0,0xa3b1,0xa3b2,0xa3b3,0xa3b4,0xa3b5,0xa3b6,0xa3b7, + 0xa3b8,0xa3b9,0xa3ba,0xa3bb,0xa3bc,0xa3bd,0xa3be,0xa3bf, + 0xa3c0,0xa3c1,0xa3c2,0xa3c3,0xa3c4,0xa3c5,0xa3c6,0xa3c7, + 0xa3c8,0xa3c9,0xa3ca,0xa3cb,0xa3cc,0xa3cd,0xa3ce,0xa3cf, + 0xa3d0,0xa3d1,0xa3d2,0xa3d3,0xa3d4,0xa3d5,0xa3d6,0xa3d7, + 0xa3d8,0xa3d9,0xa3da,0xa3db,0xa3dc,0xa3dd,0xa3de,0xa3df, + 0xa3e0,0xa3e1,0xa3e2,0xa3e3,0xa3e4,0xa3e5,0xa3e6,0xa3e7, + 0xa3e8,0xa3e9,0xa3ea,0xa3eb,0xa3ec,0xa3ed,0xa3ee,0xa3ef, + 0xa3f0,0xa3f1,0xa3f2,0xa3f3,0xa3f4,0xa3f5,0xa3f6,0xa3f7, + 0xa3f8,0xa3f9,0xa3fa,0xa3fb,0xa3fc,0xa3fd,0xa3fe,0xa3ff, + 0xa400,0xa401,0xa402,0xa403,0xa404,0xa405,0xa406,0xa407, + 0xa408,0xa409,0xa40a,0xa40b,0xa40c,0xa40d,0xa40e,0xa40f, + 0xa410,0xa411,0xa412,0xa413,0xa414,0xa415,0xa416,0xa417, + 0xa418,0xa419,0xa41a,0xa41b,0xa41c,0xa41d,0xa41e,0xa41f, + 0xa420,0xa421,0xa422,0xa423,0xa424,0xa425,0xa426,0xa427, + 0xa428,0xa429,0xa42a,0xa42b,0xa42c,0xa42d,0xa42e,0xa42f, + 0xa430,0xa431,0xa432,0xa433,0xa434,0xa435,0xa436,0xa437, + 0xa438,0xa439,0xa43a,0xa43b,0xa43c,0xa43d,0xa43e,0xa43f, + 0xa440,0xa441,0xa442,0xa443,0xa444,0xa445,0xa446,0xa447, + 0xa448,0xa449,0xa44a,0xa44b,0xa44c,0xa44d,0xa44e,0xa44f, + 0xa450,0xa451,0xa452,0xa453,0xa454,0xa455,0xa456,0xa457, + 0xa458,0xa459,0xa45a,0xa45b,0xa45c,0xa45d,0xa45e,0xa45f, + 0xa460,0xa461,0xa462,0xa463,0xa464,0xa465,0xa466,0xa467, + 0xa468,0xa469,0xa46a,0xa46b,0xa46c,0xa46d,0xa46e,0xa46f, + 0xa470,0xa471,0xa472,0xa473,0xa474,0xa475,0xa476,0xa477, + 0xa478,0xa479,0xa47a,0xa47b,0xa47c,0xa47d,0xa47e,0xa47f, + 0xa480,0xa481,0xa482,0xa483,0xa484,0xa485,0xa486,0xa487, + 0xa488,0xa489,0xa48a,0xa48b,0xa48c,0xa48d,0xa48e,0xa48f, + 0xa490,0xa491,0xa492,0xa493,0xa494,0xa495,0xa496,0xa497, + 0xa498,0xa499,0xa49a,0xa49b,0xa49c,0xa49d,0xa49e,0xa49f, + 0xa4a0,0xa4a1,0xa4a2,0xa4a3,0xa4a4,0xa4a5,0xa4a6,0xa4a7, + 0xa4a8,0xa4a9,0xa4aa,0xa4ab,0xa4ac,0xa4ad,0xa4ae,0xa4af, + 0xa4b0,0xa4b1,0xa4b2,0xa4b3,0xa4b4,0xa4b5,0xa4b6,0xa4b7, + 0xa4b8,0xa4b9,0xa4ba,0xa4bb,0xa4bc,0xa4bd,0xa4be,0xa4bf, + 0xa4c0,0xa4c1,0xa4c2,0xa4c3,0xa4c4,0xa4c5,0xa4c6,0xa4c7, + 0xa4c8,0xa4c9,0xa4ca,0xa4cb,0xa4cc,0xa4cd,0xa4ce,0xa4cf, + 0xa4d0,0xa4d1,0xa4d2,0xa4d3,0xa4d4,0xa4d5,0xa4d6,0xa4d7, + 0xa4d8,0xa4d9,0xa4da,0xa4db,0xa4dc,0xa4dd,0xa4de,0xa4df, + 0xa4e0,0xa4e1,0xa4e2,0xa4e3,0xa4e4,0xa4e5,0xa4e6,0xa4e7, + 0xa4e8,0xa4e9,0xa4ea,0xa4eb,0xa4ec,0xa4ed,0xa4ee,0xa4ef, + 0xa4f0,0xa4f1,0xa4f2,0xa4f3,0xa4f4,0xa4f5,0xa4f6,0xa4f7, + 0xa4f8,0xa4f9,0xa4fa,0xa4fb,0xa4fc,0xa4fd,0xa4fe,0xa4ff, + 0xa500,0xa501,0xa502,0xa503,0xa504,0xa505,0xa506,0xa507, + 0xa508,0xa509,0xa50a,0xa50b,0xa50c,0xa50d,0xa50e,0xa50f, + 0xa510,0xa511,0xa512,0xa513,0xa514,0xa515,0xa516,0xa517, + 0xa518,0xa519,0xa51a,0xa51b,0xa51c,0xa51d,0xa51e,0xa51f, + 0xa520,0xa521,0xa522,0xa523,0xa524,0xa525,0xa526,0xa527, + 0xa528,0xa529,0xa52a,0xa52b,0xa52c,0xa52d,0xa52e,0xa52f, + 0xa530,0xa531,0xa532,0xa533,0xa534,0xa535,0xa536,0xa537, + 0xa538,0xa539,0xa53a,0xa53b,0xa53c,0xa53d,0xa53e,0xa53f, + 0xa540,0xa541,0xa542,0xa543,0xa544,0xa545,0xa546,0xa547, + 0xa548,0xa549,0xa54a,0xa54b,0xa54c,0xa54d,0xa54e,0xa54f, + 0xa550,0xa551,0xa552,0xa553,0xa554,0xa555,0xa556,0xa557, + 0xa558,0xa559,0xa55a,0xa55b,0xa55c,0xa55d,0xa55e,0xa55f, + 0xa560,0xa561,0xa562,0xa563,0xa564,0xa565,0xa566,0xa567, + 0xa568,0xa569,0xa56a,0xa56b,0xa56c,0xa56d,0xa56e,0xa56f, + 0xa570,0xa571,0xa572,0xa573,0xa574,0xa575,0xa576,0xa577, + 0xa578,0xa579,0xa57a,0xa57b,0xa57c,0xa57d,0xa57e,0xa57f, + 0xa580,0xa581,0xa582,0xa583,0xa584,0xa585,0xa586,0xa587, + 0xa588,0xa589,0xa58a,0xa58b,0xa58c,0xa58d,0xa58e,0xa58f, + 0xa590,0xa591,0xa592,0xa593,0xa594,0xa595,0xa596,0xa597, + 0xa598,0xa599,0xa59a,0xa59b,0xa59c,0xa59d,0xa59e,0xa59f, + 0xa5a0,0xa5a1,0xa5a2,0xa5a3,0xa5a4,0xa5a5,0xa5a6,0xa5a7, + 0xa5a8,0xa5a9,0xa5aa,0xa5ab,0xa5ac,0xa5ad,0xa5ae,0xa5af, + 0xa5b0,0xa5b1,0xa5b2,0xa5b3,0xa5b4,0xa5b5,0xa5b6,0xa5b7, + 0xa5b8,0xa5b9,0xa5ba,0xa5bb,0xa5bc,0xa5bd,0xa5be,0xa5bf, + 0xa5c0,0xa5c1,0xa5c2,0xa5c3,0xa5c4,0xa5c5,0xa5c6,0xa5c7, + 0xa5c8,0xa5c9,0xa5ca,0xa5cb,0xa5cc,0xa5cd,0xa5ce,0xa5cf, + 0xa5d0,0xa5d1,0xa5d2,0xa5d3,0xa5d4,0xa5d5,0xa5d6,0xa5d7, + 0xa5d8,0xa5d9,0xa5da,0xa5db,0xa5dc,0xa5dd,0xa5de,0xa5df, + 0xa5e0,0xa5e1,0xa5e2,0xa5e3,0xa5e4,0xa5e5,0xa5e6,0xa5e7, + 0xa5e8,0xa5e9,0xa5ea,0xa5eb,0xa5ec,0xa5ed,0xa5ee,0xa5ef, + 0xa5f0,0xa5f1,0xa5f2,0xa5f3,0xa5f4,0xa5f5,0xa5f6,0xa5f7, + 0xa5f8,0xa5f9,0xa5fa,0xa5fb,0xa5fc,0xa5fd,0xa5fe,0xa5ff, + 0xa600,0xa601,0xa602,0xa603,0xa604,0xa605,0xa606,0xa607, + 0xa608,0xa609,0xa60a,0xa60b,0xa60c,0xa60d,0xa60e,0xa60f, + 0xa610,0xa611,0xa612,0xa613,0xa614,0xa615,0xa616,0xa617, + 0xa618,0xa619,0xa61a,0xa61b,0xa61c,0xa61d,0xa61e,0xa61f, + 0xa620,0xa621,0xa622,0xa623,0xa624,0xa625,0xa626,0xa627, + 0xa628,0xa629,0xa62a,0xa62b,0xa62c,0xa62d,0xa62e,0xa62f, + 0xa630,0xa631,0xa632,0xa633,0xa634,0xa635,0xa636,0xa637, + 0xa638,0xa639,0xa63a,0xa63b,0xa63c,0xa63d,0xa63e,0xa63f, + 0xa640,0xa641,0xa642,0xa643,0xa644,0xa645,0xa646,0xa647, + 0xa648,0xa649,0xa64a,0xa64b,0xa64c,0xa64d,0xa64e,0xa64f, + 0xa650,0xa651,0xa652,0xa653,0xa654,0xa655,0xa656,0xa657, + 0xa658,0xa659,0xa65a,0xa65b,0xa65c,0xa65d,0xa65e,0xa65f, + 0xa660,0xa661,0xa662,0xa663,0xa664,0xa665,0xa666,0xa667, + 0xa668,0xa669,0xa66a,0xa66b,0xa66c,0xa66d,0xa66e,0xa66f, + 0xa670,0xa671,0xa672,0xa673,0xa674,0xa675,0xa676,0xa677, + 0xa678,0xa679,0xa67a,0xa67b,0xa67c,0xa67d,0xa67e,0xa67f, + 0xa680,0xa681,0xa682,0xa683,0xa684,0xa685,0xa686,0xa687, + 0xa688,0xa689,0xa68a,0xa68b,0xa68c,0xa68d,0xa68e,0xa68f, + 0xa690,0xa691,0xa692,0xa693,0xa694,0xa695,0xa696,0xa697, + 0xa698,0xa699,0xa69a,0xa69b,0xa69c,0xa69d,0xa69e,0xa69f, + 0xa6a0,0xa6a1,0xa6a2,0xa6a3,0xa6a4,0xa6a5,0xa6a6,0xa6a7, + 0xa6a8,0xa6a9,0xa6aa,0xa6ab,0xa6ac,0xa6ad,0xa6ae,0xa6af, + 0xa6b0,0xa6b1,0xa6b2,0xa6b3,0xa6b4,0xa6b5,0xa6b6,0xa6b7, + 0xa6b8,0xa6b9,0xa6ba,0xa6bb,0xa6bc,0xa6bd,0xa6be,0xa6bf, + 0xa6c0,0xa6c1,0xa6c2,0xa6c3,0xa6c4,0xa6c5,0xa6c6,0xa6c7, + 0xa6c8,0xa6c9,0xa6ca,0xa6cb,0xa6cc,0xa6cd,0xa6ce,0xa6cf, + 0xa6d0,0xa6d1,0xa6d2,0xa6d3,0xa6d4,0xa6d5,0xa6d6,0xa6d7, + 0xa6d8,0xa6d9,0xa6da,0xa6db,0xa6dc,0xa6dd,0xa6de,0xa6df, + 0xa6e0,0xa6e1,0xa6e2,0xa6e3,0xa6e4,0xa6e5,0xa6e6,0xa6e7, + 0xa6e8,0xa6e9,0xa6ea,0xa6eb,0xa6ec,0xa6ed,0xa6ee,0xa6ef, + 0xa6f0,0xa6f1,0xa6f2,0xa6f3,0xa6f4,0xa6f5,0xa6f6,0xa6f7, + 0xa6f8,0xa6f9,0xa6fa,0xa6fb,0xa6fc,0xa6fd,0xa6fe,0xa6ff, + 0xa700,0xa701,0xa702,0xa703,0xa704,0xa705,0xa706,0xa707, + 0xa708,0xa709,0xa70a,0xa70b,0xa70c,0xa70d,0xa70e,0xa70f, + 0xa710,0xa711,0xa712,0xa713,0xa714,0xa715,0xa716,0xa717, + 0xa718,0xa719,0xa71a,0xa71b,0xa71c,0xa71d,0xa71e,0xa71f, + 0xa720,0xa721,0xa722,0xa723,0xa724,0xa725,0xa726,0xa727, + 0xa728,0xa729,0xa72a,0xa72b,0xa72c,0xa72d,0xa72e,0xa72f, + 0xa730,0xa731,0xa732,0xa733,0xa734,0xa735,0xa736,0xa737, + 0xa738,0xa739,0xa73a,0xa73b,0xa73c,0xa73d,0xa73e,0xa73f, + 0xa740,0xa741,0xa742,0xa743,0xa744,0xa745,0xa746,0xa747, + 0xa748,0xa749,0xa74a,0xa74b,0xa74c,0xa74d,0xa74e,0xa74f, + 0xa750,0xa751,0xa752,0xa753,0xa754,0xa755,0xa756,0xa757, + 0xa758,0xa759,0xa75a,0xa75b,0xa75c,0xa75d,0xa75e,0xa75f, + 0xa760,0xa761,0xa762,0xa763,0xa764,0xa765,0xa766,0xa767, + 0xa768,0xa769,0xa76a,0xa76b,0xa76c,0xa76d,0xa76e,0xa76f, + 0xa770,0xa771,0xa772,0xa773,0xa774,0xa775,0xa776,0xa777, + 0xa778,0xa779,0xa77a,0xa77b,0xa77c,0xa77d,0xa77e,0xa77f, + 0xa780,0xa781,0xa782,0xa783,0xa784,0xa785,0xa786,0xa787, + 0xa788,0xa789,0xa78a,0xa78b,0xa78c,0xa78d,0xa78e,0xa78f, + 0xa790,0xa791,0xa792,0xa793,0xa794,0xa795,0xa796,0xa797, + 0xa798,0xa799,0xa79a,0xa79b,0xa79c,0xa79d,0xa79e,0xa79f, + 0xa7a0,0xa7a1,0xa7a2,0xa7a3,0xa7a4,0xa7a5,0xa7a6,0xa7a7, + 0xa7a8,0xa7a9,0xa7aa,0xa7ab,0xa7ac,0xa7ad,0xa7ae,0xa7af, + 0xa7b0,0xa7b1,0xa7b2,0xa7b3,0xa7b4,0xa7b5,0xa7b6,0xa7b7, + 0xa7b8,0xa7b9,0xa7ba,0xa7bb,0xa7bc,0xa7bd,0xa7be,0xa7bf, + 0xa7c0,0xa7c1,0xa7c2,0xa7c3,0xa7c4,0xa7c5,0xa7c6,0xa7c7, + 0xa7c8,0xa7c9,0xa7ca,0xa7cb,0xa7cc,0xa7cd,0xa7ce,0xa7cf, + 0xa7d0,0xa7d1,0xa7d2,0xa7d3,0xa7d4,0xa7d5,0xa7d6,0xa7d7, + 0xa7d8,0xa7d9,0xa7da,0xa7db,0xa7dc,0xa7dd,0xa7de,0xa7df, + 0xa7e0,0xa7e1,0xa7e2,0xa7e3,0xa7e4,0xa7e5,0xa7e6,0xa7e7, + 0xa7e8,0xa7e9,0xa7ea,0xa7eb,0xa7ec,0xa7ed,0xa7ee,0xa7ef, + 0xa7f0,0xa7f1,0xa7f2,0xa7f3,0xa7f4,0xa7f5,0xa7f6,0xa7f7, + 0xa7f8,0xa7f9,0xa7fa,0xa7fb,0xa7fc,0xa7fd,0xa7fe,0xa7ff, + 0xa800,0xa801,0xa802,0xa803,0xa804,0xa805,0xa806,0xa807, + 0xa808,0xa809,0xa80a,0xa80b,0xa80c,0xa80d,0xa80e,0xa80f, + 0xa810,0xa811,0xa812,0xa813,0xa814,0xa815,0xa816,0xa817, + 0xa818,0xa819,0xa81a,0xa81b,0xa81c,0xa81d,0xa81e,0xa81f, + 0xa820,0xa821,0xa822,0xa823,0xa824,0xa825,0xa826,0xa827, + 0xa828,0xa829,0xa82a,0xa82b,0xa82c,0xa82d,0xa82e,0xa82f, + 0xa830,0xa831,0xa832,0xa833,0xa834,0xa835,0xa836,0xa837, + 0xa838,0xa839,0xa83a,0xa83b,0xa83c,0xa83d,0xa83e,0xa83f, + 0xa840,0xa841,0xa842,0xa843,0xa844,0xa845,0xa846,0xa847, + 0xa848,0xa849,0xa84a,0xa84b,0xa84c,0xa84d,0xa84e,0xa84f, + 0xa850,0xa851,0xa852,0xa853,0xa854,0xa855,0xa856,0xa857, + 0xa858,0xa859,0xa85a,0xa85b,0xa85c,0xa85d,0xa85e,0xa85f, + 0xa860,0xa861,0xa862,0xa863,0xa864,0xa865,0xa866,0xa867, + 0xa868,0xa869,0xa86a,0xa86b,0xa86c,0xa86d,0xa86e,0xa86f, + 0xa870,0xa871,0xa872,0xa873,0xa874,0xa875,0xa876,0xa877, + 0xa878,0xa879,0xa87a,0xa87b,0xa87c,0xa87d,0xa87e,0xa87f, + 0xa880,0xa881,0xa882,0xa883,0xa884,0xa885,0xa886,0xa887, + 0xa888,0xa889,0xa88a,0xa88b,0xa88c,0xa88d,0xa88e,0xa88f, + 0xa890,0xa891,0xa892,0xa893,0xa894,0xa895,0xa896,0xa897, + 0xa898,0xa899,0xa89a,0xa89b,0xa89c,0xa89d,0xa89e,0xa89f, + 0xa8a0,0xa8a1,0xa8a2,0xa8a3,0xa8a4,0xa8a5,0xa8a6,0xa8a7, + 0xa8a8,0xa8a9,0xa8aa,0xa8ab,0xa8ac,0xa8ad,0xa8ae,0xa8af, + 0xa8b0,0xa8b1,0xa8b2,0xa8b3,0xa8b4,0xa8b5,0xa8b6,0xa8b7, + 0xa8b8,0xa8b9,0xa8ba,0xa8bb,0xa8bc,0xa8bd,0xa8be,0xa8bf, + 0xa8c0,0xa8c1,0xa8c2,0xa8c3,0xa8c4,0xa8c5,0xa8c6,0xa8c7, + 0xa8c8,0xa8c9,0xa8ca,0xa8cb,0xa8cc,0xa8cd,0xa8ce,0xa8cf, + 0xa8d0,0xa8d1,0xa8d2,0xa8d3,0xa8d4,0xa8d5,0xa8d6,0xa8d7, + 0xa8d8,0xa8d9,0xa8da,0xa8db,0xa8dc,0xa8dd,0xa8de,0xa8df, + 0xa8e0,0xa8e1,0xa8e2,0xa8e3,0xa8e4,0xa8e5,0xa8e6,0xa8e7, + 0xa8e8,0xa8e9,0xa8ea,0xa8eb,0xa8ec,0xa8ed,0xa8ee,0xa8ef, + 0xa8f0,0xa8f1,0xa8f2,0xa8f3,0xa8f4,0xa8f5,0xa8f6,0xa8f7, + 0xa8f8,0xa8f9,0xa8fa,0xa8fb,0xa8fc,0xa8fd,0xa8fe,0xa8ff, + 0xa900,0xa901,0xa902,0xa903,0xa904,0xa905,0xa906,0xa907, + 0xa908,0xa909,0xa90a,0xa90b,0xa90c,0xa90d,0xa90e,0xa90f, + 0xa910,0xa911,0xa912,0xa913,0xa914,0xa915,0xa916,0xa917, + 0xa918,0xa919,0xa91a,0xa91b,0xa91c,0xa91d,0xa91e,0xa91f, + 0xa920,0xa921,0xa922,0xa923,0xa924,0xa925,0xa926,0xa927, + 0xa928,0xa929,0xa92a,0xa92b,0xa92c,0xa92d,0xa92e,0xa92f, + 0xa930,0xa931,0xa932,0xa933,0xa934,0xa935,0xa936,0xa937, + 0xa938,0xa939,0xa93a,0xa93b,0xa93c,0xa93d,0xa93e,0xa93f, + 0xa940,0xa941,0xa942,0xa943,0xa944,0xa945,0xa946,0xa947, + 0xa948,0xa949,0xa94a,0xa94b,0xa94c,0xa94d,0xa94e,0xa94f, + 0xa950,0xa951,0xa952,0xa953,0xa954,0xa955,0xa956,0xa957, + 0xa958,0xa959,0xa95a,0xa95b,0xa95c,0xa95d,0xa95e,0xa95f, + 0xa960,0xa961,0xa962,0xa963,0xa964,0xa965,0xa966,0xa967, + 0xa968,0xa969,0xa96a,0xa96b,0xa96c,0xa96d,0xa96e,0xa96f, + 0xa970,0xa971,0xa972,0xa973,0xa974,0xa975,0xa976,0xa977, + 0xa978,0xa979,0xa97a,0xa97b,0xa97c,0xa97d,0xa97e,0xa97f, + 0xa980,0xa981,0xa982,0xa983,0xa984,0xa985,0xa986,0xa987, + 0xa988,0xa989,0xa98a,0xa98b,0xa98c,0xa98d,0xa98e,0xa98f, + 0xa990,0xa991,0xa992,0xa993,0xa994,0xa995,0xa996,0xa997, + 0xa998,0xa999,0xa99a,0xa99b,0xa99c,0xa99d,0xa99e,0xa99f, + 0xa9a0,0xa9a1,0xa9a2,0xa9a3,0xa9a4,0xa9a5,0xa9a6,0xa9a7, + 0xa9a8,0xa9a9,0xa9aa,0xa9ab,0xa9ac,0xa9ad,0xa9ae,0xa9af, + 0xa9b0,0xa9b1,0xa9b2,0xa9b3,0xa9b4,0xa9b5,0xa9b6,0xa9b7, + 0xa9b8,0xa9b9,0xa9ba,0xa9bb,0xa9bc,0xa9bd,0xa9be,0xa9bf, + 0xa9c0,0xa9c1,0xa9c2,0xa9c3,0xa9c4,0xa9c5,0xa9c6,0xa9c7, + 0xa9c8,0xa9c9,0xa9ca,0xa9cb,0xa9cc,0xa9cd,0xa9ce,0xa9cf, + 0xa9d0,0xa9d1,0xa9d2,0xa9d3,0xa9d4,0xa9d5,0xa9d6,0xa9d7, + 0xa9d8,0xa9d9,0xa9da,0xa9db,0xa9dc,0xa9dd,0xa9de,0xa9df, + 0xa9e0,0xa9e1,0xa9e2,0xa9e3,0xa9e4,0xa9e5,0xa9e6,0xa9e7, + 0xa9e8,0xa9e9,0xa9ea,0xa9eb,0xa9ec,0xa9ed,0xa9ee,0xa9ef, + 0xa9f0,0xa9f1,0xa9f2,0xa9f3,0xa9f4,0xa9f5,0xa9f6,0xa9f7, + 0xa9f8,0xa9f9,0xa9fa,0xa9fb,0xa9fc,0xa9fd,0xa9fe,0xa9ff, + 0xaa00,0xaa01,0xaa02,0xaa03,0xaa04,0xaa05,0xaa06,0xaa07, + 0xaa08,0xaa09,0xaa0a,0xaa0b,0xaa0c,0xaa0d,0xaa0e,0xaa0f, + 0xaa10,0xaa11,0xaa12,0xaa13,0xaa14,0xaa15,0xaa16,0xaa17, + 0xaa18,0xaa19,0xaa1a,0xaa1b,0xaa1c,0xaa1d,0xaa1e,0xaa1f, + 0xaa20,0xaa21,0xaa22,0xaa23,0xaa24,0xaa25,0xaa26,0xaa27, + 0xaa28,0xaa29,0xaa2a,0xaa2b,0xaa2c,0xaa2d,0xaa2e,0xaa2f, + 0xaa30,0xaa31,0xaa32,0xaa33,0xaa34,0xaa35,0xaa36,0xaa37, + 0xaa38,0xaa39,0xaa3a,0xaa3b,0xaa3c,0xaa3d,0xaa3e,0xaa3f, + 0xaa40,0xaa41,0xaa42,0xaa43,0xaa44,0xaa45,0xaa46,0xaa47, + 0xaa48,0xaa49,0xaa4a,0xaa4b,0xaa4c,0xaa4d,0xaa4e,0xaa4f, + 0xaa50,0xaa51,0xaa52,0xaa53,0xaa54,0xaa55,0xaa56,0xaa57, + 0xaa58,0xaa59,0xaa5a,0xaa5b,0xaa5c,0xaa5d,0xaa5e,0xaa5f, + 0xaa60,0xaa61,0xaa62,0xaa63,0xaa64,0xaa65,0xaa66,0xaa67, + 0xaa68,0xaa69,0xaa6a,0xaa6b,0xaa6c,0xaa6d,0xaa6e,0xaa6f, + 0xaa70,0xaa71,0xaa72,0xaa73,0xaa74,0xaa75,0xaa76,0xaa77, + 0xaa78,0xaa79,0xaa7a,0xaa7b,0xaa7c,0xaa7d,0xaa7e,0xaa7f, + 0xaa80,0xaa81,0xaa82,0xaa83,0xaa84,0xaa85,0xaa86,0xaa87, + 0xaa88,0xaa89,0xaa8a,0xaa8b,0xaa8c,0xaa8d,0xaa8e,0xaa8f, + 0xaa90,0xaa91,0xaa92,0xaa93,0xaa94,0xaa95,0xaa96,0xaa97, + 0xaa98,0xaa99,0xaa9a,0xaa9b,0xaa9c,0xaa9d,0xaa9e,0xaa9f, + 0xaaa0,0xaaa1,0xaaa2,0xaaa3,0xaaa4,0xaaa5,0xaaa6,0xaaa7, + 0xaaa8,0xaaa9,0xaaaa,0xaaab,0xaaac,0xaaad,0xaaae,0xaaaf, + 0xaab0,0xaab1,0xaab2,0xaab3,0xaab4,0xaab5,0xaab6,0xaab7, + 0xaab8,0xaab9,0xaaba,0xaabb,0xaabc,0xaabd,0xaabe,0xaabf, + 0xaac0,0xaac1,0xaac2,0xaac3,0xaac4,0xaac5,0xaac6,0xaac7, + 0xaac8,0xaac9,0xaaca,0xaacb,0xaacc,0xaacd,0xaace,0xaacf, + 0xaad0,0xaad1,0xaad2,0xaad3,0xaad4,0xaad5,0xaad6,0xaad7, + 0xaad8,0xaad9,0xaada,0xaadb,0xaadc,0xaadd,0xaade,0xaadf, + 0xaae0,0xaae1,0xaae2,0xaae3,0xaae4,0xaae5,0xaae6,0xaae7, + 0xaae8,0xaae9,0xaaea,0xaaeb,0xaaec,0xaaed,0xaaee,0xaaef, + 0xaaf0,0xaaf1,0xaaf2,0xaaf3,0xaaf4,0xaaf5,0xaaf6,0xaaf7, + 0xaaf8,0xaaf9,0xaafa,0xaafb,0xaafc,0xaafd,0xaafe,0xaaff, + 0xab00,0xab01,0xab02,0xab03,0xab04,0xab05,0xab06,0xab07, + 0xab08,0xab09,0xab0a,0xab0b,0xab0c,0xab0d,0xab0e,0xab0f, + 0xab10,0xab11,0xab12,0xab13,0xab14,0xab15,0xab16,0xab17, + 0xab18,0xab19,0xab1a,0xab1b,0xab1c,0xab1d,0xab1e,0xab1f, + 0xab20,0xab21,0xab22,0xab23,0xab24,0xab25,0xab26,0xab27, + 0xab28,0xab29,0xab2a,0xab2b,0xab2c,0xab2d,0xab2e,0xab2f, + 0xab30,0xab31,0xab32,0xab33,0xab34,0xab35,0xab36,0xab37, + 0xab38,0xab39,0xab3a,0xab3b,0xab3c,0xab3d,0xab3e,0xab3f, + 0xab40,0xab41,0xab42,0xab43,0xab44,0xab45,0xab46,0xab47, + 0xab48,0xab49,0xab4a,0xab4b,0xab4c,0xab4d,0xab4e,0xab4f, + 0xab50,0xab51,0xab52,0xab53,0xab54,0xab55,0xab56,0xab57, + 0xab58,0xab59,0xab5a,0xab5b,0xab5c,0xab5d,0xab5e,0xab5f, + 0xab60,0xab61,0xab62,0xab63,0xab64,0xab65,0xab66,0xab67, + 0xab68,0xab69,0xab6a,0xab6b,0xab6c,0xab6d,0xab6e,0xab6f, + 0xab70,0xab71,0xab72,0xab73,0xab74,0xab75,0xab76,0xab77, + 0xab78,0xab79,0xab7a,0xab7b,0xab7c,0xab7d,0xab7e,0xab7f, + 0xab80,0xab81,0xab82,0xab83,0xab84,0xab85,0xab86,0xab87, + 0xab88,0xab89,0xab8a,0xab8b,0xab8c,0xab8d,0xab8e,0xab8f, + 0xab90,0xab91,0xab92,0xab93,0xab94,0xab95,0xab96,0xab97, + 0xab98,0xab99,0xab9a,0xab9b,0xab9c,0xab9d,0xab9e,0xab9f, + 0xaba0,0xaba1,0xaba2,0xaba3,0xaba4,0xaba5,0xaba6,0xaba7, + 0xaba8,0xaba9,0xabaa,0xabab,0xabac,0xabad,0xabae,0xabaf, + 0xabb0,0xabb1,0xabb2,0xabb3,0xabb4,0xabb5,0xabb6,0xabb7, + 0xabb8,0xabb9,0xabba,0xabbb,0xabbc,0xabbd,0xabbe,0xabbf, + 0xabc0,0xabc1,0xabc2,0xabc3,0xabc4,0xabc5,0xabc6,0xabc7, + 0xabc8,0xabc9,0xabca,0xabcb,0xabcc,0xabcd,0xabce,0xabcf, + 0xabd0,0xabd1,0xabd2,0xabd3,0xabd4,0xabd5,0xabd6,0xabd7, + 0xabd8,0xabd9,0xabda,0xabdb,0xabdc,0xabdd,0xabde,0xabdf, + 0xabe0,0xabe1,0xabe2,0xabe3,0xabe4,0xabe5,0xabe6,0xabe7, + 0xabe8,0xabe9,0xabea,0xabeb,0xabec,0xabed,0xabee,0xabef, + 0xabf0,0xabf1,0xabf2,0xabf3,0xabf4,0xabf5,0xabf6,0xabf7, + 0xabf8,0xabf9,0xabfa,0xabfb,0xabfc,0xabfd,0xabfe,0xabff, + 0xac00,0xac01,0xac02,0xac03,0xac04,0xac05,0xac06,0xac07, + 0xac08,0xac09,0xac0a,0xac0b,0xac0c,0xac0d,0xac0e,0xac0f, + 0xac10,0xac11,0xac12,0xac13,0xac14,0xac15,0xac16,0xac17, + 0xac18,0xac19,0xac1a,0xac1b,0xac1c,0xac1d,0xac1e,0xac1f, + 0xac20,0xac21,0xac22,0xac23,0xac24,0xac25,0xac26,0xac27, + 0xac28,0xac29,0xac2a,0xac2b,0xac2c,0xac2d,0xac2e,0xac2f, + 0xac30,0xac31,0xac32,0xac33,0xac34,0xac35,0xac36,0xac37, + 0xac38,0xac39,0xac3a,0xac3b,0xac3c,0xac3d,0xac3e,0xac3f, + 0xac40,0xac41,0xac42,0xac43,0xac44,0xac45,0xac46,0xac47, + 0xac48,0xac49,0xac4a,0xac4b,0xac4c,0xac4d,0xac4e,0xac4f, + 0xac50,0xac51,0xac52,0xac53,0xac54,0xac55,0xac56,0xac57, + 0xac58,0xac59,0xac5a,0xac5b,0xac5c,0xac5d,0xac5e,0xac5f, + 0xac60,0xac61,0xac62,0xac63,0xac64,0xac65,0xac66,0xac67, + 0xac68,0xac69,0xac6a,0xac6b,0xac6c,0xac6d,0xac6e,0xac6f, + 0xac70,0xac71,0xac72,0xac73,0xac74,0xac75,0xac76,0xac77, + 0xac78,0xac79,0xac7a,0xac7b,0xac7c,0xac7d,0xac7e,0xac7f, + 0xac80,0xac81,0xac82,0xac83,0xac84,0xac85,0xac86,0xac87, + 0xac88,0xac89,0xac8a,0xac8b,0xac8c,0xac8d,0xac8e,0xac8f, + 0xac90,0xac91,0xac92,0xac93,0xac94,0xac95,0xac96,0xac97, + 0xac98,0xac99,0xac9a,0xac9b,0xac9c,0xac9d,0xac9e,0xac9f, + 0xaca0,0xaca1,0xaca2,0xaca3,0xaca4,0xaca5,0xaca6,0xaca7, + 0xaca8,0xaca9,0xacaa,0xacab,0xacac,0xacad,0xacae,0xacaf, + 0xacb0,0xacb1,0xacb2,0xacb3,0xacb4,0xacb5,0xacb6,0xacb7, + 0xacb8,0xacb9,0xacba,0xacbb,0xacbc,0xacbd,0xacbe,0xacbf, + 0xacc0,0xacc1,0xacc2,0xacc3,0xacc4,0xacc5,0xacc6,0xacc7, + 0xacc8,0xacc9,0xacca,0xaccb,0xaccc,0xaccd,0xacce,0xaccf, + 0xacd0,0xacd1,0xacd2,0xacd3,0xacd4,0xacd5,0xacd6,0xacd7, + 0xacd8,0xacd9,0xacda,0xacdb,0xacdc,0xacdd,0xacde,0xacdf, + 0xace0,0xace1,0xace2,0xace3,0xace4,0xace5,0xace6,0xace7, + 0xace8,0xace9,0xacea,0xaceb,0xacec,0xaced,0xacee,0xacef, + 0xacf0,0xacf1,0xacf2,0xacf3,0xacf4,0xacf5,0xacf6,0xacf7, + 0xacf8,0xacf9,0xacfa,0xacfb,0xacfc,0xacfd,0xacfe,0xacff, + 0xad00,0xad01,0xad02,0xad03,0xad04,0xad05,0xad06,0xad07, + 0xad08,0xad09,0xad0a,0xad0b,0xad0c,0xad0d,0xad0e,0xad0f, + 0xad10,0xad11,0xad12,0xad13,0xad14,0xad15,0xad16,0xad17, + 0xad18,0xad19,0xad1a,0xad1b,0xad1c,0xad1d,0xad1e,0xad1f, + 0xad20,0xad21,0xad22,0xad23,0xad24,0xad25,0xad26,0xad27, + 0xad28,0xad29,0xad2a,0xad2b,0xad2c,0xad2d,0xad2e,0xad2f, + 0xad30,0xad31,0xad32,0xad33,0xad34,0xad35,0xad36,0xad37, + 0xad38,0xad39,0xad3a,0xad3b,0xad3c,0xad3d,0xad3e,0xad3f, + 0xad40,0xad41,0xad42,0xad43,0xad44,0xad45,0xad46,0xad47, + 0xad48,0xad49,0xad4a,0xad4b,0xad4c,0xad4d,0xad4e,0xad4f, + 0xad50,0xad51,0xad52,0xad53,0xad54,0xad55,0xad56,0xad57, + 0xad58,0xad59,0xad5a,0xad5b,0xad5c,0xad5d,0xad5e,0xad5f, + 0xad60,0xad61,0xad62,0xad63,0xad64,0xad65,0xad66,0xad67, + 0xad68,0xad69,0xad6a,0xad6b,0xad6c,0xad6d,0xad6e,0xad6f, + 0xad70,0xad71,0xad72,0xad73,0xad74,0xad75,0xad76,0xad77, + 0xad78,0xad79,0xad7a,0xad7b,0xad7c,0xad7d,0xad7e,0xad7f, + 0xad80,0xad81,0xad82,0xad83,0xad84,0xad85,0xad86,0xad87, + 0xad88,0xad89,0xad8a,0xad8b,0xad8c,0xad8d,0xad8e,0xad8f, + 0xad90,0xad91,0xad92,0xad93,0xad94,0xad95,0xad96,0xad97, + 0xad98,0xad99,0xad9a,0xad9b,0xad9c,0xad9d,0xad9e,0xad9f, + 0xada0,0xada1,0xada2,0xada3,0xada4,0xada5,0xada6,0xada7, + 0xada8,0xada9,0xadaa,0xadab,0xadac,0xadad,0xadae,0xadaf, + 0xadb0,0xadb1,0xadb2,0xadb3,0xadb4,0xadb5,0xadb6,0xadb7, + 0xadb8,0xadb9,0xadba,0xadbb,0xadbc,0xadbd,0xadbe,0xadbf, + 0xadc0,0xadc1,0xadc2,0xadc3,0xadc4,0xadc5,0xadc6,0xadc7, + 0xadc8,0xadc9,0xadca,0xadcb,0xadcc,0xadcd,0xadce,0xadcf, + 0xadd0,0xadd1,0xadd2,0xadd3,0xadd4,0xadd5,0xadd6,0xadd7, + 0xadd8,0xadd9,0xadda,0xaddb,0xaddc,0xaddd,0xadde,0xaddf, + 0xade0,0xade1,0xade2,0xade3,0xade4,0xade5,0xade6,0xade7, + 0xade8,0xade9,0xadea,0xadeb,0xadec,0xaded,0xadee,0xadef, + 0xadf0,0xadf1,0xadf2,0xadf3,0xadf4,0xadf5,0xadf6,0xadf7, + 0xadf8,0xadf9,0xadfa,0xadfb,0xadfc,0xadfd,0xadfe,0xadff, + 0xae00,0xae01,0xae02,0xae03,0xae04,0xae05,0xae06,0xae07, + 0xae08,0xae09,0xae0a,0xae0b,0xae0c,0xae0d,0xae0e,0xae0f, + 0xae10,0xae11,0xae12,0xae13,0xae14,0xae15,0xae16,0xae17, + 0xae18,0xae19,0xae1a,0xae1b,0xae1c,0xae1d,0xae1e,0xae1f, + 0xae20,0xae21,0xae22,0xae23,0xae24,0xae25,0xae26,0xae27, + 0xae28,0xae29,0xae2a,0xae2b,0xae2c,0xae2d,0xae2e,0xae2f, + 0xae30,0xae31,0xae32,0xae33,0xae34,0xae35,0xae36,0xae37, + 0xae38,0xae39,0xae3a,0xae3b,0xae3c,0xae3d,0xae3e,0xae3f, + 0xae40,0xae41,0xae42,0xae43,0xae44,0xae45,0xae46,0xae47, + 0xae48,0xae49,0xae4a,0xae4b,0xae4c,0xae4d,0xae4e,0xae4f, + 0xae50,0xae51,0xae52,0xae53,0xae54,0xae55,0xae56,0xae57, + 0xae58,0xae59,0xae5a,0xae5b,0xae5c,0xae5d,0xae5e,0xae5f, + 0xae60,0xae61,0xae62,0xae63,0xae64,0xae65,0xae66,0xae67, + 0xae68,0xae69,0xae6a,0xae6b,0xae6c,0xae6d,0xae6e,0xae6f, + 0xae70,0xae71,0xae72,0xae73,0xae74,0xae75,0xae76,0xae77, + 0xae78,0xae79,0xae7a,0xae7b,0xae7c,0xae7d,0xae7e,0xae7f, + 0xae80,0xae81,0xae82,0xae83,0xae84,0xae85,0xae86,0xae87, + 0xae88,0xae89,0xae8a,0xae8b,0xae8c,0xae8d,0xae8e,0xae8f, + 0xae90,0xae91,0xae92,0xae93,0xae94,0xae95,0xae96,0xae97, + 0xae98,0xae99,0xae9a,0xae9b,0xae9c,0xae9d,0xae9e,0xae9f, + 0xaea0,0xaea1,0xaea2,0xaea3,0xaea4,0xaea5,0xaea6,0xaea7, + 0xaea8,0xaea9,0xaeaa,0xaeab,0xaeac,0xaead,0xaeae,0xaeaf, + 0xaeb0,0xaeb1,0xaeb2,0xaeb3,0xaeb4,0xaeb5,0xaeb6,0xaeb7, + 0xaeb8,0xaeb9,0xaeba,0xaebb,0xaebc,0xaebd,0xaebe,0xaebf, + 0xaec0,0xaec1,0xaec2,0xaec3,0xaec4,0xaec5,0xaec6,0xaec7, + 0xaec8,0xaec9,0xaeca,0xaecb,0xaecc,0xaecd,0xaece,0xaecf, + 0xaed0,0xaed1,0xaed2,0xaed3,0xaed4,0xaed5,0xaed6,0xaed7, + 0xaed8,0xaed9,0xaeda,0xaedb,0xaedc,0xaedd,0xaede,0xaedf, + 0xaee0,0xaee1,0xaee2,0xaee3,0xaee4,0xaee5,0xaee6,0xaee7, + 0xaee8,0xaee9,0xaeea,0xaeeb,0xaeec,0xaeed,0xaeee,0xaeef, + 0xaef0,0xaef1,0xaef2,0xaef3,0xaef4,0xaef5,0xaef6,0xaef7, + 0xaef8,0xaef9,0xaefa,0xaefb,0xaefc,0xaefd,0xaefe,0xaeff, + 0xaf00,0xaf01,0xaf02,0xaf03,0xaf04,0xaf05,0xaf06,0xaf07, + 0xaf08,0xaf09,0xaf0a,0xaf0b,0xaf0c,0xaf0d,0xaf0e,0xaf0f, + 0xaf10,0xaf11,0xaf12,0xaf13,0xaf14,0xaf15,0xaf16,0xaf17, + 0xaf18,0xaf19,0xaf1a,0xaf1b,0xaf1c,0xaf1d,0xaf1e,0xaf1f, + 0xaf20,0xaf21,0xaf22,0xaf23,0xaf24,0xaf25,0xaf26,0xaf27, + 0xaf28,0xaf29,0xaf2a,0xaf2b,0xaf2c,0xaf2d,0xaf2e,0xaf2f, + 0xaf30,0xaf31,0xaf32,0xaf33,0xaf34,0xaf35,0xaf36,0xaf37, + 0xaf38,0xaf39,0xaf3a,0xaf3b,0xaf3c,0xaf3d,0xaf3e,0xaf3f, + 0xaf40,0xaf41,0xaf42,0xaf43,0xaf44,0xaf45,0xaf46,0xaf47, + 0xaf48,0xaf49,0xaf4a,0xaf4b,0xaf4c,0xaf4d,0xaf4e,0xaf4f, + 0xaf50,0xaf51,0xaf52,0xaf53,0xaf54,0xaf55,0xaf56,0xaf57, + 0xaf58,0xaf59,0xaf5a,0xaf5b,0xaf5c,0xaf5d,0xaf5e,0xaf5f, + 0xaf60,0xaf61,0xaf62,0xaf63,0xaf64,0xaf65,0xaf66,0xaf67, + 0xaf68,0xaf69,0xaf6a,0xaf6b,0xaf6c,0xaf6d,0xaf6e,0xaf6f, + 0xaf70,0xaf71,0xaf72,0xaf73,0xaf74,0xaf75,0xaf76,0xaf77, + 0xaf78,0xaf79,0xaf7a,0xaf7b,0xaf7c,0xaf7d,0xaf7e,0xaf7f, + 0xaf80,0xaf81,0xaf82,0xaf83,0xaf84,0xaf85,0xaf86,0xaf87, + 0xaf88,0xaf89,0xaf8a,0xaf8b,0xaf8c,0xaf8d,0xaf8e,0xaf8f, + 0xaf90,0xaf91,0xaf92,0xaf93,0xaf94,0xaf95,0xaf96,0xaf97, + 0xaf98,0xaf99,0xaf9a,0xaf9b,0xaf9c,0xaf9d,0xaf9e,0xaf9f, + 0xafa0,0xafa1,0xafa2,0xafa3,0xafa4,0xafa5,0xafa6,0xafa7, + 0xafa8,0xafa9,0xafaa,0xafab,0xafac,0xafad,0xafae,0xafaf, + 0xafb0,0xafb1,0xafb2,0xafb3,0xafb4,0xafb5,0xafb6,0xafb7, + 0xafb8,0xafb9,0xafba,0xafbb,0xafbc,0xafbd,0xafbe,0xafbf, + 0xafc0,0xafc1,0xafc2,0xafc3,0xafc4,0xafc5,0xafc6,0xafc7, + 0xafc8,0xafc9,0xafca,0xafcb,0xafcc,0xafcd,0xafce,0xafcf, + 0xafd0,0xafd1,0xafd2,0xafd3,0xafd4,0xafd5,0xafd6,0xafd7, + 0xafd8,0xafd9,0xafda,0xafdb,0xafdc,0xafdd,0xafde,0xafdf, + 0xafe0,0xafe1,0xafe2,0xafe3,0xafe4,0xafe5,0xafe6,0xafe7, + 0xafe8,0xafe9,0xafea,0xafeb,0xafec,0xafed,0xafee,0xafef, + 0xaff0,0xaff1,0xaff2,0xaff3,0xaff4,0xaff5,0xaff6,0xaff7, + 0xaff8,0xaff9,0xaffa,0xaffb,0xaffc,0xaffd,0xaffe,0xafff, + 0xb000,0xb001,0xb002,0xb003,0xb004,0xb005,0xb006,0xb007, + 0xb008,0xb009,0xb00a,0xb00b,0xb00c,0xb00d,0xb00e,0xb00f, + 0xb010,0xb011,0xb012,0xb013,0xb014,0xb015,0xb016,0xb017, + 0xb018,0xb019,0xb01a,0xb01b,0xb01c,0xb01d,0xb01e,0xb01f, + 0xb020,0xb021,0xb022,0xb023,0xb024,0xb025,0xb026,0xb027, + 0xb028,0xb029,0xb02a,0xb02b,0xb02c,0xb02d,0xb02e,0xb02f, + 0xb030,0xb031,0xb032,0xb033,0xb034,0xb035,0xb036,0xb037, + 0xb038,0xb039,0xb03a,0xb03b,0xb03c,0xb03d,0xb03e,0xb03f, + 0xb040,0xb041,0xb042,0xb043,0xb044,0xb045,0xb046,0xb047, + 0xb048,0xb049,0xb04a,0xb04b,0xb04c,0xb04d,0xb04e,0xb04f, + 0xb050,0xb051,0xb052,0xb053,0xb054,0xb055,0xb056,0xb057, + 0xb058,0xb059,0xb05a,0xb05b,0xb05c,0xb05d,0xb05e,0xb05f, + 0xb060,0xb061,0xb062,0xb063,0xb064,0xb065,0xb066,0xb067, + 0xb068,0xb069,0xb06a,0xb06b,0xb06c,0xb06d,0xb06e,0xb06f, + 0xb070,0xb071,0xb072,0xb073,0xb074,0xb075,0xb076,0xb077, + 0xb078,0xb079,0xb07a,0xb07b,0xb07c,0xb07d,0xb07e,0xb07f, + 0xb080,0xb081,0xb082,0xb083,0xb084,0xb085,0xb086,0xb087, + 0xb088,0xb089,0xb08a,0xb08b,0xb08c,0xb08d,0xb08e,0xb08f, + 0xb090,0xb091,0xb092,0xb093,0xb094,0xb095,0xb096,0xb097, + 0xb098,0xb099,0xb09a,0xb09b,0xb09c,0xb09d,0xb09e,0xb09f, + 0xb0a0,0xb0a1,0xb0a2,0xb0a3,0xb0a4,0xb0a5,0xb0a6,0xb0a7, + 0xb0a8,0xb0a9,0xb0aa,0xb0ab,0xb0ac,0xb0ad,0xb0ae,0xb0af, + 0xb0b0,0xb0b1,0xb0b2,0xb0b3,0xb0b4,0xb0b5,0xb0b6,0xb0b7, + 0xb0b8,0xb0b9,0xb0ba,0xb0bb,0xb0bc,0xb0bd,0xb0be,0xb0bf, + 0xb0c0,0xb0c1,0xb0c2,0xb0c3,0xb0c4,0xb0c5,0xb0c6,0xb0c7, + 0xb0c8,0xb0c9,0xb0ca,0xb0cb,0xb0cc,0xb0cd,0xb0ce,0xb0cf, + 0xb0d0,0xb0d1,0xb0d2,0xb0d3,0xb0d4,0xb0d5,0xb0d6,0xb0d7, + 0xb0d8,0xb0d9,0xb0da,0xb0db,0xb0dc,0xb0dd,0xb0de,0xb0df, + 0xb0e0,0xb0e1,0xb0e2,0xb0e3,0xb0e4,0xb0e5,0xb0e6,0xb0e7, + 0xb0e8,0xb0e9,0xb0ea,0xb0eb,0xb0ec,0xb0ed,0xb0ee,0xb0ef, + 0xb0f0,0xb0f1,0xb0f2,0xb0f3,0xb0f4,0xb0f5,0xb0f6,0xb0f7, + 0xb0f8,0xb0f9,0xb0fa,0xb0fb,0xb0fc,0xb0fd,0xb0fe,0xb0ff, + 0xb100,0xb101,0xb102,0xb103,0xb104,0xb105,0xb106,0xb107, + 0xb108,0xb109,0xb10a,0xb10b,0xb10c,0xb10d,0xb10e,0xb10f, + 0xb110,0xb111,0xb112,0xb113,0xb114,0xb115,0xb116,0xb117, + 0xb118,0xb119,0xb11a,0xb11b,0xb11c,0xb11d,0xb11e,0xb11f, + 0xb120,0xb121,0xb122,0xb123,0xb124,0xb125,0xb126,0xb127, + 0xb128,0xb129,0xb12a,0xb12b,0xb12c,0xb12d,0xb12e,0xb12f, + 0xb130,0xb131,0xb132,0xb133,0xb134,0xb135,0xb136,0xb137, + 0xb138,0xb139,0xb13a,0xb13b,0xb13c,0xb13d,0xb13e,0xb13f, + 0xb140,0xb141,0xb142,0xb143,0xb144,0xb145,0xb146,0xb147, + 0xb148,0xb149,0xb14a,0xb14b,0xb14c,0xb14d,0xb14e,0xb14f, + 0xb150,0xb151,0xb152,0xb153,0xb154,0xb155,0xb156,0xb157, + 0xb158,0xb159,0xb15a,0xb15b,0xb15c,0xb15d,0xb15e,0xb15f, + 0xb160,0xb161,0xb162,0xb163,0xb164,0xb165,0xb166,0xb167, + 0xb168,0xb169,0xb16a,0xb16b,0xb16c,0xb16d,0xb16e,0xb16f, + 0xb170,0xb171,0xb172,0xb173,0xb174,0xb175,0xb176,0xb177, + 0xb178,0xb179,0xb17a,0xb17b,0xb17c,0xb17d,0xb17e,0xb17f, + 0xb180,0xb181,0xb182,0xb183,0xb184,0xb185,0xb186,0xb187, + 0xb188,0xb189,0xb18a,0xb18b,0xb18c,0xb18d,0xb18e,0xb18f, + 0xb190,0xb191,0xb192,0xb193,0xb194,0xb195,0xb196,0xb197, + 0xb198,0xb199,0xb19a,0xb19b,0xb19c,0xb19d,0xb19e,0xb19f, + 0xb1a0,0xb1a1,0xb1a2,0xb1a3,0xb1a4,0xb1a5,0xb1a6,0xb1a7, + 0xb1a8,0xb1a9,0xb1aa,0xb1ab,0xb1ac,0xb1ad,0xb1ae,0xb1af, + 0xb1b0,0xb1b1,0xb1b2,0xb1b3,0xb1b4,0xb1b5,0xb1b6,0xb1b7, + 0xb1b8,0xb1b9,0xb1ba,0xb1bb,0xb1bc,0xb1bd,0xb1be,0xb1bf, + 0xb1c0,0xb1c1,0xb1c2,0xb1c3,0xb1c4,0xb1c5,0xb1c6,0xb1c7, + 0xb1c8,0xb1c9,0xb1ca,0xb1cb,0xb1cc,0xb1cd,0xb1ce,0xb1cf, + 0xb1d0,0xb1d1,0xb1d2,0xb1d3,0xb1d4,0xb1d5,0xb1d6,0xb1d7, + 0xb1d8,0xb1d9,0xb1da,0xb1db,0xb1dc,0xb1dd,0xb1de,0xb1df, + 0xb1e0,0xb1e1,0xb1e2,0xb1e3,0xb1e4,0xb1e5,0xb1e6,0xb1e7, + 0xb1e8,0xb1e9,0xb1ea,0xb1eb,0xb1ec,0xb1ed,0xb1ee,0xb1ef, + 0xb1f0,0xb1f1,0xb1f2,0xb1f3,0xb1f4,0xb1f5,0xb1f6,0xb1f7, + 0xb1f8,0xb1f9,0xb1fa,0xb1fb,0xb1fc,0xb1fd,0xb1fe,0xb1ff, + 0xb200,0xb201,0xb202,0xb203,0xb204,0xb205,0xb206,0xb207, + 0xb208,0xb209,0xb20a,0xb20b,0xb20c,0xb20d,0xb20e,0xb20f, + 0xb210,0xb211,0xb212,0xb213,0xb214,0xb215,0xb216,0xb217, + 0xb218,0xb219,0xb21a,0xb21b,0xb21c,0xb21d,0xb21e,0xb21f, + 0xb220,0xb221,0xb222,0xb223,0xb224,0xb225,0xb226,0xb227, + 0xb228,0xb229,0xb22a,0xb22b,0xb22c,0xb22d,0xb22e,0xb22f, + 0xb230,0xb231,0xb232,0xb233,0xb234,0xb235,0xb236,0xb237, + 0xb238,0xb239,0xb23a,0xb23b,0xb23c,0xb23d,0xb23e,0xb23f, + 0xb240,0xb241,0xb242,0xb243,0xb244,0xb245,0xb246,0xb247, + 0xb248,0xb249,0xb24a,0xb24b,0xb24c,0xb24d,0xb24e,0xb24f, + 0xb250,0xb251,0xb252,0xb253,0xb254,0xb255,0xb256,0xb257, + 0xb258,0xb259,0xb25a,0xb25b,0xb25c,0xb25d,0xb25e,0xb25f, + 0xb260,0xb261,0xb262,0xb263,0xb264,0xb265,0xb266,0xb267, + 0xb268,0xb269,0xb26a,0xb26b,0xb26c,0xb26d,0xb26e,0xb26f, + 0xb270,0xb271,0xb272,0xb273,0xb274,0xb275,0xb276,0xb277, + 0xb278,0xb279,0xb27a,0xb27b,0xb27c,0xb27d,0xb27e,0xb27f, + 0xb280,0xb281,0xb282,0xb283,0xb284,0xb285,0xb286,0xb287, + 0xb288,0xb289,0xb28a,0xb28b,0xb28c,0xb28d,0xb28e,0xb28f, + 0xb290,0xb291,0xb292,0xb293,0xb294,0xb295,0xb296,0xb297, + 0xb298,0xb299,0xb29a,0xb29b,0xb29c,0xb29d,0xb29e,0xb29f, + 0xb2a0,0xb2a1,0xb2a2,0xb2a3,0xb2a4,0xb2a5,0xb2a6,0xb2a7, + 0xb2a8,0xb2a9,0xb2aa,0xb2ab,0xb2ac,0xb2ad,0xb2ae,0xb2af, + 0xb2b0,0xb2b1,0xb2b2,0xb2b3,0xb2b4,0xb2b5,0xb2b6,0xb2b7, + 0xb2b8,0xb2b9,0xb2ba,0xb2bb,0xb2bc,0xb2bd,0xb2be,0xb2bf, + 0xb2c0,0xb2c1,0xb2c2,0xb2c3,0xb2c4,0xb2c5,0xb2c6,0xb2c7, + 0xb2c8,0xb2c9,0xb2ca,0xb2cb,0xb2cc,0xb2cd,0xb2ce,0xb2cf, + 0xb2d0,0xb2d1,0xb2d2,0xb2d3,0xb2d4,0xb2d5,0xb2d6,0xb2d7, + 0xb2d8,0xb2d9,0xb2da,0xb2db,0xb2dc,0xb2dd,0xb2de,0xb2df, + 0xb2e0,0xb2e1,0xb2e2,0xb2e3,0xb2e4,0xb2e5,0xb2e6,0xb2e7, + 0xb2e8,0xb2e9,0xb2ea,0xb2eb,0xb2ec,0xb2ed,0xb2ee,0xb2ef, + 0xb2f0,0xb2f1,0xb2f2,0xb2f3,0xb2f4,0xb2f5,0xb2f6,0xb2f7, + 0xb2f8,0xb2f9,0xb2fa,0xb2fb,0xb2fc,0xb2fd,0xb2fe,0xb2ff, + 0xb300,0xb301,0xb302,0xb303,0xb304,0xb305,0xb306,0xb307, + 0xb308,0xb309,0xb30a,0xb30b,0xb30c,0xb30d,0xb30e,0xb30f, + 0xb310,0xb311,0xb312,0xb313,0xb314,0xb315,0xb316,0xb317, + 0xb318,0xb319,0xb31a,0xb31b,0xb31c,0xb31d,0xb31e,0xb31f, + 0xb320,0xb321,0xb322,0xb323,0xb324,0xb325,0xb326,0xb327, + 0xb328,0xb329,0xb32a,0xb32b,0xb32c,0xb32d,0xb32e,0xb32f, + 0xb330,0xb331,0xb332,0xb333,0xb334,0xb335,0xb336,0xb337, + 0xb338,0xb339,0xb33a,0xb33b,0xb33c,0xb33d,0xb33e,0xb33f, + 0xb340,0xb341,0xb342,0xb343,0xb344,0xb345,0xb346,0xb347, + 0xb348,0xb349,0xb34a,0xb34b,0xb34c,0xb34d,0xb34e,0xb34f, + 0xb350,0xb351,0xb352,0xb353,0xb354,0xb355,0xb356,0xb357, + 0xb358,0xb359,0xb35a,0xb35b,0xb35c,0xb35d,0xb35e,0xb35f, + 0xb360,0xb361,0xb362,0xb363,0xb364,0xb365,0xb366,0xb367, + 0xb368,0xb369,0xb36a,0xb36b,0xb36c,0xb36d,0xb36e,0xb36f, + 0xb370,0xb371,0xb372,0xb373,0xb374,0xb375,0xb376,0xb377, + 0xb378,0xb379,0xb37a,0xb37b,0xb37c,0xb37d,0xb37e,0xb37f, + 0xb380,0xb381,0xb382,0xb383,0xb384,0xb385,0xb386,0xb387, + 0xb388,0xb389,0xb38a,0xb38b,0xb38c,0xb38d,0xb38e,0xb38f, + 0xb390,0xb391,0xb392,0xb393,0xb394,0xb395,0xb396,0xb397, + 0xb398,0xb399,0xb39a,0xb39b,0xb39c,0xb39d,0xb39e,0xb39f, + 0xb3a0,0xb3a1,0xb3a2,0xb3a3,0xb3a4,0xb3a5,0xb3a6,0xb3a7, + 0xb3a8,0xb3a9,0xb3aa,0xb3ab,0xb3ac,0xb3ad,0xb3ae,0xb3af, + 0xb3b0,0xb3b1,0xb3b2,0xb3b3,0xb3b4,0xb3b5,0xb3b6,0xb3b7, + 0xb3b8,0xb3b9,0xb3ba,0xb3bb,0xb3bc,0xb3bd,0xb3be,0xb3bf, + 0xb3c0,0xb3c1,0xb3c2,0xb3c3,0xb3c4,0xb3c5,0xb3c6,0xb3c7, + 0xb3c8,0xb3c9,0xb3ca,0xb3cb,0xb3cc,0xb3cd,0xb3ce,0xb3cf, + 0xb3d0,0xb3d1,0xb3d2,0xb3d3,0xb3d4,0xb3d5,0xb3d6,0xb3d7, + 0xb3d8,0xb3d9,0xb3da,0xb3db,0xb3dc,0xb3dd,0xb3de,0xb3df, + 0xb3e0,0xb3e1,0xb3e2,0xb3e3,0xb3e4,0xb3e5,0xb3e6,0xb3e7, + 0xb3e8,0xb3e9,0xb3ea,0xb3eb,0xb3ec,0xb3ed,0xb3ee,0xb3ef, + 0xb3f0,0xb3f1,0xb3f2,0xb3f3,0xb3f4,0xb3f5,0xb3f6,0xb3f7, + 0xb3f8,0xb3f9,0xb3fa,0xb3fb,0xb3fc,0xb3fd,0xb3fe,0xb3ff, + 0xb400,0xb401,0xb402,0xb403,0xb404,0xb405,0xb406,0xb407, + 0xb408,0xb409,0xb40a,0xb40b,0xb40c,0xb40d,0xb40e,0xb40f, + 0xb410,0xb411,0xb412,0xb413,0xb414,0xb415,0xb416,0xb417, + 0xb418,0xb419,0xb41a,0xb41b,0xb41c,0xb41d,0xb41e,0xb41f, + 0xb420,0xb421,0xb422,0xb423,0xb424,0xb425,0xb426,0xb427, + 0xb428,0xb429,0xb42a,0xb42b,0xb42c,0xb42d,0xb42e,0xb42f, + 0xb430,0xb431,0xb432,0xb433,0xb434,0xb435,0xb436,0xb437, + 0xb438,0xb439,0xb43a,0xb43b,0xb43c,0xb43d,0xb43e,0xb43f, + 0xb440,0xb441,0xb442,0xb443,0xb444,0xb445,0xb446,0xb447, + 0xb448,0xb449,0xb44a,0xb44b,0xb44c,0xb44d,0xb44e,0xb44f, + 0xb450,0xb451,0xb452,0xb453,0xb454,0xb455,0xb456,0xb457, + 0xb458,0xb459,0xb45a,0xb45b,0xb45c,0xb45d,0xb45e,0xb45f, + 0xb460,0xb461,0xb462,0xb463,0xb464,0xb465,0xb466,0xb467, + 0xb468,0xb469,0xb46a,0xb46b,0xb46c,0xb46d,0xb46e,0xb46f, + 0xb470,0xb471,0xb472,0xb473,0xb474,0xb475,0xb476,0xb477, + 0xb478,0xb479,0xb47a,0xb47b,0xb47c,0xb47d,0xb47e,0xb47f, + 0xb480,0xb481,0xb482,0xb483,0xb484,0xb485,0xb486,0xb487, + 0xb488,0xb489,0xb48a,0xb48b,0xb48c,0xb48d,0xb48e,0xb48f, + 0xb490,0xb491,0xb492,0xb493,0xb494,0xb495,0xb496,0xb497, + 0xb498,0xb499,0xb49a,0xb49b,0xb49c,0xb49d,0xb49e,0xb49f, + 0xb4a0,0xb4a1,0xb4a2,0xb4a3,0xb4a4,0xb4a5,0xb4a6,0xb4a7, + 0xb4a8,0xb4a9,0xb4aa,0xb4ab,0xb4ac,0xb4ad,0xb4ae,0xb4af, + 0xb4b0,0xb4b1,0xb4b2,0xb4b3,0xb4b4,0xb4b5,0xb4b6,0xb4b7, + 0xb4b8,0xb4b9,0xb4ba,0xb4bb,0xb4bc,0xb4bd,0xb4be,0xb4bf, + 0xb4c0,0xb4c1,0xb4c2,0xb4c3,0xb4c4,0xb4c5,0xb4c6,0xb4c7, + 0xb4c8,0xb4c9,0xb4ca,0xb4cb,0xb4cc,0xb4cd,0xb4ce,0xb4cf, + 0xb4d0,0xb4d1,0xb4d2,0xb4d3,0xb4d4,0xb4d5,0xb4d6,0xb4d7, + 0xb4d8,0xb4d9,0xb4da,0xb4db,0xb4dc,0xb4dd,0xb4de,0xb4df, + 0xb4e0,0xb4e1,0xb4e2,0xb4e3,0xb4e4,0xb4e5,0xb4e6,0xb4e7, + 0xb4e8,0xb4e9,0xb4ea,0xb4eb,0xb4ec,0xb4ed,0xb4ee,0xb4ef, + 0xb4f0,0xb4f1,0xb4f2,0xb4f3,0xb4f4,0xb4f5,0xb4f6,0xb4f7, + 0xb4f8,0xb4f9,0xb4fa,0xb4fb,0xb4fc,0xb4fd,0xb4fe,0xb4ff, + 0xb500,0xb501,0xb502,0xb503,0xb504,0xb505,0xb506,0xb507, + 0xb508,0xb509,0xb50a,0xb50b,0xb50c,0xb50d,0xb50e,0xb50f, + 0xb510,0xb511,0xb512,0xb513,0xb514,0xb515,0xb516,0xb517, + 0xb518,0xb519,0xb51a,0xb51b,0xb51c,0xb51d,0xb51e,0xb51f, + 0xb520,0xb521,0xb522,0xb523,0xb524,0xb525,0xb526,0xb527, + 0xb528,0xb529,0xb52a,0xb52b,0xb52c,0xb52d,0xb52e,0xb52f, + 0xb530,0xb531,0xb532,0xb533,0xb534,0xb535,0xb536,0xb537, + 0xb538,0xb539,0xb53a,0xb53b,0xb53c,0xb53d,0xb53e,0xb53f, + 0xb540,0xb541,0xb542,0xb543,0xb544,0xb545,0xb546,0xb547, + 0xb548,0xb549,0xb54a,0xb54b,0xb54c,0xb54d,0xb54e,0xb54f, + 0xb550,0xb551,0xb552,0xb553,0xb554,0xb555,0xb556,0xb557, + 0xb558,0xb559,0xb55a,0xb55b,0xb55c,0xb55d,0xb55e,0xb55f, + 0xb560,0xb561,0xb562,0xb563,0xb564,0xb565,0xb566,0xb567, + 0xb568,0xb569,0xb56a,0xb56b,0xb56c,0xb56d,0xb56e,0xb56f, + 0xb570,0xb571,0xb572,0xb573,0xb574,0xb575,0xb576,0xb577, + 0xb578,0xb579,0xb57a,0xb57b,0xb57c,0xb57d,0xb57e,0xb57f, + 0xb580,0xb581,0xb582,0xb583,0xb584,0xb585,0xb586,0xb587, + 0xb588,0xb589,0xb58a,0xb58b,0xb58c,0xb58d,0xb58e,0xb58f, + 0xb590,0xb591,0xb592,0xb593,0xb594,0xb595,0xb596,0xb597, + 0xb598,0xb599,0xb59a,0xb59b,0xb59c,0xb59d,0xb59e,0xb59f, + 0xb5a0,0xb5a1,0xb5a2,0xb5a3,0xb5a4,0xb5a5,0xb5a6,0xb5a7, + 0xb5a8,0xb5a9,0xb5aa,0xb5ab,0xb5ac,0xb5ad,0xb5ae,0xb5af, + 0xb5b0,0xb5b1,0xb5b2,0xb5b3,0xb5b4,0xb5b5,0xb5b6,0xb5b7, + 0xb5b8,0xb5b9,0xb5ba,0xb5bb,0xb5bc,0xb5bd,0xb5be,0xb5bf, + 0xb5c0,0xb5c1,0xb5c2,0xb5c3,0xb5c4,0xb5c5,0xb5c6,0xb5c7, + 0xb5c8,0xb5c9,0xb5ca,0xb5cb,0xb5cc,0xb5cd,0xb5ce,0xb5cf, + 0xb5d0,0xb5d1,0xb5d2,0xb5d3,0xb5d4,0xb5d5,0xb5d6,0xb5d7, + 0xb5d8,0xb5d9,0xb5da,0xb5db,0xb5dc,0xb5dd,0xb5de,0xb5df, + 0xb5e0,0xb5e1,0xb5e2,0xb5e3,0xb5e4,0xb5e5,0xb5e6,0xb5e7, + 0xb5e8,0xb5e9,0xb5ea,0xb5eb,0xb5ec,0xb5ed,0xb5ee,0xb5ef, + 0xb5f0,0xb5f1,0xb5f2,0xb5f3,0xb5f4,0xb5f5,0xb5f6,0xb5f7, + 0xb5f8,0xb5f9,0xb5fa,0xb5fb,0xb5fc,0xb5fd,0xb5fe,0xb5ff, + 0xb600,0xb601,0xb602,0xb603,0xb604,0xb605,0xb606,0xb607, + 0xb608,0xb609,0xb60a,0xb60b,0xb60c,0xb60d,0xb60e,0xb60f, + 0xb610,0xb611,0xb612,0xb613,0xb614,0xb615,0xb616,0xb617, + 0xb618,0xb619,0xb61a,0xb61b,0xb61c,0xb61d,0xb61e,0xb61f, + 0xb620,0xb621,0xb622,0xb623,0xb624,0xb625,0xb626,0xb627, + 0xb628,0xb629,0xb62a,0xb62b,0xb62c,0xb62d,0xb62e,0xb62f, + 0xb630,0xb631,0xb632,0xb633,0xb634,0xb635,0xb636,0xb637, + 0xb638,0xb639,0xb63a,0xb63b,0xb63c,0xb63d,0xb63e,0xb63f, + 0xb640,0xb641,0xb642,0xb643,0xb644,0xb645,0xb646,0xb647, + 0xb648,0xb649,0xb64a,0xb64b,0xb64c,0xb64d,0xb64e,0xb64f, + 0xb650,0xb651,0xb652,0xb653,0xb654,0xb655,0xb656,0xb657, + 0xb658,0xb659,0xb65a,0xb65b,0xb65c,0xb65d,0xb65e,0xb65f, + 0xb660,0xb661,0xb662,0xb663,0xb664,0xb665,0xb666,0xb667, + 0xb668,0xb669,0xb66a,0xb66b,0xb66c,0xb66d,0xb66e,0xb66f, + 0xb670,0xb671,0xb672,0xb673,0xb674,0xb675,0xb676,0xb677, + 0xb678,0xb679,0xb67a,0xb67b,0xb67c,0xb67d,0xb67e,0xb67f, + 0xb680,0xb681,0xb682,0xb683,0xb684,0xb685,0xb686,0xb687, + 0xb688,0xb689,0xb68a,0xb68b,0xb68c,0xb68d,0xb68e,0xb68f, + 0xb690,0xb691,0xb692,0xb693,0xb694,0xb695,0xb696,0xb697, + 0xb698,0xb699,0xb69a,0xb69b,0xb69c,0xb69d,0xb69e,0xb69f, + 0xb6a0,0xb6a1,0xb6a2,0xb6a3,0xb6a4,0xb6a5,0xb6a6,0xb6a7, + 0xb6a8,0xb6a9,0xb6aa,0xb6ab,0xb6ac,0xb6ad,0xb6ae,0xb6af, + 0xb6b0,0xb6b1,0xb6b2,0xb6b3,0xb6b4,0xb6b5,0xb6b6,0xb6b7, + 0xb6b8,0xb6b9,0xb6ba,0xb6bb,0xb6bc,0xb6bd,0xb6be,0xb6bf, + 0xb6c0,0xb6c1,0xb6c2,0xb6c3,0xb6c4,0xb6c5,0xb6c6,0xb6c7, + 0xb6c8,0xb6c9,0xb6ca,0xb6cb,0xb6cc,0xb6cd,0xb6ce,0xb6cf, + 0xb6d0,0xb6d1,0xb6d2,0xb6d3,0xb6d4,0xb6d5,0xb6d6,0xb6d7, + 0xb6d8,0xb6d9,0xb6da,0xb6db,0xb6dc,0xb6dd,0xb6de,0xb6df, + 0xb6e0,0xb6e1,0xb6e2,0xb6e3,0xb6e4,0xb6e5,0xb6e6,0xb6e7, + 0xb6e8,0xb6e9,0xb6ea,0xb6eb,0xb6ec,0xb6ed,0xb6ee,0xb6ef, + 0xb6f0,0xb6f1,0xb6f2,0xb6f3,0xb6f4,0xb6f5,0xb6f6,0xb6f7, + 0xb6f8,0xb6f9,0xb6fa,0xb6fb,0xb6fc,0xb6fd,0xb6fe,0xb6ff, + 0xb700,0xb701,0xb702,0xb703,0xb704,0xb705,0xb706,0xb707, + 0xb708,0xb709,0xb70a,0xb70b,0xb70c,0xb70d,0xb70e,0xb70f, + 0xb710,0xb711,0xb712,0xb713,0xb714,0xb715,0xb716,0xb717, + 0xb718,0xb719,0xb71a,0xb71b,0xb71c,0xb71d,0xb71e,0xb71f, + 0xb720,0xb721,0xb722,0xb723,0xb724,0xb725,0xb726,0xb727, + 0xb728,0xb729,0xb72a,0xb72b,0xb72c,0xb72d,0xb72e,0xb72f, + 0xb730,0xb731,0xb732,0xb733,0xb734,0xb735,0xb736,0xb737, + 0xb738,0xb739,0xb73a,0xb73b,0xb73c,0xb73d,0xb73e,0xb73f, + 0xb740,0xb741,0xb742,0xb743,0xb744,0xb745,0xb746,0xb747, + 0xb748,0xb749,0xb74a,0xb74b,0xb74c,0xb74d,0xb74e,0xb74f, + 0xb750,0xb751,0xb752,0xb753,0xb754,0xb755,0xb756,0xb757, + 0xb758,0xb759,0xb75a,0xb75b,0xb75c,0xb75d,0xb75e,0xb75f, + 0xb760,0xb761,0xb762,0xb763,0xb764,0xb765,0xb766,0xb767, + 0xb768,0xb769,0xb76a,0xb76b,0xb76c,0xb76d,0xb76e,0xb76f, + 0xb770,0xb771,0xb772,0xb773,0xb774,0xb775,0xb776,0xb777, + 0xb778,0xb779,0xb77a,0xb77b,0xb77c,0xb77d,0xb77e,0xb77f, + 0xb780,0xb781,0xb782,0xb783,0xb784,0xb785,0xb786,0xb787, + 0xb788,0xb789,0xb78a,0xb78b,0xb78c,0xb78d,0xb78e,0xb78f, + 0xb790,0xb791,0xb792,0xb793,0xb794,0xb795,0xb796,0xb797, + 0xb798,0xb799,0xb79a,0xb79b,0xb79c,0xb79d,0xb79e,0xb79f, + 0xb7a0,0xb7a1,0xb7a2,0xb7a3,0xb7a4,0xb7a5,0xb7a6,0xb7a7, + 0xb7a8,0xb7a9,0xb7aa,0xb7ab,0xb7ac,0xb7ad,0xb7ae,0xb7af, + 0xb7b0,0xb7b1,0xb7b2,0xb7b3,0xb7b4,0xb7b5,0xb7b6,0xb7b7, + 0xb7b8,0xb7b9,0xb7ba,0xb7bb,0xb7bc,0xb7bd,0xb7be,0xb7bf, + 0xb7c0,0xb7c1,0xb7c2,0xb7c3,0xb7c4,0xb7c5,0xb7c6,0xb7c7, + 0xb7c8,0xb7c9,0xb7ca,0xb7cb,0xb7cc,0xb7cd,0xb7ce,0xb7cf, + 0xb7d0,0xb7d1,0xb7d2,0xb7d3,0xb7d4,0xb7d5,0xb7d6,0xb7d7, + 0xb7d8,0xb7d9,0xb7da,0xb7db,0xb7dc,0xb7dd,0xb7de,0xb7df, + 0xb7e0,0xb7e1,0xb7e2,0xb7e3,0xb7e4,0xb7e5,0xb7e6,0xb7e7, + 0xb7e8,0xb7e9,0xb7ea,0xb7eb,0xb7ec,0xb7ed,0xb7ee,0xb7ef, + 0xb7f0,0xb7f1,0xb7f2,0xb7f3,0xb7f4,0xb7f5,0xb7f6,0xb7f7, + 0xb7f8,0xb7f9,0xb7fa,0xb7fb,0xb7fc,0xb7fd,0xb7fe,0xb7ff, + 0xb800,0xb801,0xb802,0xb803,0xb804,0xb805,0xb806,0xb807, + 0xb808,0xb809,0xb80a,0xb80b,0xb80c,0xb80d,0xb80e,0xb80f, + 0xb810,0xb811,0xb812,0xb813,0xb814,0xb815,0xb816,0xb817, + 0xb818,0xb819,0xb81a,0xb81b,0xb81c,0xb81d,0xb81e,0xb81f, + 0xb820,0xb821,0xb822,0xb823,0xb824,0xb825,0xb826,0xb827, + 0xb828,0xb829,0xb82a,0xb82b,0xb82c,0xb82d,0xb82e,0xb82f, + 0xb830,0xb831,0xb832,0xb833,0xb834,0xb835,0xb836,0xb837, + 0xb838,0xb839,0xb83a,0xb83b,0xb83c,0xb83d,0xb83e,0xb83f, + 0xb840,0xb841,0xb842,0xb843,0xb844,0xb845,0xb846,0xb847, + 0xb848,0xb849,0xb84a,0xb84b,0xb84c,0xb84d,0xb84e,0xb84f, + 0xb850,0xb851,0xb852,0xb853,0xb854,0xb855,0xb856,0xb857, + 0xb858,0xb859,0xb85a,0xb85b,0xb85c,0xb85d,0xb85e,0xb85f, + 0xb860,0xb861,0xb862,0xb863,0xb864,0xb865,0xb866,0xb867, + 0xb868,0xb869,0xb86a,0xb86b,0xb86c,0xb86d,0xb86e,0xb86f, + 0xb870,0xb871,0xb872,0xb873,0xb874,0xb875,0xb876,0xb877, + 0xb878,0xb879,0xb87a,0xb87b,0xb87c,0xb87d,0xb87e,0xb87f, + 0xb880,0xb881,0xb882,0xb883,0xb884,0xb885,0xb886,0xb887, + 0xb888,0xb889,0xb88a,0xb88b,0xb88c,0xb88d,0xb88e,0xb88f, + 0xb890,0xb891,0xb892,0xb893,0xb894,0xb895,0xb896,0xb897, + 0xb898,0xb899,0xb89a,0xb89b,0xb89c,0xb89d,0xb89e,0xb89f, + 0xb8a0,0xb8a1,0xb8a2,0xb8a3,0xb8a4,0xb8a5,0xb8a6,0xb8a7, + 0xb8a8,0xb8a9,0xb8aa,0xb8ab,0xb8ac,0xb8ad,0xb8ae,0xb8af, + 0xb8b0,0xb8b1,0xb8b2,0xb8b3,0xb8b4,0xb8b5,0xb8b6,0xb8b7, + 0xb8b8,0xb8b9,0xb8ba,0xb8bb,0xb8bc,0xb8bd,0xb8be,0xb8bf, + 0xb8c0,0xb8c1,0xb8c2,0xb8c3,0xb8c4,0xb8c5,0xb8c6,0xb8c7, + 0xb8c8,0xb8c9,0xb8ca,0xb8cb,0xb8cc,0xb8cd,0xb8ce,0xb8cf, + 0xb8d0,0xb8d1,0xb8d2,0xb8d3,0xb8d4,0xb8d5,0xb8d6,0xb8d7, + 0xb8d8,0xb8d9,0xb8da,0xb8db,0xb8dc,0xb8dd,0xb8de,0xb8df, + 0xb8e0,0xb8e1,0xb8e2,0xb8e3,0xb8e4,0xb8e5,0xb8e6,0xb8e7, + 0xb8e8,0xb8e9,0xb8ea,0xb8eb,0xb8ec,0xb8ed,0xb8ee,0xb8ef, + 0xb8f0,0xb8f1,0xb8f2,0xb8f3,0xb8f4,0xb8f5,0xb8f6,0xb8f7, + 0xb8f8,0xb8f9,0xb8fa,0xb8fb,0xb8fc,0xb8fd,0xb8fe,0xb8ff, + 0xb900,0xb901,0xb902,0xb903,0xb904,0xb905,0xb906,0xb907, + 0xb908,0xb909,0xb90a,0xb90b,0xb90c,0xb90d,0xb90e,0xb90f, + 0xb910,0xb911,0xb912,0xb913,0xb914,0xb915,0xb916,0xb917, + 0xb918,0xb919,0xb91a,0xb91b,0xb91c,0xb91d,0xb91e,0xb91f, + 0xb920,0xb921,0xb922,0xb923,0xb924,0xb925,0xb926,0xb927, + 0xb928,0xb929,0xb92a,0xb92b,0xb92c,0xb92d,0xb92e,0xb92f, + 0xb930,0xb931,0xb932,0xb933,0xb934,0xb935,0xb936,0xb937, + 0xb938,0xb939,0xb93a,0xb93b,0xb93c,0xb93d,0xb93e,0xb93f, + 0xb940,0xb941,0xb942,0xb943,0xb944,0xb945,0xb946,0xb947, + 0xb948,0xb949,0xb94a,0xb94b,0xb94c,0xb94d,0xb94e,0xb94f, + 0xb950,0xb951,0xb952,0xb953,0xb954,0xb955,0xb956,0xb957, + 0xb958,0xb959,0xb95a,0xb95b,0xb95c,0xb95d,0xb95e,0xb95f, + 0xb960,0xb961,0xb962,0xb963,0xb964,0xb965,0xb966,0xb967, + 0xb968,0xb969,0xb96a,0xb96b,0xb96c,0xb96d,0xb96e,0xb96f, + 0xb970,0xb971,0xb972,0xb973,0xb974,0xb975,0xb976,0xb977, + 0xb978,0xb979,0xb97a,0xb97b,0xb97c,0xb97d,0xb97e,0xb97f, + 0xb980,0xb981,0xb982,0xb983,0xb984,0xb985,0xb986,0xb987, + 0xb988,0xb989,0xb98a,0xb98b,0xb98c,0xb98d,0xb98e,0xb98f, + 0xb990,0xb991,0xb992,0xb993,0xb994,0xb995,0xb996,0xb997, + 0xb998,0xb999,0xb99a,0xb99b,0xb99c,0xb99d,0xb99e,0xb99f, + 0xb9a0,0xb9a1,0xb9a2,0xb9a3,0xb9a4,0xb9a5,0xb9a6,0xb9a7, + 0xb9a8,0xb9a9,0xb9aa,0xb9ab,0xb9ac,0xb9ad,0xb9ae,0xb9af, + 0xb9b0,0xb9b1,0xb9b2,0xb9b3,0xb9b4,0xb9b5,0xb9b6,0xb9b7, + 0xb9b8,0xb9b9,0xb9ba,0xb9bb,0xb9bc,0xb9bd,0xb9be,0xb9bf, + 0xb9c0,0xb9c1,0xb9c2,0xb9c3,0xb9c4,0xb9c5,0xb9c6,0xb9c7, + 0xb9c8,0xb9c9,0xb9ca,0xb9cb,0xb9cc,0xb9cd,0xb9ce,0xb9cf, + 0xb9d0,0xb9d1,0xb9d2,0xb9d3,0xb9d4,0xb9d5,0xb9d6,0xb9d7, + 0xb9d8,0xb9d9,0xb9da,0xb9db,0xb9dc,0xb9dd,0xb9de,0xb9df, + 0xb9e0,0xb9e1,0xb9e2,0xb9e3,0xb9e4,0xb9e5,0xb9e6,0xb9e7, + 0xb9e8,0xb9e9,0xb9ea,0xb9eb,0xb9ec,0xb9ed,0xb9ee,0xb9ef, + 0xb9f0,0xb9f1,0xb9f2,0xb9f3,0xb9f4,0xb9f5,0xb9f6,0xb9f7, + 0xb9f8,0xb9f9,0xb9fa,0xb9fb,0xb9fc,0xb9fd,0xb9fe,0xb9ff, + 0xba00,0xba01,0xba02,0xba03,0xba04,0xba05,0xba06,0xba07, + 0xba08,0xba09,0xba0a,0xba0b,0xba0c,0xba0d,0xba0e,0xba0f, + 0xba10,0xba11,0xba12,0xba13,0xba14,0xba15,0xba16,0xba17, + 0xba18,0xba19,0xba1a,0xba1b,0xba1c,0xba1d,0xba1e,0xba1f, + 0xba20,0xba21,0xba22,0xba23,0xba24,0xba25,0xba26,0xba27, + 0xba28,0xba29,0xba2a,0xba2b,0xba2c,0xba2d,0xba2e,0xba2f, + 0xba30,0xba31,0xba32,0xba33,0xba34,0xba35,0xba36,0xba37, + 0xba38,0xba39,0xba3a,0xba3b,0xba3c,0xba3d,0xba3e,0xba3f, + 0xba40,0xba41,0xba42,0xba43,0xba44,0xba45,0xba46,0xba47, + 0xba48,0xba49,0xba4a,0xba4b,0xba4c,0xba4d,0xba4e,0xba4f, + 0xba50,0xba51,0xba52,0xba53,0xba54,0xba55,0xba56,0xba57, + 0xba58,0xba59,0xba5a,0xba5b,0xba5c,0xba5d,0xba5e,0xba5f, + 0xba60,0xba61,0xba62,0xba63,0xba64,0xba65,0xba66,0xba67, + 0xba68,0xba69,0xba6a,0xba6b,0xba6c,0xba6d,0xba6e,0xba6f, + 0xba70,0xba71,0xba72,0xba73,0xba74,0xba75,0xba76,0xba77, + 0xba78,0xba79,0xba7a,0xba7b,0xba7c,0xba7d,0xba7e,0xba7f, + 0xba80,0xba81,0xba82,0xba83,0xba84,0xba85,0xba86,0xba87, + 0xba88,0xba89,0xba8a,0xba8b,0xba8c,0xba8d,0xba8e,0xba8f, + 0xba90,0xba91,0xba92,0xba93,0xba94,0xba95,0xba96,0xba97, + 0xba98,0xba99,0xba9a,0xba9b,0xba9c,0xba9d,0xba9e,0xba9f, + 0xbaa0,0xbaa1,0xbaa2,0xbaa3,0xbaa4,0xbaa5,0xbaa6,0xbaa7, + 0xbaa8,0xbaa9,0xbaaa,0xbaab,0xbaac,0xbaad,0xbaae,0xbaaf, + 0xbab0,0xbab1,0xbab2,0xbab3,0xbab4,0xbab5,0xbab6,0xbab7, + 0xbab8,0xbab9,0xbaba,0xbabb,0xbabc,0xbabd,0xbabe,0xbabf, + 0xbac0,0xbac1,0xbac2,0xbac3,0xbac4,0xbac5,0xbac6,0xbac7, + 0xbac8,0xbac9,0xbaca,0xbacb,0xbacc,0xbacd,0xbace,0xbacf, + 0xbad0,0xbad1,0xbad2,0xbad3,0xbad4,0xbad5,0xbad6,0xbad7, + 0xbad8,0xbad9,0xbada,0xbadb,0xbadc,0xbadd,0xbade,0xbadf, + 0xbae0,0xbae1,0xbae2,0xbae3,0xbae4,0xbae5,0xbae6,0xbae7, + 0xbae8,0xbae9,0xbaea,0xbaeb,0xbaec,0xbaed,0xbaee,0xbaef, + 0xbaf0,0xbaf1,0xbaf2,0xbaf3,0xbaf4,0xbaf5,0xbaf6,0xbaf7, + 0xbaf8,0xbaf9,0xbafa,0xbafb,0xbafc,0xbafd,0xbafe,0xbaff, + 0xbb00,0xbb01,0xbb02,0xbb03,0xbb04,0xbb05,0xbb06,0xbb07, + 0xbb08,0xbb09,0xbb0a,0xbb0b,0xbb0c,0xbb0d,0xbb0e,0xbb0f, + 0xbb10,0xbb11,0xbb12,0xbb13,0xbb14,0xbb15,0xbb16,0xbb17, + 0xbb18,0xbb19,0xbb1a,0xbb1b,0xbb1c,0xbb1d,0xbb1e,0xbb1f, + 0xbb20,0xbb21,0xbb22,0xbb23,0xbb24,0xbb25,0xbb26,0xbb27, + 0xbb28,0xbb29,0xbb2a,0xbb2b,0xbb2c,0xbb2d,0xbb2e,0xbb2f, + 0xbb30,0xbb31,0xbb32,0xbb33,0xbb34,0xbb35,0xbb36,0xbb37, + 0xbb38,0xbb39,0xbb3a,0xbb3b,0xbb3c,0xbb3d,0xbb3e,0xbb3f, + 0xbb40,0xbb41,0xbb42,0xbb43,0xbb44,0xbb45,0xbb46,0xbb47, + 0xbb48,0xbb49,0xbb4a,0xbb4b,0xbb4c,0xbb4d,0xbb4e,0xbb4f, + 0xbb50,0xbb51,0xbb52,0xbb53,0xbb54,0xbb55,0xbb56,0xbb57, + 0xbb58,0xbb59,0xbb5a,0xbb5b,0xbb5c,0xbb5d,0xbb5e,0xbb5f, + 0xbb60,0xbb61,0xbb62,0xbb63,0xbb64,0xbb65,0xbb66,0xbb67, + 0xbb68,0xbb69,0xbb6a,0xbb6b,0xbb6c,0xbb6d,0xbb6e,0xbb6f, + 0xbb70,0xbb71,0xbb72,0xbb73,0xbb74,0xbb75,0xbb76,0xbb77, + 0xbb78,0xbb79,0xbb7a,0xbb7b,0xbb7c,0xbb7d,0xbb7e,0xbb7f, + 0xbb80,0xbb81,0xbb82,0xbb83,0xbb84,0xbb85,0xbb86,0xbb87, + 0xbb88,0xbb89,0xbb8a,0xbb8b,0xbb8c,0xbb8d,0xbb8e,0xbb8f, + 0xbb90,0xbb91,0xbb92,0xbb93,0xbb94,0xbb95,0xbb96,0xbb97, + 0xbb98,0xbb99,0xbb9a,0xbb9b,0xbb9c,0xbb9d,0xbb9e,0xbb9f, + 0xbba0,0xbba1,0xbba2,0xbba3,0xbba4,0xbba5,0xbba6,0xbba7, + 0xbba8,0xbba9,0xbbaa,0xbbab,0xbbac,0xbbad,0xbbae,0xbbaf, + 0xbbb0,0xbbb1,0xbbb2,0xbbb3,0xbbb4,0xbbb5,0xbbb6,0xbbb7, + 0xbbb8,0xbbb9,0xbbba,0xbbbb,0xbbbc,0xbbbd,0xbbbe,0xbbbf, + 0xbbc0,0xbbc1,0xbbc2,0xbbc3,0xbbc4,0xbbc5,0xbbc6,0xbbc7, + 0xbbc8,0xbbc9,0xbbca,0xbbcb,0xbbcc,0xbbcd,0xbbce,0xbbcf, + 0xbbd0,0xbbd1,0xbbd2,0xbbd3,0xbbd4,0xbbd5,0xbbd6,0xbbd7, + 0xbbd8,0xbbd9,0xbbda,0xbbdb,0xbbdc,0xbbdd,0xbbde,0xbbdf, + 0xbbe0,0xbbe1,0xbbe2,0xbbe3,0xbbe4,0xbbe5,0xbbe6,0xbbe7, + 0xbbe8,0xbbe9,0xbbea,0xbbeb,0xbbec,0xbbed,0xbbee,0xbbef, + 0xbbf0,0xbbf1,0xbbf2,0xbbf3,0xbbf4,0xbbf5,0xbbf6,0xbbf7, + 0xbbf8,0xbbf9,0xbbfa,0xbbfb,0xbbfc,0xbbfd,0xbbfe,0xbbff, + 0xbc00,0xbc01,0xbc02,0xbc03,0xbc04,0xbc05,0xbc06,0xbc07, + 0xbc08,0xbc09,0xbc0a,0xbc0b,0xbc0c,0xbc0d,0xbc0e,0xbc0f, + 0xbc10,0xbc11,0xbc12,0xbc13,0xbc14,0xbc15,0xbc16,0xbc17, + 0xbc18,0xbc19,0xbc1a,0xbc1b,0xbc1c,0xbc1d,0xbc1e,0xbc1f, + 0xbc20,0xbc21,0xbc22,0xbc23,0xbc24,0xbc25,0xbc26,0xbc27, + 0xbc28,0xbc29,0xbc2a,0xbc2b,0xbc2c,0xbc2d,0xbc2e,0xbc2f, + 0xbc30,0xbc31,0xbc32,0xbc33,0xbc34,0xbc35,0xbc36,0xbc37, + 0xbc38,0xbc39,0xbc3a,0xbc3b,0xbc3c,0xbc3d,0xbc3e,0xbc3f, + 0xbc40,0xbc41,0xbc42,0xbc43,0xbc44,0xbc45,0xbc46,0xbc47, + 0xbc48,0xbc49,0xbc4a,0xbc4b,0xbc4c,0xbc4d,0xbc4e,0xbc4f, + 0xbc50,0xbc51,0xbc52,0xbc53,0xbc54,0xbc55,0xbc56,0xbc57, + 0xbc58,0xbc59,0xbc5a,0xbc5b,0xbc5c,0xbc5d,0xbc5e,0xbc5f, + 0xbc60,0xbc61,0xbc62,0xbc63,0xbc64,0xbc65,0xbc66,0xbc67, + 0xbc68,0xbc69,0xbc6a,0xbc6b,0xbc6c,0xbc6d,0xbc6e,0xbc6f, + 0xbc70,0xbc71,0xbc72,0xbc73,0xbc74,0xbc75,0xbc76,0xbc77, + 0xbc78,0xbc79,0xbc7a,0xbc7b,0xbc7c,0xbc7d,0xbc7e,0xbc7f, + 0xbc80,0xbc81,0xbc82,0xbc83,0xbc84,0xbc85,0xbc86,0xbc87, + 0xbc88,0xbc89,0xbc8a,0xbc8b,0xbc8c,0xbc8d,0xbc8e,0xbc8f, + 0xbc90,0xbc91,0xbc92,0xbc93,0xbc94,0xbc95,0xbc96,0xbc97, + 0xbc98,0xbc99,0xbc9a,0xbc9b,0xbc9c,0xbc9d,0xbc9e,0xbc9f, + 0xbca0,0xbca1,0xbca2,0xbca3,0xbca4,0xbca5,0xbca6,0xbca7, + 0xbca8,0xbca9,0xbcaa,0xbcab,0xbcac,0xbcad,0xbcae,0xbcaf, + 0xbcb0,0xbcb1,0xbcb2,0xbcb3,0xbcb4,0xbcb5,0xbcb6,0xbcb7, + 0xbcb8,0xbcb9,0xbcba,0xbcbb,0xbcbc,0xbcbd,0xbcbe,0xbcbf, + 0xbcc0,0xbcc1,0xbcc2,0xbcc3,0xbcc4,0xbcc5,0xbcc6,0xbcc7, + 0xbcc8,0xbcc9,0xbcca,0xbccb,0xbccc,0xbccd,0xbcce,0xbccf, + 0xbcd0,0xbcd1,0xbcd2,0xbcd3,0xbcd4,0xbcd5,0xbcd6,0xbcd7, + 0xbcd8,0xbcd9,0xbcda,0xbcdb,0xbcdc,0xbcdd,0xbcde,0xbcdf, + 0xbce0,0xbce1,0xbce2,0xbce3,0xbce4,0xbce5,0xbce6,0xbce7, + 0xbce8,0xbce9,0xbcea,0xbceb,0xbcec,0xbced,0xbcee,0xbcef, + 0xbcf0,0xbcf1,0xbcf2,0xbcf3,0xbcf4,0xbcf5,0xbcf6,0xbcf7, + 0xbcf8,0xbcf9,0xbcfa,0xbcfb,0xbcfc,0xbcfd,0xbcfe,0xbcff, + 0xbd00,0xbd01,0xbd02,0xbd03,0xbd04,0xbd05,0xbd06,0xbd07, + 0xbd08,0xbd09,0xbd0a,0xbd0b,0xbd0c,0xbd0d,0xbd0e,0xbd0f, + 0xbd10,0xbd11,0xbd12,0xbd13,0xbd14,0xbd15,0xbd16,0xbd17, + 0xbd18,0xbd19,0xbd1a,0xbd1b,0xbd1c,0xbd1d,0xbd1e,0xbd1f, + 0xbd20,0xbd21,0xbd22,0xbd23,0xbd24,0xbd25,0xbd26,0xbd27, + 0xbd28,0xbd29,0xbd2a,0xbd2b,0xbd2c,0xbd2d,0xbd2e,0xbd2f, + 0xbd30,0xbd31,0xbd32,0xbd33,0xbd34,0xbd35,0xbd36,0xbd37, + 0xbd38,0xbd39,0xbd3a,0xbd3b,0xbd3c,0xbd3d,0xbd3e,0xbd3f, + 0xbd40,0xbd41,0xbd42,0xbd43,0xbd44,0xbd45,0xbd46,0xbd47, + 0xbd48,0xbd49,0xbd4a,0xbd4b,0xbd4c,0xbd4d,0xbd4e,0xbd4f, + 0xbd50,0xbd51,0xbd52,0xbd53,0xbd54,0xbd55,0xbd56,0xbd57, + 0xbd58,0xbd59,0xbd5a,0xbd5b,0xbd5c,0xbd5d,0xbd5e,0xbd5f, + 0xbd60,0xbd61,0xbd62,0xbd63,0xbd64,0xbd65,0xbd66,0xbd67, + 0xbd68,0xbd69,0xbd6a,0xbd6b,0xbd6c,0xbd6d,0xbd6e,0xbd6f, + 0xbd70,0xbd71,0xbd72,0xbd73,0xbd74,0xbd75,0xbd76,0xbd77, + 0xbd78,0xbd79,0xbd7a,0xbd7b,0xbd7c,0xbd7d,0xbd7e,0xbd7f, + 0xbd80,0xbd81,0xbd82,0xbd83,0xbd84,0xbd85,0xbd86,0xbd87, + 0xbd88,0xbd89,0xbd8a,0xbd8b,0xbd8c,0xbd8d,0xbd8e,0xbd8f, + 0xbd90,0xbd91,0xbd92,0xbd93,0xbd94,0xbd95,0xbd96,0xbd97, + 0xbd98,0xbd99,0xbd9a,0xbd9b,0xbd9c,0xbd9d,0xbd9e,0xbd9f, + 0xbda0,0xbda1,0xbda2,0xbda3,0xbda4,0xbda5,0xbda6,0xbda7, + 0xbda8,0xbda9,0xbdaa,0xbdab,0xbdac,0xbdad,0xbdae,0xbdaf, + 0xbdb0,0xbdb1,0xbdb2,0xbdb3,0xbdb4,0xbdb5,0xbdb6,0xbdb7, + 0xbdb8,0xbdb9,0xbdba,0xbdbb,0xbdbc,0xbdbd,0xbdbe,0xbdbf, + 0xbdc0,0xbdc1,0xbdc2,0xbdc3,0xbdc4,0xbdc5,0xbdc6,0xbdc7, + 0xbdc8,0xbdc9,0xbdca,0xbdcb,0xbdcc,0xbdcd,0xbdce,0xbdcf, + 0xbdd0,0xbdd1,0xbdd2,0xbdd3,0xbdd4,0xbdd5,0xbdd6,0xbdd7, + 0xbdd8,0xbdd9,0xbdda,0xbddb,0xbddc,0xbddd,0xbdde,0xbddf, + 0xbde0,0xbde1,0xbde2,0xbde3,0xbde4,0xbde5,0xbde6,0xbde7, + 0xbde8,0xbde9,0xbdea,0xbdeb,0xbdec,0xbded,0xbdee,0xbdef, + 0xbdf0,0xbdf1,0xbdf2,0xbdf3,0xbdf4,0xbdf5,0xbdf6,0xbdf7, + 0xbdf8,0xbdf9,0xbdfa,0xbdfb,0xbdfc,0xbdfd,0xbdfe,0xbdff, + 0xbe00,0xbe01,0xbe02,0xbe03,0xbe04,0xbe05,0xbe06,0xbe07, + 0xbe08,0xbe09,0xbe0a,0xbe0b,0xbe0c,0xbe0d,0xbe0e,0xbe0f, + 0xbe10,0xbe11,0xbe12,0xbe13,0xbe14,0xbe15,0xbe16,0xbe17, + 0xbe18,0xbe19,0xbe1a,0xbe1b,0xbe1c,0xbe1d,0xbe1e,0xbe1f, + 0xbe20,0xbe21,0xbe22,0xbe23,0xbe24,0xbe25,0xbe26,0xbe27, + 0xbe28,0xbe29,0xbe2a,0xbe2b,0xbe2c,0xbe2d,0xbe2e,0xbe2f, + 0xbe30,0xbe31,0xbe32,0xbe33,0xbe34,0xbe35,0xbe36,0xbe37, + 0xbe38,0xbe39,0xbe3a,0xbe3b,0xbe3c,0xbe3d,0xbe3e,0xbe3f, + 0xbe40,0xbe41,0xbe42,0xbe43,0xbe44,0xbe45,0xbe46,0xbe47, + 0xbe48,0xbe49,0xbe4a,0xbe4b,0xbe4c,0xbe4d,0xbe4e,0xbe4f, + 0xbe50,0xbe51,0xbe52,0xbe53,0xbe54,0xbe55,0xbe56,0xbe57, + 0xbe58,0xbe59,0xbe5a,0xbe5b,0xbe5c,0xbe5d,0xbe5e,0xbe5f, + 0xbe60,0xbe61,0xbe62,0xbe63,0xbe64,0xbe65,0xbe66,0xbe67, + 0xbe68,0xbe69,0xbe6a,0xbe6b,0xbe6c,0xbe6d,0xbe6e,0xbe6f, + 0xbe70,0xbe71,0xbe72,0xbe73,0xbe74,0xbe75,0xbe76,0xbe77, + 0xbe78,0xbe79,0xbe7a,0xbe7b,0xbe7c,0xbe7d,0xbe7e,0xbe7f, + 0xbe80,0xbe81,0xbe82,0xbe83,0xbe84,0xbe85,0xbe86,0xbe87, + 0xbe88,0xbe89,0xbe8a,0xbe8b,0xbe8c,0xbe8d,0xbe8e,0xbe8f, + 0xbe90,0xbe91,0xbe92,0xbe93,0xbe94,0xbe95,0xbe96,0xbe97, + 0xbe98,0xbe99,0xbe9a,0xbe9b,0xbe9c,0xbe9d,0xbe9e,0xbe9f, + 0xbea0,0xbea1,0xbea2,0xbea3,0xbea4,0xbea5,0xbea6,0xbea7, + 0xbea8,0xbea9,0xbeaa,0xbeab,0xbeac,0xbead,0xbeae,0xbeaf, + 0xbeb0,0xbeb1,0xbeb2,0xbeb3,0xbeb4,0xbeb5,0xbeb6,0xbeb7, + 0xbeb8,0xbeb9,0xbeba,0xbebb,0xbebc,0xbebd,0xbebe,0xbebf, + 0xbec0,0xbec1,0xbec2,0xbec3,0xbec4,0xbec5,0xbec6,0xbec7, + 0xbec8,0xbec9,0xbeca,0xbecb,0xbecc,0xbecd,0xbece,0xbecf, + 0xbed0,0xbed1,0xbed2,0xbed3,0xbed4,0xbed5,0xbed6,0xbed7, + 0xbed8,0xbed9,0xbeda,0xbedb,0xbedc,0xbedd,0xbede,0xbedf, + 0xbee0,0xbee1,0xbee2,0xbee3,0xbee4,0xbee5,0xbee6,0xbee7, + 0xbee8,0xbee9,0xbeea,0xbeeb,0xbeec,0xbeed,0xbeee,0xbeef, + 0xbef0,0xbef1,0xbef2,0xbef3,0xbef4,0xbef5,0xbef6,0xbef7, + 0xbef8,0xbef9,0xbefa,0xbefb,0xbefc,0xbefd,0xbefe,0xbeff, + 0xbf00,0xbf01,0xbf02,0xbf03,0xbf04,0xbf05,0xbf06,0xbf07, + 0xbf08,0xbf09,0xbf0a,0xbf0b,0xbf0c,0xbf0d,0xbf0e,0xbf0f, + 0xbf10,0xbf11,0xbf12,0xbf13,0xbf14,0xbf15,0xbf16,0xbf17, + 0xbf18,0xbf19,0xbf1a,0xbf1b,0xbf1c,0xbf1d,0xbf1e,0xbf1f, + 0xbf20,0xbf21,0xbf22,0xbf23,0xbf24,0xbf25,0xbf26,0xbf27, + 0xbf28,0xbf29,0xbf2a,0xbf2b,0xbf2c,0xbf2d,0xbf2e,0xbf2f, + 0xbf30,0xbf31,0xbf32,0xbf33,0xbf34,0xbf35,0xbf36,0xbf37, + 0xbf38,0xbf39,0xbf3a,0xbf3b,0xbf3c,0xbf3d,0xbf3e,0xbf3f, + 0xbf40,0xbf41,0xbf42,0xbf43,0xbf44,0xbf45,0xbf46,0xbf47, + 0xbf48,0xbf49,0xbf4a,0xbf4b,0xbf4c,0xbf4d,0xbf4e,0xbf4f, + 0xbf50,0xbf51,0xbf52,0xbf53,0xbf54,0xbf55,0xbf56,0xbf57, + 0xbf58,0xbf59,0xbf5a,0xbf5b,0xbf5c,0xbf5d,0xbf5e,0xbf5f, + 0xbf60,0xbf61,0xbf62,0xbf63,0xbf64,0xbf65,0xbf66,0xbf67, + 0xbf68,0xbf69,0xbf6a,0xbf6b,0xbf6c,0xbf6d,0xbf6e,0xbf6f, + 0xbf70,0xbf71,0xbf72,0xbf73,0xbf74,0xbf75,0xbf76,0xbf77, + 0xbf78,0xbf79,0xbf7a,0xbf7b,0xbf7c,0xbf7d,0xbf7e,0xbf7f, + 0xbf80,0xbf81,0xbf82,0xbf83,0xbf84,0xbf85,0xbf86,0xbf87, + 0xbf88,0xbf89,0xbf8a,0xbf8b,0xbf8c,0xbf8d,0xbf8e,0xbf8f, + 0xbf90,0xbf91,0xbf92,0xbf93,0xbf94,0xbf95,0xbf96,0xbf97, + 0xbf98,0xbf99,0xbf9a,0xbf9b,0xbf9c,0xbf9d,0xbf9e,0xbf9f, + 0xbfa0,0xbfa1,0xbfa2,0xbfa3,0xbfa4,0xbfa5,0xbfa6,0xbfa7, + 0xbfa8,0xbfa9,0xbfaa,0xbfab,0xbfac,0xbfad,0xbfae,0xbfaf, + 0xbfb0,0xbfb1,0xbfb2,0xbfb3,0xbfb4,0xbfb5,0xbfb6,0xbfb7, + 0xbfb8,0xbfb9,0xbfba,0xbfbb,0xbfbc,0xbfbd,0xbfbe,0xbfbf, + 0xbfc0,0xbfc1,0xbfc2,0xbfc3,0xbfc4,0xbfc5,0xbfc6,0xbfc7, + 0xbfc8,0xbfc9,0xbfca,0xbfcb,0xbfcc,0xbfcd,0xbfce,0xbfcf, + 0xbfd0,0xbfd1,0xbfd2,0xbfd3,0xbfd4,0xbfd5,0xbfd6,0xbfd7, + 0xbfd8,0xbfd9,0xbfda,0xbfdb,0xbfdc,0xbfdd,0xbfde,0xbfdf, + 0xbfe0,0xbfe1,0xbfe2,0xbfe3,0xbfe4,0xbfe5,0xbfe6,0xbfe7, + 0xbfe8,0xbfe9,0xbfea,0xbfeb,0xbfec,0xbfed,0xbfee,0xbfef, + 0xbff0,0xbff1,0xbff2,0xbff3,0xbff4,0xbff5,0xbff6,0xbff7, + 0xbff8,0xbff9,0xbffa,0xbffb,0xbffc,0xbffd,0xbffe,0xbfff, + 0xc000,0xc001,0xc002,0xc003,0xc004,0xc005,0xc006,0xc007, + 0xc008,0xc009,0xc00a,0xc00b,0xc00c,0xc00d,0xc00e,0xc00f, + 0xc010,0xc011,0xc012,0xc013,0xc014,0xc015,0xc016,0xc017, + 0xc018,0xc019,0xc01a,0xc01b,0xc01c,0xc01d,0xc01e,0xc01f, + 0xc020,0xc021,0xc022,0xc023,0xc024,0xc025,0xc026,0xc027, + 0xc028,0xc029,0xc02a,0xc02b,0xc02c,0xc02d,0xc02e,0xc02f, + 0xc030,0xc031,0xc032,0xc033,0xc034,0xc035,0xc036,0xc037, + 0xc038,0xc039,0xc03a,0xc03b,0xc03c,0xc03d,0xc03e,0xc03f, + 0xc040,0xc041,0xc042,0xc043,0xc044,0xc045,0xc046,0xc047, + 0xc048,0xc049,0xc04a,0xc04b,0xc04c,0xc04d,0xc04e,0xc04f, + 0xc050,0xc051,0xc052,0xc053,0xc054,0xc055,0xc056,0xc057, + 0xc058,0xc059,0xc05a,0xc05b,0xc05c,0xc05d,0xc05e,0xc05f, + 0xc060,0xc061,0xc062,0xc063,0xc064,0xc065,0xc066,0xc067, + 0xc068,0xc069,0xc06a,0xc06b,0xc06c,0xc06d,0xc06e,0xc06f, + 0xc070,0xc071,0xc072,0xc073,0xc074,0xc075,0xc076,0xc077, + 0xc078,0xc079,0xc07a,0xc07b,0xc07c,0xc07d,0xc07e,0xc07f, + 0xc080,0xc081,0xc082,0xc083,0xc084,0xc085,0xc086,0xc087, + 0xc088,0xc089,0xc08a,0xc08b,0xc08c,0xc08d,0xc08e,0xc08f, + 0xc090,0xc091,0xc092,0xc093,0xc094,0xc095,0xc096,0xc097, + 0xc098,0xc099,0xc09a,0xc09b,0xc09c,0xc09d,0xc09e,0xc09f, + 0xc0a0,0xc0a1,0xc0a2,0xc0a3,0xc0a4,0xc0a5,0xc0a6,0xc0a7, + 0xc0a8,0xc0a9,0xc0aa,0xc0ab,0xc0ac,0xc0ad,0xc0ae,0xc0af, + 0xc0b0,0xc0b1,0xc0b2,0xc0b3,0xc0b4,0xc0b5,0xc0b6,0xc0b7, + 0xc0b8,0xc0b9,0xc0ba,0xc0bb,0xc0bc,0xc0bd,0xc0be,0xc0bf, + 0xc0c0,0xc0c1,0xc0c2,0xc0c3,0xc0c4,0xc0c5,0xc0c6,0xc0c7, + 0xc0c8,0xc0c9,0xc0ca,0xc0cb,0xc0cc,0xc0cd,0xc0ce,0xc0cf, + 0xc0d0,0xc0d1,0xc0d2,0xc0d3,0xc0d4,0xc0d5,0xc0d6,0xc0d7, + 0xc0d8,0xc0d9,0xc0da,0xc0db,0xc0dc,0xc0dd,0xc0de,0xc0df, + 0xc0e0,0xc0e1,0xc0e2,0xc0e3,0xc0e4,0xc0e5,0xc0e6,0xc0e7, + 0xc0e8,0xc0e9,0xc0ea,0xc0eb,0xc0ec,0xc0ed,0xc0ee,0xc0ef, + 0xc0f0,0xc0f1,0xc0f2,0xc0f3,0xc0f4,0xc0f5,0xc0f6,0xc0f7, + 0xc0f8,0xc0f9,0xc0fa,0xc0fb,0xc0fc,0xc0fd,0xc0fe,0xc0ff, + 0xc100,0xc101,0xc102,0xc103,0xc104,0xc105,0xc106,0xc107, + 0xc108,0xc109,0xc10a,0xc10b,0xc10c,0xc10d,0xc10e,0xc10f, + 0xc110,0xc111,0xc112,0xc113,0xc114,0xc115,0xc116,0xc117, + 0xc118,0xc119,0xc11a,0xc11b,0xc11c,0xc11d,0xc11e,0xc11f, + 0xc120,0xc121,0xc122,0xc123,0xc124,0xc125,0xc126,0xc127, + 0xc128,0xc129,0xc12a,0xc12b,0xc12c,0xc12d,0xc12e,0xc12f, + 0xc130,0xc131,0xc132,0xc133,0xc134,0xc135,0xc136,0xc137, + 0xc138,0xc139,0xc13a,0xc13b,0xc13c,0xc13d,0xc13e,0xc13f, + 0xc140,0xc141,0xc142,0xc143,0xc144,0xc145,0xc146,0xc147, + 0xc148,0xc149,0xc14a,0xc14b,0xc14c,0xc14d,0xc14e,0xc14f, + 0xc150,0xc151,0xc152,0xc153,0xc154,0xc155,0xc156,0xc157, + 0xc158,0xc159,0xc15a,0xc15b,0xc15c,0xc15d,0xc15e,0xc15f, + 0xc160,0xc161,0xc162,0xc163,0xc164,0xc165,0xc166,0xc167, + 0xc168,0xc169,0xc16a,0xc16b,0xc16c,0xc16d,0xc16e,0xc16f, + 0xc170,0xc171,0xc172,0xc173,0xc174,0xc175,0xc176,0xc177, + 0xc178,0xc179,0xc17a,0xc17b,0xc17c,0xc17d,0xc17e,0xc17f, + 0xc180,0xc181,0xc182,0xc183,0xc184,0xc185,0xc186,0xc187, + 0xc188,0xc189,0xc18a,0xc18b,0xc18c,0xc18d,0xc18e,0xc18f, + 0xc190,0xc191,0xc192,0xc193,0xc194,0xc195,0xc196,0xc197, + 0xc198,0xc199,0xc19a,0xc19b,0xc19c,0xc19d,0xc19e,0xc19f, + 0xc1a0,0xc1a1,0xc1a2,0xc1a3,0xc1a4,0xc1a5,0xc1a6,0xc1a7, + 0xc1a8,0xc1a9,0xc1aa,0xc1ab,0xc1ac,0xc1ad,0xc1ae,0xc1af, + 0xc1b0,0xc1b1,0xc1b2,0xc1b3,0xc1b4,0xc1b5,0xc1b6,0xc1b7, + 0xc1b8,0xc1b9,0xc1ba,0xc1bb,0xc1bc,0xc1bd,0xc1be,0xc1bf, + 0xc1c0,0xc1c1,0xc1c2,0xc1c3,0xc1c4,0xc1c5,0xc1c6,0xc1c7, + 0xc1c8,0xc1c9,0xc1ca,0xc1cb,0xc1cc,0xc1cd,0xc1ce,0xc1cf, + 0xc1d0,0xc1d1,0xc1d2,0xc1d3,0xc1d4,0xc1d5,0xc1d6,0xc1d7, + 0xc1d8,0xc1d9,0xc1da,0xc1db,0xc1dc,0xc1dd,0xc1de,0xc1df, + 0xc1e0,0xc1e1,0xc1e2,0xc1e3,0xc1e4,0xc1e5,0xc1e6,0xc1e7, + 0xc1e8,0xc1e9,0xc1ea,0xc1eb,0xc1ec,0xc1ed,0xc1ee,0xc1ef, + 0xc1f0,0xc1f1,0xc1f2,0xc1f3,0xc1f4,0xc1f5,0xc1f6,0xc1f7, + 0xc1f8,0xc1f9,0xc1fa,0xc1fb,0xc1fc,0xc1fd,0xc1fe,0xc1ff, + 0xc200,0xc201,0xc202,0xc203,0xc204,0xc205,0xc206,0xc207, + 0xc208,0xc209,0xc20a,0xc20b,0xc20c,0xc20d,0xc20e,0xc20f, + 0xc210,0xc211,0xc212,0xc213,0xc214,0xc215,0xc216,0xc217, + 0xc218,0xc219,0xc21a,0xc21b,0xc21c,0xc21d,0xc21e,0xc21f, + 0xc220,0xc221,0xc222,0xc223,0xc224,0xc225,0xc226,0xc227, + 0xc228,0xc229,0xc22a,0xc22b,0xc22c,0xc22d,0xc22e,0xc22f, + 0xc230,0xc231,0xc232,0xc233,0xc234,0xc235,0xc236,0xc237, + 0xc238,0xc239,0xc23a,0xc23b,0xc23c,0xc23d,0xc23e,0xc23f, + 0xc240,0xc241,0xc242,0xc243,0xc244,0xc245,0xc246,0xc247, + 0xc248,0xc249,0xc24a,0xc24b,0xc24c,0xc24d,0xc24e,0xc24f, + 0xc250,0xc251,0xc252,0xc253,0xc254,0xc255,0xc256,0xc257, + 0xc258,0xc259,0xc25a,0xc25b,0xc25c,0xc25d,0xc25e,0xc25f, + 0xc260,0xc261,0xc262,0xc263,0xc264,0xc265,0xc266,0xc267, + 0xc268,0xc269,0xc26a,0xc26b,0xc26c,0xc26d,0xc26e,0xc26f, + 0xc270,0xc271,0xc272,0xc273,0xc274,0xc275,0xc276,0xc277, + 0xc278,0xc279,0xc27a,0xc27b,0xc27c,0xc27d,0xc27e,0xc27f, + 0xc280,0xc281,0xc282,0xc283,0xc284,0xc285,0xc286,0xc287, + 0xc288,0xc289,0xc28a,0xc28b,0xc28c,0xc28d,0xc28e,0xc28f, + 0xc290,0xc291,0xc292,0xc293,0xc294,0xc295,0xc296,0xc297, + 0xc298,0xc299,0xc29a,0xc29b,0xc29c,0xc29d,0xc29e,0xc29f, + 0xc2a0,0xc2a1,0xc2a2,0xc2a3,0xc2a4,0xc2a5,0xc2a6,0xc2a7, + 0xc2a8,0xc2a9,0xc2aa,0xc2ab,0xc2ac,0xc2ad,0xc2ae,0xc2af, + 0xc2b0,0xc2b1,0xc2b2,0xc2b3,0xc2b4,0xc2b5,0xc2b6,0xc2b7, + 0xc2b8,0xc2b9,0xc2ba,0xc2bb,0xc2bc,0xc2bd,0xc2be,0xc2bf, + 0xc2c0,0xc2c1,0xc2c2,0xc2c3,0xc2c4,0xc2c5,0xc2c6,0xc2c7, + 0xc2c8,0xc2c9,0xc2ca,0xc2cb,0xc2cc,0xc2cd,0xc2ce,0xc2cf, + 0xc2d0,0xc2d1,0xc2d2,0xc2d3,0xc2d4,0xc2d5,0xc2d6,0xc2d7, + 0xc2d8,0xc2d9,0xc2da,0xc2db,0xc2dc,0xc2dd,0xc2de,0xc2df, + 0xc2e0,0xc2e1,0xc2e2,0xc2e3,0xc2e4,0xc2e5,0xc2e6,0xc2e7, + 0xc2e8,0xc2e9,0xc2ea,0xc2eb,0xc2ec,0xc2ed,0xc2ee,0xc2ef, + 0xc2f0,0xc2f1,0xc2f2,0xc2f3,0xc2f4,0xc2f5,0xc2f6,0xc2f7, + 0xc2f8,0xc2f9,0xc2fa,0xc2fb,0xc2fc,0xc2fd,0xc2fe,0xc2ff, + 0xc300,0xc301,0xc302,0xc303,0xc304,0xc305,0xc306,0xc307, + 0xc308,0xc309,0xc30a,0xc30b,0xc30c,0xc30d,0xc30e,0xc30f, + 0xc310,0xc311,0xc312,0xc313,0xc314,0xc315,0xc316,0xc317, + 0xc318,0xc319,0xc31a,0xc31b,0xc31c,0xc31d,0xc31e,0xc31f, + 0xc320,0xc321,0xc322,0xc323,0xc324,0xc325,0xc326,0xc327, + 0xc328,0xc329,0xc32a,0xc32b,0xc32c,0xc32d,0xc32e,0xc32f, + 0xc330,0xc331,0xc332,0xc333,0xc334,0xc335,0xc336,0xc337, + 0xc338,0xc339,0xc33a,0xc33b,0xc33c,0xc33d,0xc33e,0xc33f, + 0xc340,0xc341,0xc342,0xc343,0xc344,0xc345,0xc346,0xc347, + 0xc348,0xc349,0xc34a,0xc34b,0xc34c,0xc34d,0xc34e,0xc34f, + 0xc350,0xc351,0xc352,0xc353,0xc354,0xc355,0xc356,0xc357, + 0xc358,0xc359,0xc35a,0xc35b,0xc35c,0xc35d,0xc35e,0xc35f, + 0xc360,0xc361,0xc362,0xc363,0xc364,0xc365,0xc366,0xc367, + 0xc368,0xc369,0xc36a,0xc36b,0xc36c,0xc36d,0xc36e,0xc36f, + 0xc370,0xc371,0xc372,0xc373,0xc374,0xc375,0xc376,0xc377, + 0xc378,0xc379,0xc37a,0xc37b,0xc37c,0xc37d,0xc37e,0xc37f, + 0xc380,0xc381,0xc382,0xc383,0xc384,0xc385,0xc386,0xc387, + 0xc388,0xc389,0xc38a,0xc38b,0xc38c,0xc38d,0xc38e,0xc38f, + 0xc390,0xc391,0xc392,0xc393,0xc394,0xc395,0xc396,0xc397, + 0xc398,0xc399,0xc39a,0xc39b,0xc39c,0xc39d,0xc39e,0xc39f, + 0xc3a0,0xc3a1,0xc3a2,0xc3a3,0xc3a4,0xc3a5,0xc3a6,0xc3a7, + 0xc3a8,0xc3a9,0xc3aa,0xc3ab,0xc3ac,0xc3ad,0xc3ae,0xc3af, + 0xc3b0,0xc3b1,0xc3b2,0xc3b3,0xc3b4,0xc3b5,0xc3b6,0xc3b7, + 0xc3b8,0xc3b9,0xc3ba,0xc3bb,0xc3bc,0xc3bd,0xc3be,0xc3bf, + 0xc3c0,0xc3c1,0xc3c2,0xc3c3,0xc3c4,0xc3c5,0xc3c6,0xc3c7, + 0xc3c8,0xc3c9,0xc3ca,0xc3cb,0xc3cc,0xc3cd,0xc3ce,0xc3cf, + 0xc3d0,0xc3d1,0xc3d2,0xc3d3,0xc3d4,0xc3d5,0xc3d6,0xc3d7, + 0xc3d8,0xc3d9,0xc3da,0xc3db,0xc3dc,0xc3dd,0xc3de,0xc3df, + 0xc3e0,0xc3e1,0xc3e2,0xc3e3,0xc3e4,0xc3e5,0xc3e6,0xc3e7, + 0xc3e8,0xc3e9,0xc3ea,0xc3eb,0xc3ec,0xc3ed,0xc3ee,0xc3ef, + 0xc3f0,0xc3f1,0xc3f2,0xc3f3,0xc3f4,0xc3f5,0xc3f6,0xc3f7, + 0xc3f8,0xc3f9,0xc3fa,0xc3fb,0xc3fc,0xc3fd,0xc3fe,0xc3ff, + 0xc400,0xc401,0xc402,0xc403,0xc404,0xc405,0xc406,0xc407, + 0xc408,0xc409,0xc40a,0xc40b,0xc40c,0xc40d,0xc40e,0xc40f, + 0xc410,0xc411,0xc412,0xc413,0xc414,0xc415,0xc416,0xc417, + 0xc418,0xc419,0xc41a,0xc41b,0xc41c,0xc41d,0xc41e,0xc41f, + 0xc420,0xc421,0xc422,0xc423,0xc424,0xc425,0xc426,0xc427, + 0xc428,0xc429,0xc42a,0xc42b,0xc42c,0xc42d,0xc42e,0xc42f, + 0xc430,0xc431,0xc432,0xc433,0xc434,0xc435,0xc436,0xc437, + 0xc438,0xc439,0xc43a,0xc43b,0xc43c,0xc43d,0xc43e,0xc43f, + 0xc440,0xc441,0xc442,0xc443,0xc444,0xc445,0xc446,0xc447, + 0xc448,0xc449,0xc44a,0xc44b,0xc44c,0xc44d,0xc44e,0xc44f, + 0xc450,0xc451,0xc452,0xc453,0xc454,0xc455,0xc456,0xc457, + 0xc458,0xc459,0xc45a,0xc45b,0xc45c,0xc45d,0xc45e,0xc45f, + 0xc460,0xc461,0xc462,0xc463,0xc464,0xc465,0xc466,0xc467, + 0xc468,0xc469,0xc46a,0xc46b,0xc46c,0xc46d,0xc46e,0xc46f, + 0xc470,0xc471,0xc472,0xc473,0xc474,0xc475,0xc476,0xc477, + 0xc478,0xc479,0xc47a,0xc47b,0xc47c,0xc47d,0xc47e,0xc47f, + 0xc480,0xc481,0xc482,0xc483,0xc484,0xc485,0xc486,0xc487, + 0xc488,0xc489,0xc48a,0xc48b,0xc48c,0xc48d,0xc48e,0xc48f, + 0xc490,0xc491,0xc492,0xc493,0xc494,0xc495,0xc496,0xc497, + 0xc498,0xc499,0xc49a,0xc49b,0xc49c,0xc49d,0xc49e,0xc49f, + 0xc4a0,0xc4a1,0xc4a2,0xc4a3,0xc4a4,0xc4a5,0xc4a6,0xc4a7, + 0xc4a8,0xc4a9,0xc4aa,0xc4ab,0xc4ac,0xc4ad,0xc4ae,0xc4af, + 0xc4b0,0xc4b1,0xc4b2,0xc4b3,0xc4b4,0xc4b5,0xc4b6,0xc4b7, + 0xc4b8,0xc4b9,0xc4ba,0xc4bb,0xc4bc,0xc4bd,0xc4be,0xc4bf, + 0xc4c0,0xc4c1,0xc4c2,0xc4c3,0xc4c4,0xc4c5,0xc4c6,0xc4c7, + 0xc4c8,0xc4c9,0xc4ca,0xc4cb,0xc4cc,0xc4cd,0xc4ce,0xc4cf, + 0xc4d0,0xc4d1,0xc4d2,0xc4d3,0xc4d4,0xc4d5,0xc4d6,0xc4d7, + 0xc4d8,0xc4d9,0xc4da,0xc4db,0xc4dc,0xc4dd,0xc4de,0xc4df, + 0xc4e0,0xc4e1,0xc4e2,0xc4e3,0xc4e4,0xc4e5,0xc4e6,0xc4e7, + 0xc4e8,0xc4e9,0xc4ea,0xc4eb,0xc4ec,0xc4ed,0xc4ee,0xc4ef, + 0xc4f0,0xc4f1,0xc4f2,0xc4f3,0xc4f4,0xc4f5,0xc4f6,0xc4f7, + 0xc4f8,0xc4f9,0xc4fa,0xc4fb,0xc4fc,0xc4fd,0xc4fe,0xc4ff, + 0xc500,0xc501,0xc502,0xc503,0xc504,0xc505,0xc506,0xc507, + 0xc508,0xc509,0xc50a,0xc50b,0xc50c,0xc50d,0xc50e,0xc50f, + 0xc510,0xc511,0xc512,0xc513,0xc514,0xc515,0xc516,0xc517, + 0xc518,0xc519,0xc51a,0xc51b,0xc51c,0xc51d,0xc51e,0xc51f, + 0xc520,0xc521,0xc522,0xc523,0xc524,0xc525,0xc526,0xc527, + 0xc528,0xc529,0xc52a,0xc52b,0xc52c,0xc52d,0xc52e,0xc52f, + 0xc530,0xc531,0xc532,0xc533,0xc534,0xc535,0xc536,0xc537, + 0xc538,0xc539,0xc53a,0xc53b,0xc53c,0xc53d,0xc53e,0xc53f, + 0xc540,0xc541,0xc542,0xc543,0xc544,0xc545,0xc546,0xc547, + 0xc548,0xc549,0xc54a,0xc54b,0xc54c,0xc54d,0xc54e,0xc54f, + 0xc550,0xc551,0xc552,0xc553,0xc554,0xc555,0xc556,0xc557, + 0xc558,0xc559,0xc55a,0xc55b,0xc55c,0xc55d,0xc55e,0xc55f, + 0xc560,0xc561,0xc562,0xc563,0xc564,0xc565,0xc566,0xc567, + 0xc568,0xc569,0xc56a,0xc56b,0xc56c,0xc56d,0xc56e,0xc56f, + 0xc570,0xc571,0xc572,0xc573,0xc574,0xc575,0xc576,0xc577, + 0xc578,0xc579,0xc57a,0xc57b,0xc57c,0xc57d,0xc57e,0xc57f, + 0xc580,0xc581,0xc582,0xc583,0xc584,0xc585,0xc586,0xc587, + 0xc588,0xc589,0xc58a,0xc58b,0xc58c,0xc58d,0xc58e,0xc58f, + 0xc590,0xc591,0xc592,0xc593,0xc594,0xc595,0xc596,0xc597, + 0xc598,0xc599,0xc59a,0xc59b,0xc59c,0xc59d,0xc59e,0xc59f, + 0xc5a0,0xc5a1,0xc5a2,0xc5a3,0xc5a4,0xc5a5,0xc5a6,0xc5a7, + 0xc5a8,0xc5a9,0xc5aa,0xc5ab,0xc5ac,0xc5ad,0xc5ae,0xc5af, + 0xc5b0,0xc5b1,0xc5b2,0xc5b3,0xc5b4,0xc5b5,0xc5b6,0xc5b7, + 0xc5b8,0xc5b9,0xc5ba,0xc5bb,0xc5bc,0xc5bd,0xc5be,0xc5bf, + 0xc5c0,0xc5c1,0xc5c2,0xc5c3,0xc5c4,0xc5c5,0xc5c6,0xc5c7, + 0xc5c8,0xc5c9,0xc5ca,0xc5cb,0xc5cc,0xc5cd,0xc5ce,0xc5cf, + 0xc5d0,0xc5d1,0xc5d2,0xc5d3,0xc5d4,0xc5d5,0xc5d6,0xc5d7, + 0xc5d8,0xc5d9,0xc5da,0xc5db,0xc5dc,0xc5dd,0xc5de,0xc5df, + 0xc5e0,0xc5e1,0xc5e2,0xc5e3,0xc5e4,0xc5e5,0xc5e6,0xc5e7, + 0xc5e8,0xc5e9,0xc5ea,0xc5eb,0xc5ec,0xc5ed,0xc5ee,0xc5ef, + 0xc5f0,0xc5f1,0xc5f2,0xc5f3,0xc5f4,0xc5f5,0xc5f6,0xc5f7, + 0xc5f8,0xc5f9,0xc5fa,0xc5fb,0xc5fc,0xc5fd,0xc5fe,0xc5ff, + 0xc600,0xc601,0xc602,0xc603,0xc604,0xc605,0xc606,0xc607, + 0xc608,0xc609,0xc60a,0xc60b,0xc60c,0xc60d,0xc60e,0xc60f, + 0xc610,0xc611,0xc612,0xc613,0xc614,0xc615,0xc616,0xc617, + 0xc618,0xc619,0xc61a,0xc61b,0xc61c,0xc61d,0xc61e,0xc61f, + 0xc620,0xc621,0xc622,0xc623,0xc624,0xc625,0xc626,0xc627, + 0xc628,0xc629,0xc62a,0xc62b,0xc62c,0xc62d,0xc62e,0xc62f, + 0xc630,0xc631,0xc632,0xc633,0xc634,0xc635,0xc636,0xc637, + 0xc638,0xc639,0xc63a,0xc63b,0xc63c,0xc63d,0xc63e,0xc63f, + 0xc640,0xc641,0xc642,0xc643,0xc644,0xc645,0xc646,0xc647, + 0xc648,0xc649,0xc64a,0xc64b,0xc64c,0xc64d,0xc64e,0xc64f, + 0xc650,0xc651,0xc652,0xc653,0xc654,0xc655,0xc656,0xc657, + 0xc658,0xc659,0xc65a,0xc65b,0xc65c,0xc65d,0xc65e,0xc65f, + 0xc660,0xc661,0xc662,0xc663,0xc664,0xc665,0xc666,0xc667, + 0xc668,0xc669,0xc66a,0xc66b,0xc66c,0xc66d,0xc66e,0xc66f, + 0xc670,0xc671,0xc672,0xc673,0xc674,0xc675,0xc676,0xc677, + 0xc678,0xc679,0xc67a,0xc67b,0xc67c,0xc67d,0xc67e,0xc67f, + 0xc680,0xc681,0xc682,0xc683,0xc684,0xc685,0xc686,0xc687, + 0xc688,0xc689,0xc68a,0xc68b,0xc68c,0xc68d,0xc68e,0xc68f, + 0xc690,0xc691,0xc692,0xc693,0xc694,0xc695,0xc696,0xc697, + 0xc698,0xc699,0xc69a,0xc69b,0xc69c,0xc69d,0xc69e,0xc69f, + 0xc6a0,0xc6a1,0xc6a2,0xc6a3,0xc6a4,0xc6a5,0xc6a6,0xc6a7, + 0xc6a8,0xc6a9,0xc6aa,0xc6ab,0xc6ac,0xc6ad,0xc6ae,0xc6af, + 0xc6b0,0xc6b1,0xc6b2,0xc6b3,0xc6b4,0xc6b5,0xc6b6,0xc6b7, + 0xc6b8,0xc6b9,0xc6ba,0xc6bb,0xc6bc,0xc6bd,0xc6be,0xc6bf, + 0xc6c0,0xc6c1,0xc6c2,0xc6c3,0xc6c4,0xc6c5,0xc6c6,0xc6c7, + 0xc6c8,0xc6c9,0xc6ca,0xc6cb,0xc6cc,0xc6cd,0xc6ce,0xc6cf, + 0xc6d0,0xc6d1,0xc6d2,0xc6d3,0xc6d4,0xc6d5,0xc6d6,0xc6d7, + 0xc6d8,0xc6d9,0xc6da,0xc6db,0xc6dc,0xc6dd,0xc6de,0xc6df, + 0xc6e0,0xc6e1,0xc6e2,0xc6e3,0xc6e4,0xc6e5,0xc6e6,0xc6e7, + 0xc6e8,0xc6e9,0xc6ea,0xc6eb,0xc6ec,0xc6ed,0xc6ee,0xc6ef, + 0xc6f0,0xc6f1,0xc6f2,0xc6f3,0xc6f4,0xc6f5,0xc6f6,0xc6f7, + 0xc6f8,0xc6f9,0xc6fa,0xc6fb,0xc6fc,0xc6fd,0xc6fe,0xc6ff, + 0xc700,0xc701,0xc702,0xc703,0xc704,0xc705,0xc706,0xc707, + 0xc708,0xc709,0xc70a,0xc70b,0xc70c,0xc70d,0xc70e,0xc70f, + 0xc710,0xc711,0xc712,0xc713,0xc714,0xc715,0xc716,0xc717, + 0xc718,0xc719,0xc71a,0xc71b,0xc71c,0xc71d,0xc71e,0xc71f, + 0xc720,0xc721,0xc722,0xc723,0xc724,0xc725,0xc726,0xc727, + 0xc728,0xc729,0xc72a,0xc72b,0xc72c,0xc72d,0xc72e,0xc72f, + 0xc730,0xc731,0xc732,0xc733,0xc734,0xc735,0xc736,0xc737, + 0xc738,0xc739,0xc73a,0xc73b,0xc73c,0xc73d,0xc73e,0xc73f, + 0xc740,0xc741,0xc742,0xc743,0xc744,0xc745,0xc746,0xc747, + 0xc748,0xc749,0xc74a,0xc74b,0xc74c,0xc74d,0xc74e,0xc74f, + 0xc750,0xc751,0xc752,0xc753,0xc754,0xc755,0xc756,0xc757, + 0xc758,0xc759,0xc75a,0xc75b,0xc75c,0xc75d,0xc75e,0xc75f, + 0xc760,0xc761,0xc762,0xc763,0xc764,0xc765,0xc766,0xc767, + 0xc768,0xc769,0xc76a,0xc76b,0xc76c,0xc76d,0xc76e,0xc76f, + 0xc770,0xc771,0xc772,0xc773,0xc774,0xc775,0xc776,0xc777, + 0xc778,0xc779,0xc77a,0xc77b,0xc77c,0xc77d,0xc77e,0xc77f, + 0xc780,0xc781,0xc782,0xc783,0xc784,0xc785,0xc786,0xc787, + 0xc788,0xc789,0xc78a,0xc78b,0xc78c,0xc78d,0xc78e,0xc78f, + 0xc790,0xc791,0xc792,0xc793,0xc794,0xc795,0xc796,0xc797, + 0xc798,0xc799,0xc79a,0xc79b,0xc79c,0xc79d,0xc79e,0xc79f, + 0xc7a0,0xc7a1,0xc7a2,0xc7a3,0xc7a4,0xc7a5,0xc7a6,0xc7a7, + 0xc7a8,0xc7a9,0xc7aa,0xc7ab,0xc7ac,0xc7ad,0xc7ae,0xc7af, + 0xc7b0,0xc7b1,0xc7b2,0xc7b3,0xc7b4,0xc7b5,0xc7b6,0xc7b7, + 0xc7b8,0xc7b9,0xc7ba,0xc7bb,0xc7bc,0xc7bd,0xc7be,0xc7bf, + 0xc7c0,0xc7c1,0xc7c2,0xc7c3,0xc7c4,0xc7c5,0xc7c6,0xc7c7, + 0xc7c8,0xc7c9,0xc7ca,0xc7cb,0xc7cc,0xc7cd,0xc7ce,0xc7cf, + 0xc7d0,0xc7d1,0xc7d2,0xc7d3,0xc7d4,0xc7d5,0xc7d6,0xc7d7, + 0xc7d8,0xc7d9,0xc7da,0xc7db,0xc7dc,0xc7dd,0xc7de,0xc7df, + 0xc7e0,0xc7e1,0xc7e2,0xc7e3,0xc7e4,0xc7e5,0xc7e6,0xc7e7, + 0xc7e8,0xc7e9,0xc7ea,0xc7eb,0xc7ec,0xc7ed,0xc7ee,0xc7ef, + 0xc7f0,0xc7f1,0xc7f2,0xc7f3,0xc7f4,0xc7f5,0xc7f6,0xc7f7, + 0xc7f8,0xc7f9,0xc7fa,0xc7fb,0xc7fc,0xc7fd,0xc7fe,0xc7ff, + 0xc800,0xc801,0xc802,0xc803,0xc804,0xc805,0xc806,0xc807, + 0xc808,0xc809,0xc80a,0xc80b,0xc80c,0xc80d,0xc80e,0xc80f, + 0xc810,0xc811,0xc812,0xc813,0xc814,0xc815,0xc816,0xc817, + 0xc818,0xc819,0xc81a,0xc81b,0xc81c,0xc81d,0xc81e,0xc81f, + 0xc820,0xc821,0xc822,0xc823,0xc824,0xc825,0xc826,0xc827, + 0xc828,0xc829,0xc82a,0xc82b,0xc82c,0xc82d,0xc82e,0xc82f, + 0xc830,0xc831,0xc832,0xc833,0xc834,0xc835,0xc836,0xc837, + 0xc838,0xc839,0xc83a,0xc83b,0xc83c,0xc83d,0xc83e,0xc83f, + 0xc840,0xc841,0xc842,0xc843,0xc844,0xc845,0xc846,0xc847, + 0xc848,0xc849,0xc84a,0xc84b,0xc84c,0xc84d,0xc84e,0xc84f, + 0xc850,0xc851,0xc852,0xc853,0xc854,0xc855,0xc856,0xc857, + 0xc858,0xc859,0xc85a,0xc85b,0xc85c,0xc85d,0xc85e,0xc85f, + 0xc860,0xc861,0xc862,0xc863,0xc864,0xc865,0xc866,0xc867, + 0xc868,0xc869,0xc86a,0xc86b,0xc86c,0xc86d,0xc86e,0xc86f, + 0xc870,0xc871,0xc872,0xc873,0xc874,0xc875,0xc876,0xc877, + 0xc878,0xc879,0xc87a,0xc87b,0xc87c,0xc87d,0xc87e,0xc87f, + 0xc880,0xc881,0xc882,0xc883,0xc884,0xc885,0xc886,0xc887, + 0xc888,0xc889,0xc88a,0xc88b,0xc88c,0xc88d,0xc88e,0xc88f, + 0xc890,0xc891,0xc892,0xc893,0xc894,0xc895,0xc896,0xc897, + 0xc898,0xc899,0xc89a,0xc89b,0xc89c,0xc89d,0xc89e,0xc89f, + 0xc8a0,0xc8a1,0xc8a2,0xc8a3,0xc8a4,0xc8a5,0xc8a6,0xc8a7, + 0xc8a8,0xc8a9,0xc8aa,0xc8ab,0xc8ac,0xc8ad,0xc8ae,0xc8af, + 0xc8b0,0xc8b1,0xc8b2,0xc8b3,0xc8b4,0xc8b5,0xc8b6,0xc8b7, + 0xc8b8,0xc8b9,0xc8ba,0xc8bb,0xc8bc,0xc8bd,0xc8be,0xc8bf, + 0xc8c0,0xc8c1,0xc8c2,0xc8c3,0xc8c4,0xc8c5,0xc8c6,0xc8c7, + 0xc8c8,0xc8c9,0xc8ca,0xc8cb,0xc8cc,0xc8cd,0xc8ce,0xc8cf, + 0xc8d0,0xc8d1,0xc8d2,0xc8d3,0xc8d4,0xc8d5,0xc8d6,0xc8d7, + 0xc8d8,0xc8d9,0xc8da,0xc8db,0xc8dc,0xc8dd,0xc8de,0xc8df, + 0xc8e0,0xc8e1,0xc8e2,0xc8e3,0xc8e4,0xc8e5,0xc8e6,0xc8e7, + 0xc8e8,0xc8e9,0xc8ea,0xc8eb,0xc8ec,0xc8ed,0xc8ee,0xc8ef, + 0xc8f0,0xc8f1,0xc8f2,0xc8f3,0xc8f4,0xc8f5,0xc8f6,0xc8f7, + 0xc8f8,0xc8f9,0xc8fa,0xc8fb,0xc8fc,0xc8fd,0xc8fe,0xc8ff, + 0xc900,0xc901,0xc902,0xc903,0xc904,0xc905,0xc906,0xc907, + 0xc908,0xc909,0xc90a,0xc90b,0xc90c,0xc90d,0xc90e,0xc90f, + 0xc910,0xc911,0xc912,0xc913,0xc914,0xc915,0xc916,0xc917, + 0xc918,0xc919,0xc91a,0xc91b,0xc91c,0xc91d,0xc91e,0xc91f, + 0xc920,0xc921,0xc922,0xc923,0xc924,0xc925,0xc926,0xc927, + 0xc928,0xc929,0xc92a,0xc92b,0xc92c,0xc92d,0xc92e,0xc92f, + 0xc930,0xc931,0xc932,0xc933,0xc934,0xc935,0xc936,0xc937, + 0xc938,0xc939,0xc93a,0xc93b,0xc93c,0xc93d,0xc93e,0xc93f, + 0xc940,0xc941,0xc942,0xc943,0xc944,0xc945,0xc946,0xc947, + 0xc948,0xc949,0xc94a,0xc94b,0xc94c,0xc94d,0xc94e,0xc94f, + 0xc950,0xc951,0xc952,0xc953,0xc954,0xc955,0xc956,0xc957, + 0xc958,0xc959,0xc95a,0xc95b,0xc95c,0xc95d,0xc95e,0xc95f, + 0xc960,0xc961,0xc962,0xc963,0xc964,0xc965,0xc966,0xc967, + 0xc968,0xc969,0xc96a,0xc96b,0xc96c,0xc96d,0xc96e,0xc96f, + 0xc970,0xc971,0xc972,0xc973,0xc974,0xc975,0xc976,0xc977, + 0xc978,0xc979,0xc97a,0xc97b,0xc97c,0xc97d,0xc97e,0xc97f, + 0xc980,0xc981,0xc982,0xc983,0xc984,0xc985,0xc986,0xc987, + 0xc988,0xc989,0xc98a,0xc98b,0xc98c,0xc98d,0xc98e,0xc98f, + 0xc990,0xc991,0xc992,0xc993,0xc994,0xc995,0xc996,0xc997, + 0xc998,0xc999,0xc99a,0xc99b,0xc99c,0xc99d,0xc99e,0xc99f, + 0xc9a0,0xc9a1,0xc9a2,0xc9a3,0xc9a4,0xc9a5,0xc9a6,0xc9a7, + 0xc9a8,0xc9a9,0xc9aa,0xc9ab,0xc9ac,0xc9ad,0xc9ae,0xc9af, + 0xc9b0,0xc9b1,0xc9b2,0xc9b3,0xc9b4,0xc9b5,0xc9b6,0xc9b7, + 0xc9b8,0xc9b9,0xc9ba,0xc9bb,0xc9bc,0xc9bd,0xc9be,0xc9bf, + 0xc9c0,0xc9c1,0xc9c2,0xc9c3,0xc9c4,0xc9c5,0xc9c6,0xc9c7, + 0xc9c8,0xc9c9,0xc9ca,0xc9cb,0xc9cc,0xc9cd,0xc9ce,0xc9cf, + 0xc9d0,0xc9d1,0xc9d2,0xc9d3,0xc9d4,0xc9d5,0xc9d6,0xc9d7, + 0xc9d8,0xc9d9,0xc9da,0xc9db,0xc9dc,0xc9dd,0xc9de,0xc9df, + 0xc9e0,0xc9e1,0xc9e2,0xc9e3,0xc9e4,0xc9e5,0xc9e6,0xc9e7, + 0xc9e8,0xc9e9,0xc9ea,0xc9eb,0xc9ec,0xc9ed,0xc9ee,0xc9ef, + 0xc9f0,0xc9f1,0xc9f2,0xc9f3,0xc9f4,0xc9f5,0xc9f6,0xc9f7, + 0xc9f8,0xc9f9,0xc9fa,0xc9fb,0xc9fc,0xc9fd,0xc9fe,0xc9ff, + 0xca00,0xca01,0xca02,0xca03,0xca04,0xca05,0xca06,0xca07, + 0xca08,0xca09,0xca0a,0xca0b,0xca0c,0xca0d,0xca0e,0xca0f, + 0xca10,0xca11,0xca12,0xca13,0xca14,0xca15,0xca16,0xca17, + 0xca18,0xca19,0xca1a,0xca1b,0xca1c,0xca1d,0xca1e,0xca1f, + 0xca20,0xca21,0xca22,0xca23,0xca24,0xca25,0xca26,0xca27, + 0xca28,0xca29,0xca2a,0xca2b,0xca2c,0xca2d,0xca2e,0xca2f, + 0xca30,0xca31,0xca32,0xca33,0xca34,0xca35,0xca36,0xca37, + 0xca38,0xca39,0xca3a,0xca3b,0xca3c,0xca3d,0xca3e,0xca3f, + 0xca40,0xca41,0xca42,0xca43,0xca44,0xca45,0xca46,0xca47, + 0xca48,0xca49,0xca4a,0xca4b,0xca4c,0xca4d,0xca4e,0xca4f, + 0xca50,0xca51,0xca52,0xca53,0xca54,0xca55,0xca56,0xca57, + 0xca58,0xca59,0xca5a,0xca5b,0xca5c,0xca5d,0xca5e,0xca5f, + 0xca60,0xca61,0xca62,0xca63,0xca64,0xca65,0xca66,0xca67, + 0xca68,0xca69,0xca6a,0xca6b,0xca6c,0xca6d,0xca6e,0xca6f, + 0xca70,0xca71,0xca72,0xca73,0xca74,0xca75,0xca76,0xca77, + 0xca78,0xca79,0xca7a,0xca7b,0xca7c,0xca7d,0xca7e,0xca7f, + 0xca80,0xca81,0xca82,0xca83,0xca84,0xca85,0xca86,0xca87, + 0xca88,0xca89,0xca8a,0xca8b,0xca8c,0xca8d,0xca8e,0xca8f, + 0xca90,0xca91,0xca92,0xca93,0xca94,0xca95,0xca96,0xca97, + 0xca98,0xca99,0xca9a,0xca9b,0xca9c,0xca9d,0xca9e,0xca9f, + 0xcaa0,0xcaa1,0xcaa2,0xcaa3,0xcaa4,0xcaa5,0xcaa6,0xcaa7, + 0xcaa8,0xcaa9,0xcaaa,0xcaab,0xcaac,0xcaad,0xcaae,0xcaaf, + 0xcab0,0xcab1,0xcab2,0xcab3,0xcab4,0xcab5,0xcab6,0xcab7, + 0xcab8,0xcab9,0xcaba,0xcabb,0xcabc,0xcabd,0xcabe,0xcabf, + 0xcac0,0xcac1,0xcac2,0xcac3,0xcac4,0xcac5,0xcac6,0xcac7, + 0xcac8,0xcac9,0xcaca,0xcacb,0xcacc,0xcacd,0xcace,0xcacf, + 0xcad0,0xcad1,0xcad2,0xcad3,0xcad4,0xcad5,0xcad6,0xcad7, + 0xcad8,0xcad9,0xcada,0xcadb,0xcadc,0xcadd,0xcade,0xcadf, + 0xcae0,0xcae1,0xcae2,0xcae3,0xcae4,0xcae5,0xcae6,0xcae7, + 0xcae8,0xcae9,0xcaea,0xcaeb,0xcaec,0xcaed,0xcaee,0xcaef, + 0xcaf0,0xcaf1,0xcaf2,0xcaf3,0xcaf4,0xcaf5,0xcaf6,0xcaf7, + 0xcaf8,0xcaf9,0xcafa,0xcafb,0xcafc,0xcafd,0xcafe,0xcaff, + 0xcb00,0xcb01,0xcb02,0xcb03,0xcb04,0xcb05,0xcb06,0xcb07, + 0xcb08,0xcb09,0xcb0a,0xcb0b,0xcb0c,0xcb0d,0xcb0e,0xcb0f, + 0xcb10,0xcb11,0xcb12,0xcb13,0xcb14,0xcb15,0xcb16,0xcb17, + 0xcb18,0xcb19,0xcb1a,0xcb1b,0xcb1c,0xcb1d,0xcb1e,0xcb1f, + 0xcb20,0xcb21,0xcb22,0xcb23,0xcb24,0xcb25,0xcb26,0xcb27, + 0xcb28,0xcb29,0xcb2a,0xcb2b,0xcb2c,0xcb2d,0xcb2e,0xcb2f, + 0xcb30,0xcb31,0xcb32,0xcb33,0xcb34,0xcb35,0xcb36,0xcb37, + 0xcb38,0xcb39,0xcb3a,0xcb3b,0xcb3c,0xcb3d,0xcb3e,0xcb3f, + 0xcb40,0xcb41,0xcb42,0xcb43,0xcb44,0xcb45,0xcb46,0xcb47, + 0xcb48,0xcb49,0xcb4a,0xcb4b,0xcb4c,0xcb4d,0xcb4e,0xcb4f, + 0xcb50,0xcb51,0xcb52,0xcb53,0xcb54,0xcb55,0xcb56,0xcb57, + 0xcb58,0xcb59,0xcb5a,0xcb5b,0xcb5c,0xcb5d,0xcb5e,0xcb5f, + 0xcb60,0xcb61,0xcb62,0xcb63,0xcb64,0xcb65,0xcb66,0xcb67, + 0xcb68,0xcb69,0xcb6a,0xcb6b,0xcb6c,0xcb6d,0xcb6e,0xcb6f, + 0xcb70,0xcb71,0xcb72,0xcb73,0xcb74,0xcb75,0xcb76,0xcb77, + 0xcb78,0xcb79,0xcb7a,0xcb7b,0xcb7c,0xcb7d,0xcb7e,0xcb7f, + 0xcb80,0xcb81,0xcb82,0xcb83,0xcb84,0xcb85,0xcb86,0xcb87, + 0xcb88,0xcb89,0xcb8a,0xcb8b,0xcb8c,0xcb8d,0xcb8e,0xcb8f, + 0xcb90,0xcb91,0xcb92,0xcb93,0xcb94,0xcb95,0xcb96,0xcb97, + 0xcb98,0xcb99,0xcb9a,0xcb9b,0xcb9c,0xcb9d,0xcb9e,0xcb9f, + 0xcba0,0xcba1,0xcba2,0xcba3,0xcba4,0xcba5,0xcba6,0xcba7, + 0xcba8,0xcba9,0xcbaa,0xcbab,0xcbac,0xcbad,0xcbae,0xcbaf, + 0xcbb0,0xcbb1,0xcbb2,0xcbb3,0xcbb4,0xcbb5,0xcbb6,0xcbb7, + 0xcbb8,0xcbb9,0xcbba,0xcbbb,0xcbbc,0xcbbd,0xcbbe,0xcbbf, + 0xcbc0,0xcbc1,0xcbc2,0xcbc3,0xcbc4,0xcbc5,0xcbc6,0xcbc7, + 0xcbc8,0xcbc9,0xcbca,0xcbcb,0xcbcc,0xcbcd,0xcbce,0xcbcf, + 0xcbd0,0xcbd1,0xcbd2,0xcbd3,0xcbd4,0xcbd5,0xcbd6,0xcbd7, + 0xcbd8,0xcbd9,0xcbda,0xcbdb,0xcbdc,0xcbdd,0xcbde,0xcbdf, + 0xcbe0,0xcbe1,0xcbe2,0xcbe3,0xcbe4,0xcbe5,0xcbe6,0xcbe7, + 0xcbe8,0xcbe9,0xcbea,0xcbeb,0xcbec,0xcbed,0xcbee,0xcbef, + 0xcbf0,0xcbf1,0xcbf2,0xcbf3,0xcbf4,0xcbf5,0xcbf6,0xcbf7, + 0xcbf8,0xcbf9,0xcbfa,0xcbfb,0xcbfc,0xcbfd,0xcbfe,0xcbff, + 0xcc00,0xcc01,0xcc02,0xcc03,0xcc04,0xcc05,0xcc06,0xcc07, + 0xcc08,0xcc09,0xcc0a,0xcc0b,0xcc0c,0xcc0d,0xcc0e,0xcc0f, + 0xcc10,0xcc11,0xcc12,0xcc13,0xcc14,0xcc15,0xcc16,0xcc17, + 0xcc18,0xcc19,0xcc1a,0xcc1b,0xcc1c,0xcc1d,0xcc1e,0xcc1f, + 0xcc20,0xcc21,0xcc22,0xcc23,0xcc24,0xcc25,0xcc26,0xcc27, + 0xcc28,0xcc29,0xcc2a,0xcc2b,0xcc2c,0xcc2d,0xcc2e,0xcc2f, + 0xcc30,0xcc31,0xcc32,0xcc33,0xcc34,0xcc35,0xcc36,0xcc37, + 0xcc38,0xcc39,0xcc3a,0xcc3b,0xcc3c,0xcc3d,0xcc3e,0xcc3f, + 0xcc40,0xcc41,0xcc42,0xcc43,0xcc44,0xcc45,0xcc46,0xcc47, + 0xcc48,0xcc49,0xcc4a,0xcc4b,0xcc4c,0xcc4d,0xcc4e,0xcc4f, + 0xcc50,0xcc51,0xcc52,0xcc53,0xcc54,0xcc55,0xcc56,0xcc57, + 0xcc58,0xcc59,0xcc5a,0xcc5b,0xcc5c,0xcc5d,0xcc5e,0xcc5f, + 0xcc60,0xcc61,0xcc62,0xcc63,0xcc64,0xcc65,0xcc66,0xcc67, + 0xcc68,0xcc69,0xcc6a,0xcc6b,0xcc6c,0xcc6d,0xcc6e,0xcc6f, + 0xcc70,0xcc71,0xcc72,0xcc73,0xcc74,0xcc75,0xcc76,0xcc77, + 0xcc78,0xcc79,0xcc7a,0xcc7b,0xcc7c,0xcc7d,0xcc7e,0xcc7f, + 0xcc80,0xcc81,0xcc82,0xcc83,0xcc84,0xcc85,0xcc86,0xcc87, + 0xcc88,0xcc89,0xcc8a,0xcc8b,0xcc8c,0xcc8d,0xcc8e,0xcc8f, + 0xcc90,0xcc91,0xcc92,0xcc93,0xcc94,0xcc95,0xcc96,0xcc97, + 0xcc98,0xcc99,0xcc9a,0xcc9b,0xcc9c,0xcc9d,0xcc9e,0xcc9f, + 0xcca0,0xcca1,0xcca2,0xcca3,0xcca4,0xcca5,0xcca6,0xcca7, + 0xcca8,0xcca9,0xccaa,0xccab,0xccac,0xccad,0xccae,0xccaf, + 0xccb0,0xccb1,0xccb2,0xccb3,0xccb4,0xccb5,0xccb6,0xccb7, + 0xccb8,0xccb9,0xccba,0xccbb,0xccbc,0xccbd,0xccbe,0xccbf, + 0xccc0,0xccc1,0xccc2,0xccc3,0xccc4,0xccc5,0xccc6,0xccc7, + 0xccc8,0xccc9,0xccca,0xcccb,0xcccc,0xcccd,0xccce,0xcccf, + 0xccd0,0xccd1,0xccd2,0xccd3,0xccd4,0xccd5,0xccd6,0xccd7, + 0xccd8,0xccd9,0xccda,0xccdb,0xccdc,0xccdd,0xccde,0xccdf, + 0xcce0,0xcce1,0xcce2,0xcce3,0xcce4,0xcce5,0xcce6,0xcce7, + 0xcce8,0xcce9,0xccea,0xcceb,0xccec,0xcced,0xccee,0xccef, + 0xccf0,0xccf1,0xccf2,0xccf3,0xccf4,0xccf5,0xccf6,0xccf7, + 0xccf8,0xccf9,0xccfa,0xccfb,0xccfc,0xccfd,0xccfe,0xccff, + 0xcd00,0xcd01,0xcd02,0xcd03,0xcd04,0xcd05,0xcd06,0xcd07, + 0xcd08,0xcd09,0xcd0a,0xcd0b,0xcd0c,0xcd0d,0xcd0e,0xcd0f, + 0xcd10,0xcd11,0xcd12,0xcd13,0xcd14,0xcd15,0xcd16,0xcd17, + 0xcd18,0xcd19,0xcd1a,0xcd1b,0xcd1c,0xcd1d,0xcd1e,0xcd1f, + 0xcd20,0xcd21,0xcd22,0xcd23,0xcd24,0xcd25,0xcd26,0xcd27, + 0xcd28,0xcd29,0xcd2a,0xcd2b,0xcd2c,0xcd2d,0xcd2e,0xcd2f, + 0xcd30,0xcd31,0xcd32,0xcd33,0xcd34,0xcd35,0xcd36,0xcd37, + 0xcd38,0xcd39,0xcd3a,0xcd3b,0xcd3c,0xcd3d,0xcd3e,0xcd3f, + 0xcd40,0xcd41,0xcd42,0xcd43,0xcd44,0xcd45,0xcd46,0xcd47, + 0xcd48,0xcd49,0xcd4a,0xcd4b,0xcd4c,0xcd4d,0xcd4e,0xcd4f, + 0xcd50,0xcd51,0xcd52,0xcd53,0xcd54,0xcd55,0xcd56,0xcd57, + 0xcd58,0xcd59,0xcd5a,0xcd5b,0xcd5c,0xcd5d,0xcd5e,0xcd5f, + 0xcd60,0xcd61,0xcd62,0xcd63,0xcd64,0xcd65,0xcd66,0xcd67, + 0xcd68,0xcd69,0xcd6a,0xcd6b,0xcd6c,0xcd6d,0xcd6e,0xcd6f, + 0xcd70,0xcd71,0xcd72,0xcd73,0xcd74,0xcd75,0xcd76,0xcd77, + 0xcd78,0xcd79,0xcd7a,0xcd7b,0xcd7c,0xcd7d,0xcd7e,0xcd7f, + 0xcd80,0xcd81,0xcd82,0xcd83,0xcd84,0xcd85,0xcd86,0xcd87, + 0xcd88,0xcd89,0xcd8a,0xcd8b,0xcd8c,0xcd8d,0xcd8e,0xcd8f, + 0xcd90,0xcd91,0xcd92,0xcd93,0xcd94,0xcd95,0xcd96,0xcd97, + 0xcd98,0xcd99,0xcd9a,0xcd9b,0xcd9c,0xcd9d,0xcd9e,0xcd9f, + 0xcda0,0xcda1,0xcda2,0xcda3,0xcda4,0xcda5,0xcda6,0xcda7, + 0xcda8,0xcda9,0xcdaa,0xcdab,0xcdac,0xcdad,0xcdae,0xcdaf, + 0xcdb0,0xcdb1,0xcdb2,0xcdb3,0xcdb4,0xcdb5,0xcdb6,0xcdb7, + 0xcdb8,0xcdb9,0xcdba,0xcdbb,0xcdbc,0xcdbd,0xcdbe,0xcdbf, + 0xcdc0,0xcdc1,0xcdc2,0xcdc3,0xcdc4,0xcdc5,0xcdc6,0xcdc7, + 0xcdc8,0xcdc9,0xcdca,0xcdcb,0xcdcc,0xcdcd,0xcdce,0xcdcf, + 0xcdd0,0xcdd1,0xcdd2,0xcdd3,0xcdd4,0xcdd5,0xcdd6,0xcdd7, + 0xcdd8,0xcdd9,0xcdda,0xcddb,0xcddc,0xcddd,0xcdde,0xcddf, + 0xcde0,0xcde1,0xcde2,0xcde3,0xcde4,0xcde5,0xcde6,0xcde7, + 0xcde8,0xcde9,0xcdea,0xcdeb,0xcdec,0xcded,0xcdee,0xcdef, + 0xcdf0,0xcdf1,0xcdf2,0xcdf3,0xcdf4,0xcdf5,0xcdf6,0xcdf7, + 0xcdf8,0xcdf9,0xcdfa,0xcdfb,0xcdfc,0xcdfd,0xcdfe,0xcdff, + 0xce00,0xce01,0xce02,0xce03,0xce04,0xce05,0xce06,0xce07, + 0xce08,0xce09,0xce0a,0xce0b,0xce0c,0xce0d,0xce0e,0xce0f, + 0xce10,0xce11,0xce12,0xce13,0xce14,0xce15,0xce16,0xce17, + 0xce18,0xce19,0xce1a,0xce1b,0xce1c,0xce1d,0xce1e,0xce1f, + 0xce20,0xce21,0xce22,0xce23,0xce24,0xce25,0xce26,0xce27, + 0xce28,0xce29,0xce2a,0xce2b,0xce2c,0xce2d,0xce2e,0xce2f, + 0xce30,0xce31,0xce32,0xce33,0xce34,0xce35,0xce36,0xce37, + 0xce38,0xce39,0xce3a,0xce3b,0xce3c,0xce3d,0xce3e,0xce3f, + 0xce40,0xce41,0xce42,0xce43,0xce44,0xce45,0xce46,0xce47, + 0xce48,0xce49,0xce4a,0xce4b,0xce4c,0xce4d,0xce4e,0xce4f, + 0xce50,0xce51,0xce52,0xce53,0xce54,0xce55,0xce56,0xce57, + 0xce58,0xce59,0xce5a,0xce5b,0xce5c,0xce5d,0xce5e,0xce5f, + 0xce60,0xce61,0xce62,0xce63,0xce64,0xce65,0xce66,0xce67, + 0xce68,0xce69,0xce6a,0xce6b,0xce6c,0xce6d,0xce6e,0xce6f, + 0xce70,0xce71,0xce72,0xce73,0xce74,0xce75,0xce76,0xce77, + 0xce78,0xce79,0xce7a,0xce7b,0xce7c,0xce7d,0xce7e,0xce7f, + 0xce80,0xce81,0xce82,0xce83,0xce84,0xce85,0xce86,0xce87, + 0xce88,0xce89,0xce8a,0xce8b,0xce8c,0xce8d,0xce8e,0xce8f, + 0xce90,0xce91,0xce92,0xce93,0xce94,0xce95,0xce96,0xce97, + 0xce98,0xce99,0xce9a,0xce9b,0xce9c,0xce9d,0xce9e,0xce9f, + 0xcea0,0xcea1,0xcea2,0xcea3,0xcea4,0xcea5,0xcea6,0xcea7, + 0xcea8,0xcea9,0xceaa,0xceab,0xceac,0xcead,0xceae,0xceaf, + 0xceb0,0xceb1,0xceb2,0xceb3,0xceb4,0xceb5,0xceb6,0xceb7, + 0xceb8,0xceb9,0xceba,0xcebb,0xcebc,0xcebd,0xcebe,0xcebf, + 0xcec0,0xcec1,0xcec2,0xcec3,0xcec4,0xcec5,0xcec6,0xcec7, + 0xcec8,0xcec9,0xceca,0xcecb,0xcecc,0xcecd,0xcece,0xcecf, + 0xced0,0xced1,0xced2,0xced3,0xced4,0xced5,0xced6,0xced7, + 0xced8,0xced9,0xceda,0xcedb,0xcedc,0xcedd,0xcede,0xcedf, + 0xcee0,0xcee1,0xcee2,0xcee3,0xcee4,0xcee5,0xcee6,0xcee7, + 0xcee8,0xcee9,0xceea,0xceeb,0xceec,0xceed,0xceee,0xceef, + 0xcef0,0xcef1,0xcef2,0xcef3,0xcef4,0xcef5,0xcef6,0xcef7, + 0xcef8,0xcef9,0xcefa,0xcefb,0xcefc,0xcefd,0xcefe,0xceff, + 0xcf00,0xcf01,0xcf02,0xcf03,0xcf04,0xcf05,0xcf06,0xcf07, + 0xcf08,0xcf09,0xcf0a,0xcf0b,0xcf0c,0xcf0d,0xcf0e,0xcf0f, + 0xcf10,0xcf11,0xcf12,0xcf13,0xcf14,0xcf15,0xcf16,0xcf17, + 0xcf18,0xcf19,0xcf1a,0xcf1b,0xcf1c,0xcf1d,0xcf1e,0xcf1f, + 0xcf20,0xcf21,0xcf22,0xcf23,0xcf24,0xcf25,0xcf26,0xcf27, + 0xcf28,0xcf29,0xcf2a,0xcf2b,0xcf2c,0xcf2d,0xcf2e,0xcf2f, + 0xcf30,0xcf31,0xcf32,0xcf33,0xcf34,0xcf35,0xcf36,0xcf37, + 0xcf38,0xcf39,0xcf3a,0xcf3b,0xcf3c,0xcf3d,0xcf3e,0xcf3f, + 0xcf40,0xcf41,0xcf42,0xcf43,0xcf44,0xcf45,0xcf46,0xcf47, + 0xcf48,0xcf49,0xcf4a,0xcf4b,0xcf4c,0xcf4d,0xcf4e,0xcf4f, + 0xcf50,0xcf51,0xcf52,0xcf53,0xcf54,0xcf55,0xcf56,0xcf57, + 0xcf58,0xcf59,0xcf5a,0xcf5b,0xcf5c,0xcf5d,0xcf5e,0xcf5f, + 0xcf60,0xcf61,0xcf62,0xcf63,0xcf64,0xcf65,0xcf66,0xcf67, + 0xcf68,0xcf69,0xcf6a,0xcf6b,0xcf6c,0xcf6d,0xcf6e,0xcf6f, + 0xcf70,0xcf71,0xcf72,0xcf73,0xcf74,0xcf75,0xcf76,0xcf77, + 0xcf78,0xcf79,0xcf7a,0xcf7b,0xcf7c,0xcf7d,0xcf7e,0xcf7f, + 0xcf80,0xcf81,0xcf82,0xcf83,0xcf84,0xcf85,0xcf86,0xcf87, + 0xcf88,0xcf89,0xcf8a,0xcf8b,0xcf8c,0xcf8d,0xcf8e,0xcf8f, + 0xcf90,0xcf91,0xcf92,0xcf93,0xcf94,0xcf95,0xcf96,0xcf97, + 0xcf98,0xcf99,0xcf9a,0xcf9b,0xcf9c,0xcf9d,0xcf9e,0xcf9f, + 0xcfa0,0xcfa1,0xcfa2,0xcfa3,0xcfa4,0xcfa5,0xcfa6,0xcfa7, + 0xcfa8,0xcfa9,0xcfaa,0xcfab,0xcfac,0xcfad,0xcfae,0xcfaf, + 0xcfb0,0xcfb1,0xcfb2,0xcfb3,0xcfb4,0xcfb5,0xcfb6,0xcfb7, + 0xcfb8,0xcfb9,0xcfba,0xcfbb,0xcfbc,0xcfbd,0xcfbe,0xcfbf, + 0xcfc0,0xcfc1,0xcfc2,0xcfc3,0xcfc4,0xcfc5,0xcfc6,0xcfc7, + 0xcfc8,0xcfc9,0xcfca,0xcfcb,0xcfcc,0xcfcd,0xcfce,0xcfcf, + 0xcfd0,0xcfd1,0xcfd2,0xcfd3,0xcfd4,0xcfd5,0xcfd6,0xcfd7, + 0xcfd8,0xcfd9,0xcfda,0xcfdb,0xcfdc,0xcfdd,0xcfde,0xcfdf, + 0xcfe0,0xcfe1,0xcfe2,0xcfe3,0xcfe4,0xcfe5,0xcfe6,0xcfe7, + 0xcfe8,0xcfe9,0xcfea,0xcfeb,0xcfec,0xcfed,0xcfee,0xcfef, + 0xcff0,0xcff1,0xcff2,0xcff3,0xcff4,0xcff5,0xcff6,0xcff7, + 0xcff8,0xcff9,0xcffa,0xcffb,0xcffc,0xcffd,0xcffe,0xcfff, + 0xd000,0xd001,0xd002,0xd003,0xd004,0xd005,0xd006,0xd007, + 0xd008,0xd009,0xd00a,0xd00b,0xd00c,0xd00d,0xd00e,0xd00f, + 0xd010,0xd011,0xd012,0xd013,0xd014,0xd015,0xd016,0xd017, + 0xd018,0xd019,0xd01a,0xd01b,0xd01c,0xd01d,0xd01e,0xd01f, + 0xd020,0xd021,0xd022,0xd023,0xd024,0xd025,0xd026,0xd027, + 0xd028,0xd029,0xd02a,0xd02b,0xd02c,0xd02d,0xd02e,0xd02f, + 0xd030,0xd031,0xd032,0xd033,0xd034,0xd035,0xd036,0xd037, + 0xd038,0xd039,0xd03a,0xd03b,0xd03c,0xd03d,0xd03e,0xd03f, + 0xd040,0xd041,0xd042,0xd043,0xd044,0xd045,0xd046,0xd047, + 0xd048,0xd049,0xd04a,0xd04b,0xd04c,0xd04d,0xd04e,0xd04f, + 0xd050,0xd051,0xd052,0xd053,0xd054,0xd055,0xd056,0xd057, + 0xd058,0xd059,0xd05a,0xd05b,0xd05c,0xd05d,0xd05e,0xd05f, + 0xd060,0xd061,0xd062,0xd063,0xd064,0xd065,0xd066,0xd067, + 0xd068,0xd069,0xd06a,0xd06b,0xd06c,0xd06d,0xd06e,0xd06f, + 0xd070,0xd071,0xd072,0xd073,0xd074,0xd075,0xd076,0xd077, + 0xd078,0xd079,0xd07a,0xd07b,0xd07c,0xd07d,0xd07e,0xd07f, + 0xd080,0xd081,0xd082,0xd083,0xd084,0xd085,0xd086,0xd087, + 0xd088,0xd089,0xd08a,0xd08b,0xd08c,0xd08d,0xd08e,0xd08f, + 0xd090,0xd091,0xd092,0xd093,0xd094,0xd095,0xd096,0xd097, + 0xd098,0xd099,0xd09a,0xd09b,0xd09c,0xd09d,0xd09e,0xd09f, + 0xd0a0,0xd0a1,0xd0a2,0xd0a3,0xd0a4,0xd0a5,0xd0a6,0xd0a7, + 0xd0a8,0xd0a9,0xd0aa,0xd0ab,0xd0ac,0xd0ad,0xd0ae,0xd0af, + 0xd0b0,0xd0b1,0xd0b2,0xd0b3,0xd0b4,0xd0b5,0xd0b6,0xd0b7, + 0xd0b8,0xd0b9,0xd0ba,0xd0bb,0xd0bc,0xd0bd,0xd0be,0xd0bf, + 0xd0c0,0xd0c1,0xd0c2,0xd0c3,0xd0c4,0xd0c5,0xd0c6,0xd0c7, + 0xd0c8,0xd0c9,0xd0ca,0xd0cb,0xd0cc,0xd0cd,0xd0ce,0xd0cf, + 0xd0d0,0xd0d1,0xd0d2,0xd0d3,0xd0d4,0xd0d5,0xd0d6,0xd0d7, + 0xd0d8,0xd0d9,0xd0da,0xd0db,0xd0dc,0xd0dd,0xd0de,0xd0df, + 0xd0e0,0xd0e1,0xd0e2,0xd0e3,0xd0e4,0xd0e5,0xd0e6,0xd0e7, + 0xd0e8,0xd0e9,0xd0ea,0xd0eb,0xd0ec,0xd0ed,0xd0ee,0xd0ef, + 0xd0f0,0xd0f1,0xd0f2,0xd0f3,0xd0f4,0xd0f5,0xd0f6,0xd0f7, + 0xd0f8,0xd0f9,0xd0fa,0xd0fb,0xd0fc,0xd0fd,0xd0fe,0xd0ff, + 0xd100,0xd101,0xd102,0xd103,0xd104,0xd105,0xd106,0xd107, + 0xd108,0xd109,0xd10a,0xd10b,0xd10c,0xd10d,0xd10e,0xd10f, + 0xd110,0xd111,0xd112,0xd113,0xd114,0xd115,0xd116,0xd117, + 0xd118,0xd119,0xd11a,0xd11b,0xd11c,0xd11d,0xd11e,0xd11f, + 0xd120,0xd121,0xd122,0xd123,0xd124,0xd125,0xd126,0xd127, + 0xd128,0xd129,0xd12a,0xd12b,0xd12c,0xd12d,0xd12e,0xd12f, + 0xd130,0xd131,0xd132,0xd133,0xd134,0xd135,0xd136,0xd137, + 0xd138,0xd139,0xd13a,0xd13b,0xd13c,0xd13d,0xd13e,0xd13f, + 0xd140,0xd141,0xd142,0xd143,0xd144,0xd145,0xd146,0xd147, + 0xd148,0xd149,0xd14a,0xd14b,0xd14c,0xd14d,0xd14e,0xd14f, + 0xd150,0xd151,0xd152,0xd153,0xd154,0xd155,0xd156,0xd157, + 0xd158,0xd159,0xd15a,0xd15b,0xd15c,0xd15d,0xd15e,0xd15f, + 0xd160,0xd161,0xd162,0xd163,0xd164,0xd165,0xd166,0xd167, + 0xd168,0xd169,0xd16a,0xd16b,0xd16c,0xd16d,0xd16e,0xd16f, + 0xd170,0xd171,0xd172,0xd173,0xd174,0xd175,0xd176,0xd177, + 0xd178,0xd179,0xd17a,0xd17b,0xd17c,0xd17d,0xd17e,0xd17f, + 0xd180,0xd181,0xd182,0xd183,0xd184,0xd185,0xd186,0xd187, + 0xd188,0xd189,0xd18a,0xd18b,0xd18c,0xd18d,0xd18e,0xd18f, + 0xd190,0xd191,0xd192,0xd193,0xd194,0xd195,0xd196,0xd197, + 0xd198,0xd199,0xd19a,0xd19b,0xd19c,0xd19d,0xd19e,0xd19f, + 0xd1a0,0xd1a1,0xd1a2,0xd1a3,0xd1a4,0xd1a5,0xd1a6,0xd1a7, + 0xd1a8,0xd1a9,0xd1aa,0xd1ab,0xd1ac,0xd1ad,0xd1ae,0xd1af, + 0xd1b0,0xd1b1,0xd1b2,0xd1b3,0xd1b4,0xd1b5,0xd1b6,0xd1b7, + 0xd1b8,0xd1b9,0xd1ba,0xd1bb,0xd1bc,0xd1bd,0xd1be,0xd1bf, + 0xd1c0,0xd1c1,0xd1c2,0xd1c3,0xd1c4,0xd1c5,0xd1c6,0xd1c7, + 0xd1c8,0xd1c9,0xd1ca,0xd1cb,0xd1cc,0xd1cd,0xd1ce,0xd1cf, + 0xd1d0,0xd1d1,0xd1d2,0xd1d3,0xd1d4,0xd1d5,0xd1d6,0xd1d7, + 0xd1d8,0xd1d9,0xd1da,0xd1db,0xd1dc,0xd1dd,0xd1de,0xd1df, + 0xd1e0,0xd1e1,0xd1e2,0xd1e3,0xd1e4,0xd1e5,0xd1e6,0xd1e7, + 0xd1e8,0xd1e9,0xd1ea,0xd1eb,0xd1ec,0xd1ed,0xd1ee,0xd1ef, + 0xd1f0,0xd1f1,0xd1f2,0xd1f3,0xd1f4,0xd1f5,0xd1f6,0xd1f7, + 0xd1f8,0xd1f9,0xd1fa,0xd1fb,0xd1fc,0xd1fd,0xd1fe,0xd1ff, + 0xd200,0xd201,0xd202,0xd203,0xd204,0xd205,0xd206,0xd207, + 0xd208,0xd209,0xd20a,0xd20b,0xd20c,0xd20d,0xd20e,0xd20f, + 0xd210,0xd211,0xd212,0xd213,0xd214,0xd215,0xd216,0xd217, + 0xd218,0xd219,0xd21a,0xd21b,0xd21c,0xd21d,0xd21e,0xd21f, + 0xd220,0xd221,0xd222,0xd223,0xd224,0xd225,0xd226,0xd227, + 0xd228,0xd229,0xd22a,0xd22b,0xd22c,0xd22d,0xd22e,0xd22f, + 0xd230,0xd231,0xd232,0xd233,0xd234,0xd235,0xd236,0xd237, + 0xd238,0xd239,0xd23a,0xd23b,0xd23c,0xd23d,0xd23e,0xd23f, + 0xd240,0xd241,0xd242,0xd243,0xd244,0xd245,0xd246,0xd247, + 0xd248,0xd249,0xd24a,0xd24b,0xd24c,0xd24d,0xd24e,0xd24f, + 0xd250,0xd251,0xd252,0xd253,0xd254,0xd255,0xd256,0xd257, + 0xd258,0xd259,0xd25a,0xd25b,0xd25c,0xd25d,0xd25e,0xd25f, + 0xd260,0xd261,0xd262,0xd263,0xd264,0xd265,0xd266,0xd267, + 0xd268,0xd269,0xd26a,0xd26b,0xd26c,0xd26d,0xd26e,0xd26f, + 0xd270,0xd271,0xd272,0xd273,0xd274,0xd275,0xd276,0xd277, + 0xd278,0xd279,0xd27a,0xd27b,0xd27c,0xd27d,0xd27e,0xd27f, + 0xd280,0xd281,0xd282,0xd283,0xd284,0xd285,0xd286,0xd287, + 0xd288,0xd289,0xd28a,0xd28b,0xd28c,0xd28d,0xd28e,0xd28f, + 0xd290,0xd291,0xd292,0xd293,0xd294,0xd295,0xd296,0xd297, + 0xd298,0xd299,0xd29a,0xd29b,0xd29c,0xd29d,0xd29e,0xd29f, + 0xd2a0,0xd2a1,0xd2a2,0xd2a3,0xd2a4,0xd2a5,0xd2a6,0xd2a7, + 0xd2a8,0xd2a9,0xd2aa,0xd2ab,0xd2ac,0xd2ad,0xd2ae,0xd2af, + 0xd2b0,0xd2b1,0xd2b2,0xd2b3,0xd2b4,0xd2b5,0xd2b6,0xd2b7, + 0xd2b8,0xd2b9,0xd2ba,0xd2bb,0xd2bc,0xd2bd,0xd2be,0xd2bf, + 0xd2c0,0xd2c1,0xd2c2,0xd2c3,0xd2c4,0xd2c5,0xd2c6,0xd2c7, + 0xd2c8,0xd2c9,0xd2ca,0xd2cb,0xd2cc,0xd2cd,0xd2ce,0xd2cf, + 0xd2d0,0xd2d1,0xd2d2,0xd2d3,0xd2d4,0xd2d5,0xd2d6,0xd2d7, + 0xd2d8,0xd2d9,0xd2da,0xd2db,0xd2dc,0xd2dd,0xd2de,0xd2df, + 0xd2e0,0xd2e1,0xd2e2,0xd2e3,0xd2e4,0xd2e5,0xd2e6,0xd2e7, + 0xd2e8,0xd2e9,0xd2ea,0xd2eb,0xd2ec,0xd2ed,0xd2ee,0xd2ef, + 0xd2f0,0xd2f1,0xd2f2,0xd2f3,0xd2f4,0xd2f5,0xd2f6,0xd2f7, + 0xd2f8,0xd2f9,0xd2fa,0xd2fb,0xd2fc,0xd2fd,0xd2fe,0xd2ff, + 0xd300,0xd301,0xd302,0xd303,0xd304,0xd305,0xd306,0xd307, + 0xd308,0xd309,0xd30a,0xd30b,0xd30c,0xd30d,0xd30e,0xd30f, + 0xd310,0xd311,0xd312,0xd313,0xd314,0xd315,0xd316,0xd317, + 0xd318,0xd319,0xd31a,0xd31b,0xd31c,0xd31d,0xd31e,0xd31f, + 0xd320,0xd321,0xd322,0xd323,0xd324,0xd325,0xd326,0xd327, + 0xd328,0xd329,0xd32a,0xd32b,0xd32c,0xd32d,0xd32e,0xd32f, + 0xd330,0xd331,0xd332,0xd333,0xd334,0xd335,0xd336,0xd337, + 0xd338,0xd339,0xd33a,0xd33b,0xd33c,0xd33d,0xd33e,0xd33f, + 0xd340,0xd341,0xd342,0xd343,0xd344,0xd345,0xd346,0xd347, + 0xd348,0xd349,0xd34a,0xd34b,0xd34c,0xd34d,0xd34e,0xd34f, + 0xd350,0xd351,0xd352,0xd353,0xd354,0xd355,0xd356,0xd357, + 0xd358,0xd359,0xd35a,0xd35b,0xd35c,0xd35d,0xd35e,0xd35f, + 0xd360,0xd361,0xd362,0xd363,0xd364,0xd365,0xd366,0xd367, + 0xd368,0xd369,0xd36a,0xd36b,0xd36c,0xd36d,0xd36e,0xd36f, + 0xd370,0xd371,0xd372,0xd373,0xd374,0xd375,0xd376,0xd377, + 0xd378,0xd379,0xd37a,0xd37b,0xd37c,0xd37d,0xd37e,0xd37f, + 0xd380,0xd381,0xd382,0xd383,0xd384,0xd385,0xd386,0xd387, + 0xd388,0xd389,0xd38a,0xd38b,0xd38c,0xd38d,0xd38e,0xd38f, + 0xd390,0xd391,0xd392,0xd393,0xd394,0xd395,0xd396,0xd397, + 0xd398,0xd399,0xd39a,0xd39b,0xd39c,0xd39d,0xd39e,0xd39f, + 0xd3a0,0xd3a1,0xd3a2,0xd3a3,0xd3a4,0xd3a5,0xd3a6,0xd3a7, + 0xd3a8,0xd3a9,0xd3aa,0xd3ab,0xd3ac,0xd3ad,0xd3ae,0xd3af, + 0xd3b0,0xd3b1,0xd3b2,0xd3b3,0xd3b4,0xd3b5,0xd3b6,0xd3b7, + 0xd3b8,0xd3b9,0xd3ba,0xd3bb,0xd3bc,0xd3bd,0xd3be,0xd3bf, + 0xd3c0,0xd3c1,0xd3c2,0xd3c3,0xd3c4,0xd3c5,0xd3c6,0xd3c7, + 0xd3c8,0xd3c9,0xd3ca,0xd3cb,0xd3cc,0xd3cd,0xd3ce,0xd3cf, + 0xd3d0,0xd3d1,0xd3d2,0xd3d3,0xd3d4,0xd3d5,0xd3d6,0xd3d7, + 0xd3d8,0xd3d9,0xd3da,0xd3db,0xd3dc,0xd3dd,0xd3de,0xd3df, + 0xd3e0,0xd3e1,0xd3e2,0xd3e3,0xd3e4,0xd3e5,0xd3e6,0xd3e7, + 0xd3e8,0xd3e9,0xd3ea,0xd3eb,0xd3ec,0xd3ed,0xd3ee,0xd3ef, + 0xd3f0,0xd3f1,0xd3f2,0xd3f3,0xd3f4,0xd3f5,0xd3f6,0xd3f7, + 0xd3f8,0xd3f9,0xd3fa,0xd3fb,0xd3fc,0xd3fd,0xd3fe,0xd3ff, + 0xd400,0xd401,0xd402,0xd403,0xd404,0xd405,0xd406,0xd407, + 0xd408,0xd409,0xd40a,0xd40b,0xd40c,0xd40d,0xd40e,0xd40f, + 0xd410,0xd411,0xd412,0xd413,0xd414,0xd415,0xd416,0xd417, + 0xd418,0xd419,0xd41a,0xd41b,0xd41c,0xd41d,0xd41e,0xd41f, + 0xd420,0xd421,0xd422,0xd423,0xd424,0xd425,0xd426,0xd427, + 0xd428,0xd429,0xd42a,0xd42b,0xd42c,0xd42d,0xd42e,0xd42f, + 0xd430,0xd431,0xd432,0xd433,0xd434,0xd435,0xd436,0xd437, + 0xd438,0xd439,0xd43a,0xd43b,0xd43c,0xd43d,0xd43e,0xd43f, + 0xd440,0xd441,0xd442,0xd443,0xd444,0xd445,0xd446,0xd447, + 0xd448,0xd449,0xd44a,0xd44b,0xd44c,0xd44d,0xd44e,0xd44f, + 0xd450,0xd451,0xd452,0xd453,0xd454,0xd455,0xd456,0xd457, + 0xd458,0xd459,0xd45a,0xd45b,0xd45c,0xd45d,0xd45e,0xd45f, + 0xd460,0xd461,0xd462,0xd463,0xd464,0xd465,0xd466,0xd467, + 0xd468,0xd469,0xd46a,0xd46b,0xd46c,0xd46d,0xd46e,0xd46f, + 0xd470,0xd471,0xd472,0xd473,0xd474,0xd475,0xd476,0xd477, + 0xd478,0xd479,0xd47a,0xd47b,0xd47c,0xd47d,0xd47e,0xd47f, + 0xd480,0xd481,0xd482,0xd483,0xd484,0xd485,0xd486,0xd487, + 0xd488,0xd489,0xd48a,0xd48b,0xd48c,0xd48d,0xd48e,0xd48f, + 0xd490,0xd491,0xd492,0xd493,0xd494,0xd495,0xd496,0xd497, + 0xd498,0xd499,0xd49a,0xd49b,0xd49c,0xd49d,0xd49e,0xd49f, + 0xd4a0,0xd4a1,0xd4a2,0xd4a3,0xd4a4,0xd4a5,0xd4a6,0xd4a7, + 0xd4a8,0xd4a9,0xd4aa,0xd4ab,0xd4ac,0xd4ad,0xd4ae,0xd4af, + 0xd4b0,0xd4b1,0xd4b2,0xd4b3,0xd4b4,0xd4b5,0xd4b6,0xd4b7, + 0xd4b8,0xd4b9,0xd4ba,0xd4bb,0xd4bc,0xd4bd,0xd4be,0xd4bf, + 0xd4c0,0xd4c1,0xd4c2,0xd4c3,0xd4c4,0xd4c5,0xd4c6,0xd4c7, + 0xd4c8,0xd4c9,0xd4ca,0xd4cb,0xd4cc,0xd4cd,0xd4ce,0xd4cf, + 0xd4d0,0xd4d1,0xd4d2,0xd4d3,0xd4d4,0xd4d5,0xd4d6,0xd4d7, + 0xd4d8,0xd4d9,0xd4da,0xd4db,0xd4dc,0xd4dd,0xd4de,0xd4df, + 0xd4e0,0xd4e1,0xd4e2,0xd4e3,0xd4e4,0xd4e5,0xd4e6,0xd4e7, + 0xd4e8,0xd4e9,0xd4ea,0xd4eb,0xd4ec,0xd4ed,0xd4ee,0xd4ef, + 0xd4f0,0xd4f1,0xd4f2,0xd4f3,0xd4f4,0xd4f5,0xd4f6,0xd4f7, + 0xd4f8,0xd4f9,0xd4fa,0xd4fb,0xd4fc,0xd4fd,0xd4fe,0xd4ff, + 0xd500,0xd501,0xd502,0xd503,0xd504,0xd505,0xd506,0xd507, + 0xd508,0xd509,0xd50a,0xd50b,0xd50c,0xd50d,0xd50e,0xd50f, + 0xd510,0xd511,0xd512,0xd513,0xd514,0xd515,0xd516,0xd517, + 0xd518,0xd519,0xd51a,0xd51b,0xd51c,0xd51d,0xd51e,0xd51f, + 0xd520,0xd521,0xd522,0xd523,0xd524,0xd525,0xd526,0xd527, + 0xd528,0xd529,0xd52a,0xd52b,0xd52c,0xd52d,0xd52e,0xd52f, + 0xd530,0xd531,0xd532,0xd533,0xd534,0xd535,0xd536,0xd537, + 0xd538,0xd539,0xd53a,0xd53b,0xd53c,0xd53d,0xd53e,0xd53f, + 0xd540,0xd541,0xd542,0xd543,0xd544,0xd545,0xd546,0xd547, + 0xd548,0xd549,0xd54a,0xd54b,0xd54c,0xd54d,0xd54e,0xd54f, + 0xd550,0xd551,0xd552,0xd553,0xd554,0xd555,0xd556,0xd557, + 0xd558,0xd559,0xd55a,0xd55b,0xd55c,0xd55d,0xd55e,0xd55f, + 0xd560,0xd561,0xd562,0xd563,0xd564,0xd565,0xd566,0xd567, + 0xd568,0xd569,0xd56a,0xd56b,0xd56c,0xd56d,0xd56e,0xd56f, + 0xd570,0xd571,0xd572,0xd573,0xd574,0xd575,0xd576,0xd577, + 0xd578,0xd579,0xd57a,0xd57b,0xd57c,0xd57d,0xd57e,0xd57f, + 0xd580,0xd581,0xd582,0xd583,0xd584,0xd585,0xd586,0xd587, + 0xd588,0xd589,0xd58a,0xd58b,0xd58c,0xd58d,0xd58e,0xd58f, + 0xd590,0xd591,0xd592,0xd593,0xd594,0xd595,0xd596,0xd597, + 0xd598,0xd599,0xd59a,0xd59b,0xd59c,0xd59d,0xd59e,0xd59f, + 0xd5a0,0xd5a1,0xd5a2,0xd5a3,0xd5a4,0xd5a5,0xd5a6,0xd5a7, + 0xd5a8,0xd5a9,0xd5aa,0xd5ab,0xd5ac,0xd5ad,0xd5ae,0xd5af, + 0xd5b0,0xd5b1,0xd5b2,0xd5b3,0xd5b4,0xd5b5,0xd5b6,0xd5b7, + 0xd5b8,0xd5b9,0xd5ba,0xd5bb,0xd5bc,0xd5bd,0xd5be,0xd5bf, + 0xd5c0,0xd5c1,0xd5c2,0xd5c3,0xd5c4,0xd5c5,0xd5c6,0xd5c7, + 0xd5c8,0xd5c9,0xd5ca,0xd5cb,0xd5cc,0xd5cd,0xd5ce,0xd5cf, + 0xd5d0,0xd5d1,0xd5d2,0xd5d3,0xd5d4,0xd5d5,0xd5d6,0xd5d7, + 0xd5d8,0xd5d9,0xd5da,0xd5db,0xd5dc,0xd5dd,0xd5de,0xd5df, + 0xd5e0,0xd5e1,0xd5e2,0xd5e3,0xd5e4,0xd5e5,0xd5e6,0xd5e7, + 0xd5e8,0xd5e9,0xd5ea,0xd5eb,0xd5ec,0xd5ed,0xd5ee,0xd5ef, + 0xd5f0,0xd5f1,0xd5f2,0xd5f3,0xd5f4,0xd5f5,0xd5f6,0xd5f7, + 0xd5f8,0xd5f9,0xd5fa,0xd5fb,0xd5fc,0xd5fd,0xd5fe,0xd5ff, + 0xd600,0xd601,0xd602,0xd603,0xd604,0xd605,0xd606,0xd607, + 0xd608,0xd609,0xd60a,0xd60b,0xd60c,0xd60d,0xd60e,0xd60f, + 0xd610,0xd611,0xd612,0xd613,0xd614,0xd615,0xd616,0xd617, + 0xd618,0xd619,0xd61a,0xd61b,0xd61c,0xd61d,0xd61e,0xd61f, + 0xd620,0xd621,0xd622,0xd623,0xd624,0xd625,0xd626,0xd627, + 0xd628,0xd629,0xd62a,0xd62b,0xd62c,0xd62d,0xd62e,0xd62f, + 0xd630,0xd631,0xd632,0xd633,0xd634,0xd635,0xd636,0xd637, + 0xd638,0xd639,0xd63a,0xd63b,0xd63c,0xd63d,0xd63e,0xd63f, + 0xd640,0xd641,0xd642,0xd643,0xd644,0xd645,0xd646,0xd647, + 0xd648,0xd649,0xd64a,0xd64b,0xd64c,0xd64d,0xd64e,0xd64f, + 0xd650,0xd651,0xd652,0xd653,0xd654,0xd655,0xd656,0xd657, + 0xd658,0xd659,0xd65a,0xd65b,0xd65c,0xd65d,0xd65e,0xd65f, + 0xd660,0xd661,0xd662,0xd663,0xd664,0xd665,0xd666,0xd667, + 0xd668,0xd669,0xd66a,0xd66b,0xd66c,0xd66d,0xd66e,0xd66f, + 0xd670,0xd671,0xd672,0xd673,0xd674,0xd675,0xd676,0xd677, + 0xd678,0xd679,0xd67a,0xd67b,0xd67c,0xd67d,0xd67e,0xd67f, + 0xd680,0xd681,0xd682,0xd683,0xd684,0xd685,0xd686,0xd687, + 0xd688,0xd689,0xd68a,0xd68b,0xd68c,0xd68d,0xd68e,0xd68f, + 0xd690,0xd691,0xd692,0xd693,0xd694,0xd695,0xd696,0xd697, + 0xd698,0xd699,0xd69a,0xd69b,0xd69c,0xd69d,0xd69e,0xd69f, + 0xd6a0,0xd6a1,0xd6a2,0xd6a3,0xd6a4,0xd6a5,0xd6a6,0xd6a7, + 0xd6a8,0xd6a9,0xd6aa,0xd6ab,0xd6ac,0xd6ad,0xd6ae,0xd6af, + 0xd6b0,0xd6b1,0xd6b2,0xd6b3,0xd6b4,0xd6b5,0xd6b6,0xd6b7, + 0xd6b8,0xd6b9,0xd6ba,0xd6bb,0xd6bc,0xd6bd,0xd6be,0xd6bf, + 0xd6c0,0xd6c1,0xd6c2,0xd6c3,0xd6c4,0xd6c5,0xd6c6,0xd6c7, + 0xd6c8,0xd6c9,0xd6ca,0xd6cb,0xd6cc,0xd6cd,0xd6ce,0xd6cf, + 0xd6d0,0xd6d1,0xd6d2,0xd6d3,0xd6d4,0xd6d5,0xd6d6,0xd6d7, + 0xd6d8,0xd6d9,0xd6da,0xd6db,0xd6dc,0xd6dd,0xd6de,0xd6df, + 0xd6e0,0xd6e1,0xd6e2,0xd6e3,0xd6e4,0xd6e5,0xd6e6,0xd6e7, + 0xd6e8,0xd6e9,0xd6ea,0xd6eb,0xd6ec,0xd6ed,0xd6ee,0xd6ef, + 0xd6f0,0xd6f1,0xd6f2,0xd6f3,0xd6f4,0xd6f5,0xd6f6,0xd6f7, + 0xd6f8,0xd6f9,0xd6fa,0xd6fb,0xd6fc,0xd6fd,0xd6fe,0xd6ff, + 0xd700,0xd701,0xd702,0xd703,0xd704,0xd705,0xd706,0xd707, + 0xd708,0xd709,0xd70a,0xd70b,0xd70c,0xd70d,0xd70e,0xd70f, + 0xd710,0xd711,0xd712,0xd713,0xd714,0xd715,0xd716,0xd717, + 0xd718,0xd719,0xd71a,0xd71b,0xd71c,0xd71d,0xd71e,0xd71f, + 0xd720,0xd721,0xd722,0xd723,0xd724,0xd725,0xd726,0xd727, + 0xd728,0xd729,0xd72a,0xd72b,0xd72c,0xd72d,0xd72e,0xd72f, + 0xd730,0xd731,0xd732,0xd733,0xd734,0xd735,0xd736,0xd737, + 0xd738,0xd739,0xd73a,0xd73b,0xd73c,0xd73d,0xd73e,0xd73f, + 0xd740,0xd741,0xd742,0xd743,0xd744,0xd745,0xd746,0xd747, + 0xd748,0xd749,0xd74a,0xd74b,0xd74c,0xd74d,0xd74e,0xd74f, + 0xd750,0xd751,0xd752,0xd753,0xd754,0xd755,0xd756,0xd757, + 0xd758,0xd759,0xd75a,0xd75b,0xd75c,0xd75d,0xd75e,0xd75f, + 0xd760,0xd761,0xd762,0xd763,0xd764,0xd765,0xd766,0xd767, + 0xd768,0xd769,0xd76a,0xd76b,0xd76c,0xd76d,0xd76e,0xd76f, + 0xd770,0xd771,0xd772,0xd773,0xd774,0xd775,0xd776,0xd777, + 0xd778,0xd779,0xd77a,0xd77b,0xd77c,0xd77d,0xd77e,0xd77f, + 0xd780,0xd781,0xd782,0xd783,0xd784,0xd785,0xd786,0xd787, + 0xd788,0xd789,0xd78a,0xd78b,0xd78c,0xd78d,0xd78e,0xd78f, + 0xd790,0xd791,0xd792,0xd793,0xd794,0xd795,0xd796,0xd797, + 0xd798,0xd799,0xd79a,0xd79b,0xd79c,0xd79d,0xd79e,0xd79f, + 0xd7a0,0xd7a1,0xd7a2,0xd7a3,0xd7a4,0xd7a5,0xd7a6,0xd7a7, + 0xd7a8,0xd7a9,0xd7aa,0xd7ab,0xd7ac,0xd7ad,0xd7ae,0xd7af, + 0xd7b0,0xd7b1,0xd7b2,0xd7b3,0xd7b4,0xd7b5,0xd7b6,0xd7b7, + 0xd7b8,0xd7b9,0xd7ba,0xd7bb,0xd7bc,0xd7bd,0xd7be,0xd7bf, + 0xd7c0,0xd7c1,0xd7c2,0xd7c3,0xd7c4,0xd7c5,0xd7c6,0xd7c7, + 0xd7c8,0xd7c9,0xd7ca,0xd7cb,0xd7cc,0xd7cd,0xd7ce,0xd7cf, + 0xd7d0,0xd7d1,0xd7d2,0xd7d3,0xd7d4,0xd7d5,0xd7d6,0xd7d7, + 0xd7d8,0xd7d9,0xd7da,0xd7db,0xd7dc,0xd7dd,0xd7de,0xd7df, + 0xd7e0,0xd7e1,0xd7e2,0xd7e3,0xd7e4,0xd7e5,0xd7e6,0xd7e7, + 0xd7e8,0xd7e9,0xd7ea,0xd7eb,0xd7ec,0xd7ed,0xd7ee,0xd7ef, + 0xd7f0,0xd7f1,0xd7f2,0xd7f3,0xd7f4,0xd7f5,0xd7f6,0xd7f7, + 0xd7f8,0xd7f9,0xd7fa,0xd7fb,0xd7fc,0xd7fd,0xd7fe,0xd7ff, + 0xd800,0xd801,0xd802,0xd803,0xd804,0xd805,0xd806,0xd807, + 0xd808,0xd809,0xd80a,0xd80b,0xd80c,0xd80d,0xd80e,0xd80f, + 0xd810,0xd811,0xd812,0xd813,0xd814,0xd815,0xd816,0xd817, + 0xd818,0xd819,0xd81a,0xd81b,0xd81c,0xd81d,0xd81e,0xd81f, + 0xd820,0xd821,0xd822,0xd823,0xd824,0xd825,0xd826,0xd827, + 0xd828,0xd829,0xd82a,0xd82b,0xd82c,0xd82d,0xd82e,0xd82f, + 0xd830,0xd831,0xd832,0xd833,0xd834,0xd835,0xd836,0xd837, + 0xd838,0xd839,0xd83a,0xd83b,0xd83c,0xd83d,0xd83e,0xd83f, + 0xd840,0xd841,0xd842,0xd843,0xd844,0xd845,0xd846,0xd847, + 0xd848,0xd849,0xd84a,0xd84b,0xd84c,0xd84d,0xd84e,0xd84f, + 0xd850,0xd851,0xd852,0xd853,0xd854,0xd855,0xd856,0xd857, + 0xd858,0xd859,0xd85a,0xd85b,0xd85c,0xd85d,0xd85e,0xd85f, + 0xd860,0xd861,0xd862,0xd863,0xd864,0xd865,0xd866,0xd867, + 0xd868,0xd869,0xd86a,0xd86b,0xd86c,0xd86d,0xd86e,0xd86f, + 0xd870,0xd871,0xd872,0xd873,0xd874,0xd875,0xd876,0xd877, + 0xd878,0xd879,0xd87a,0xd87b,0xd87c,0xd87d,0xd87e,0xd87f, + 0xd880,0xd881,0xd882,0xd883,0xd884,0xd885,0xd886,0xd887, + 0xd888,0xd889,0xd88a,0xd88b,0xd88c,0xd88d,0xd88e,0xd88f, + 0xd890,0xd891,0xd892,0xd893,0xd894,0xd895,0xd896,0xd897, + 0xd898,0xd899,0xd89a,0xd89b,0xd89c,0xd89d,0xd89e,0xd89f, + 0xd8a0,0xd8a1,0xd8a2,0xd8a3,0xd8a4,0xd8a5,0xd8a6,0xd8a7, + 0xd8a8,0xd8a9,0xd8aa,0xd8ab,0xd8ac,0xd8ad,0xd8ae,0xd8af, + 0xd8b0,0xd8b1,0xd8b2,0xd8b3,0xd8b4,0xd8b5,0xd8b6,0xd8b7, + 0xd8b8,0xd8b9,0xd8ba,0xd8bb,0xd8bc,0xd8bd,0xd8be,0xd8bf, + 0xd8c0,0xd8c1,0xd8c2,0xd8c3,0xd8c4,0xd8c5,0xd8c6,0xd8c7, + 0xd8c8,0xd8c9,0xd8ca,0xd8cb,0xd8cc,0xd8cd,0xd8ce,0xd8cf, + 0xd8d0,0xd8d1,0xd8d2,0xd8d3,0xd8d4,0xd8d5,0xd8d6,0xd8d7, + 0xd8d8,0xd8d9,0xd8da,0xd8db,0xd8dc,0xd8dd,0xd8de,0xd8df, + 0xd8e0,0xd8e1,0xd8e2,0xd8e3,0xd8e4,0xd8e5,0xd8e6,0xd8e7, + 0xd8e8,0xd8e9,0xd8ea,0xd8eb,0xd8ec,0xd8ed,0xd8ee,0xd8ef, + 0xd8f0,0xd8f1,0xd8f2,0xd8f3,0xd8f4,0xd8f5,0xd8f6,0xd8f7, + 0xd8f8,0xd8f9,0xd8fa,0xd8fb,0xd8fc,0xd8fd,0xd8fe,0xd8ff, + 0xd900,0xd901,0xd902,0xd903,0xd904,0xd905,0xd906,0xd907, + 0xd908,0xd909,0xd90a,0xd90b,0xd90c,0xd90d,0xd90e,0xd90f, + 0xd910,0xd911,0xd912,0xd913,0xd914,0xd915,0xd916,0xd917, + 0xd918,0xd919,0xd91a,0xd91b,0xd91c,0xd91d,0xd91e,0xd91f, + 0xd920,0xd921,0xd922,0xd923,0xd924,0xd925,0xd926,0xd927, + 0xd928,0xd929,0xd92a,0xd92b,0xd92c,0xd92d,0xd92e,0xd92f, + 0xd930,0xd931,0xd932,0xd933,0xd934,0xd935,0xd936,0xd937, + 0xd938,0xd939,0xd93a,0xd93b,0xd93c,0xd93d,0xd93e,0xd93f, + 0xd940,0xd941,0xd942,0xd943,0xd944,0xd945,0xd946,0xd947, + 0xd948,0xd949,0xd94a,0xd94b,0xd94c,0xd94d,0xd94e,0xd94f, + 0xd950,0xd951,0xd952,0xd953,0xd954,0xd955,0xd956,0xd957, + 0xd958,0xd959,0xd95a,0xd95b,0xd95c,0xd95d,0xd95e,0xd95f, + 0xd960,0xd961,0xd962,0xd963,0xd964,0xd965,0xd966,0xd967, + 0xd968,0xd969,0xd96a,0xd96b,0xd96c,0xd96d,0xd96e,0xd96f, + 0xd970,0xd971,0xd972,0xd973,0xd974,0xd975,0xd976,0xd977, + 0xd978,0xd979,0xd97a,0xd97b,0xd97c,0xd97d,0xd97e,0xd97f, + 0xd980,0xd981,0xd982,0xd983,0xd984,0xd985,0xd986,0xd987, + 0xd988,0xd989,0xd98a,0xd98b,0xd98c,0xd98d,0xd98e,0xd98f, + 0xd990,0xd991,0xd992,0xd993,0xd994,0xd995,0xd996,0xd997, + 0xd998,0xd999,0xd99a,0xd99b,0xd99c,0xd99d,0xd99e,0xd99f, + 0xd9a0,0xd9a1,0xd9a2,0xd9a3,0xd9a4,0xd9a5,0xd9a6,0xd9a7, + 0xd9a8,0xd9a9,0xd9aa,0xd9ab,0xd9ac,0xd9ad,0xd9ae,0xd9af, + 0xd9b0,0xd9b1,0xd9b2,0xd9b3,0xd9b4,0xd9b5,0xd9b6,0xd9b7, + 0xd9b8,0xd9b9,0xd9ba,0xd9bb,0xd9bc,0xd9bd,0xd9be,0xd9bf, + 0xd9c0,0xd9c1,0xd9c2,0xd9c3,0xd9c4,0xd9c5,0xd9c6,0xd9c7, + 0xd9c8,0xd9c9,0xd9ca,0xd9cb,0xd9cc,0xd9cd,0xd9ce,0xd9cf, + 0xd9d0,0xd9d1,0xd9d2,0xd9d3,0xd9d4,0xd9d5,0xd9d6,0xd9d7, + 0xd9d8,0xd9d9,0xd9da,0xd9db,0xd9dc,0xd9dd,0xd9de,0xd9df, + 0xd9e0,0xd9e1,0xd9e2,0xd9e3,0xd9e4,0xd9e5,0xd9e6,0xd9e7, + 0xd9e8,0xd9e9,0xd9ea,0xd9eb,0xd9ec,0xd9ed,0xd9ee,0xd9ef, + 0xd9f0,0xd9f1,0xd9f2,0xd9f3,0xd9f4,0xd9f5,0xd9f6,0xd9f7, + 0xd9f8,0xd9f9,0xd9fa,0xd9fb,0xd9fc,0xd9fd,0xd9fe,0xd9ff, + 0xda00,0xda01,0xda02,0xda03,0xda04,0xda05,0xda06,0xda07, + 0xda08,0xda09,0xda0a,0xda0b,0xda0c,0xda0d,0xda0e,0xda0f, + 0xda10,0xda11,0xda12,0xda13,0xda14,0xda15,0xda16,0xda17, + 0xda18,0xda19,0xda1a,0xda1b,0xda1c,0xda1d,0xda1e,0xda1f, + 0xda20,0xda21,0xda22,0xda23,0xda24,0xda25,0xda26,0xda27, + 0xda28,0xda29,0xda2a,0xda2b,0xda2c,0xda2d,0xda2e,0xda2f, + 0xda30,0xda31,0xda32,0xda33,0xda34,0xda35,0xda36,0xda37, + 0xda38,0xda39,0xda3a,0xda3b,0xda3c,0xda3d,0xda3e,0xda3f, + 0xda40,0xda41,0xda42,0xda43,0xda44,0xda45,0xda46,0xda47, + 0xda48,0xda49,0xda4a,0xda4b,0xda4c,0xda4d,0xda4e,0xda4f, + 0xda50,0xda51,0xda52,0xda53,0xda54,0xda55,0xda56,0xda57, + 0xda58,0xda59,0xda5a,0xda5b,0xda5c,0xda5d,0xda5e,0xda5f, + 0xda60,0xda61,0xda62,0xda63,0xda64,0xda65,0xda66,0xda67, + 0xda68,0xda69,0xda6a,0xda6b,0xda6c,0xda6d,0xda6e,0xda6f, + 0xda70,0xda71,0xda72,0xda73,0xda74,0xda75,0xda76,0xda77, + 0xda78,0xda79,0xda7a,0xda7b,0xda7c,0xda7d,0xda7e,0xda7f, + 0xda80,0xda81,0xda82,0xda83,0xda84,0xda85,0xda86,0xda87, + 0xda88,0xda89,0xda8a,0xda8b,0xda8c,0xda8d,0xda8e,0xda8f, + 0xda90,0xda91,0xda92,0xda93,0xda94,0xda95,0xda96,0xda97, + 0xda98,0xda99,0xda9a,0xda9b,0xda9c,0xda9d,0xda9e,0xda9f, + 0xdaa0,0xdaa1,0xdaa2,0xdaa3,0xdaa4,0xdaa5,0xdaa6,0xdaa7, + 0xdaa8,0xdaa9,0xdaaa,0xdaab,0xdaac,0xdaad,0xdaae,0xdaaf, + 0xdab0,0xdab1,0xdab2,0xdab3,0xdab4,0xdab5,0xdab6,0xdab7, + 0xdab8,0xdab9,0xdaba,0xdabb,0xdabc,0xdabd,0xdabe,0xdabf, + 0xdac0,0xdac1,0xdac2,0xdac3,0xdac4,0xdac5,0xdac6,0xdac7, + 0xdac8,0xdac9,0xdaca,0xdacb,0xdacc,0xdacd,0xdace,0xdacf, + 0xdad0,0xdad1,0xdad2,0xdad3,0xdad4,0xdad5,0xdad6,0xdad7, + 0xdad8,0xdad9,0xdada,0xdadb,0xdadc,0xdadd,0xdade,0xdadf, + 0xdae0,0xdae1,0xdae2,0xdae3,0xdae4,0xdae5,0xdae6,0xdae7, + 0xdae8,0xdae9,0xdaea,0xdaeb,0xdaec,0xdaed,0xdaee,0xdaef, + 0xdaf0,0xdaf1,0xdaf2,0xdaf3,0xdaf4,0xdaf5,0xdaf6,0xdaf7, + 0xdaf8,0xdaf9,0xdafa,0xdafb,0xdafc,0xdafd,0xdafe,0xdaff, + 0xdb00,0xdb01,0xdb02,0xdb03,0xdb04,0xdb05,0xdb06,0xdb07, + 0xdb08,0xdb09,0xdb0a,0xdb0b,0xdb0c,0xdb0d,0xdb0e,0xdb0f, + 0xdb10,0xdb11,0xdb12,0xdb13,0xdb14,0xdb15,0xdb16,0xdb17, + 0xdb18,0xdb19,0xdb1a,0xdb1b,0xdb1c,0xdb1d,0xdb1e,0xdb1f, + 0xdb20,0xdb21,0xdb22,0xdb23,0xdb24,0xdb25,0xdb26,0xdb27, + 0xdb28,0xdb29,0xdb2a,0xdb2b,0xdb2c,0xdb2d,0xdb2e,0xdb2f, + 0xdb30,0xdb31,0xdb32,0xdb33,0xdb34,0xdb35,0xdb36,0xdb37, + 0xdb38,0xdb39,0xdb3a,0xdb3b,0xdb3c,0xdb3d,0xdb3e,0xdb3f, + 0xdb40,0xdb41,0xdb42,0xdb43,0xdb44,0xdb45,0xdb46,0xdb47, + 0xdb48,0xdb49,0xdb4a,0xdb4b,0xdb4c,0xdb4d,0xdb4e,0xdb4f, + 0xdb50,0xdb51,0xdb52,0xdb53,0xdb54,0xdb55,0xdb56,0xdb57, + 0xdb58,0xdb59,0xdb5a,0xdb5b,0xdb5c,0xdb5d,0xdb5e,0xdb5f, + 0xdb60,0xdb61,0xdb62,0xdb63,0xdb64,0xdb65,0xdb66,0xdb67, + 0xdb68,0xdb69,0xdb6a,0xdb6b,0xdb6c,0xdb6d,0xdb6e,0xdb6f, + 0xdb70,0xdb71,0xdb72,0xdb73,0xdb74,0xdb75,0xdb76,0xdb77, + 0xdb78,0xdb79,0xdb7a,0xdb7b,0xdb7c,0xdb7d,0xdb7e,0xdb7f, + 0xdb80,0xdb81,0xdb82,0xdb83,0xdb84,0xdb85,0xdb86,0xdb87, + 0xdb88,0xdb89,0xdb8a,0xdb8b,0xdb8c,0xdb8d,0xdb8e,0xdb8f, + 0xdb90,0xdb91,0xdb92,0xdb93,0xdb94,0xdb95,0xdb96,0xdb97, + 0xdb98,0xdb99,0xdb9a,0xdb9b,0xdb9c,0xdb9d,0xdb9e,0xdb9f, + 0xdba0,0xdba1,0xdba2,0xdba3,0xdba4,0xdba5,0xdba6,0xdba7, + 0xdba8,0xdba9,0xdbaa,0xdbab,0xdbac,0xdbad,0xdbae,0xdbaf, + 0xdbb0,0xdbb1,0xdbb2,0xdbb3,0xdbb4,0xdbb5,0xdbb6,0xdbb7, + 0xdbb8,0xdbb9,0xdbba,0xdbbb,0xdbbc,0xdbbd,0xdbbe,0xdbbf, + 0xdbc0,0xdbc1,0xdbc2,0xdbc3,0xdbc4,0xdbc5,0xdbc6,0xdbc7, + 0xdbc8,0xdbc9,0xdbca,0xdbcb,0xdbcc,0xdbcd,0xdbce,0xdbcf, + 0xdbd0,0xdbd1,0xdbd2,0xdbd3,0xdbd4,0xdbd5,0xdbd6,0xdbd7, + 0xdbd8,0xdbd9,0xdbda,0xdbdb,0xdbdc,0xdbdd,0xdbde,0xdbdf, + 0xdbe0,0xdbe1,0xdbe2,0xdbe3,0xdbe4,0xdbe5,0xdbe6,0xdbe7, + 0xdbe8,0xdbe9,0xdbea,0xdbeb,0xdbec,0xdbed,0xdbee,0xdbef, + 0xdbf0,0xdbf1,0xdbf2,0xdbf3,0xdbf4,0xdbf5,0xdbf6,0xdbf7, + 0xdbf8,0xdbf9,0xdbfa,0xdbfb,0xdbfc,0xdbfd,0xdbfe,0xdbff, + 0xdc00,0xdc01,0xdc02,0xdc03,0xdc04,0xdc05,0xdc06,0xdc07, + 0xdc08,0xdc09,0xdc0a,0xdc0b,0xdc0c,0xdc0d,0xdc0e,0xdc0f, + 0xdc10,0xdc11,0xdc12,0xdc13,0xdc14,0xdc15,0xdc16,0xdc17, + 0xdc18,0xdc19,0xdc1a,0xdc1b,0xdc1c,0xdc1d,0xdc1e,0xdc1f, + 0xdc20,0xdc21,0xdc22,0xdc23,0xdc24,0xdc25,0xdc26,0xdc27, + 0xdc28,0xdc29,0xdc2a,0xdc2b,0xdc2c,0xdc2d,0xdc2e,0xdc2f, + 0xdc30,0xdc31,0xdc32,0xdc33,0xdc34,0xdc35,0xdc36,0xdc37, + 0xdc38,0xdc39,0xdc3a,0xdc3b,0xdc3c,0xdc3d,0xdc3e,0xdc3f, + 0xdc40,0xdc41,0xdc42,0xdc43,0xdc44,0xdc45,0xdc46,0xdc47, + 0xdc48,0xdc49,0xdc4a,0xdc4b,0xdc4c,0xdc4d,0xdc4e,0xdc4f, + 0xdc50,0xdc51,0xdc52,0xdc53,0xdc54,0xdc55,0xdc56,0xdc57, + 0xdc58,0xdc59,0xdc5a,0xdc5b,0xdc5c,0xdc5d,0xdc5e,0xdc5f, + 0xdc60,0xdc61,0xdc62,0xdc63,0xdc64,0xdc65,0xdc66,0xdc67, + 0xdc68,0xdc69,0xdc6a,0xdc6b,0xdc6c,0xdc6d,0xdc6e,0xdc6f, + 0xdc70,0xdc71,0xdc72,0xdc73,0xdc74,0xdc75,0xdc76,0xdc77, + 0xdc78,0xdc79,0xdc7a,0xdc7b,0xdc7c,0xdc7d,0xdc7e,0xdc7f, + 0xdc80,0xdc81,0xdc82,0xdc83,0xdc84,0xdc85,0xdc86,0xdc87, + 0xdc88,0xdc89,0xdc8a,0xdc8b,0xdc8c,0xdc8d,0xdc8e,0xdc8f, + 0xdc90,0xdc91,0xdc92,0xdc93,0xdc94,0xdc95,0xdc96,0xdc97, + 0xdc98,0xdc99,0xdc9a,0xdc9b,0xdc9c,0xdc9d,0xdc9e,0xdc9f, + 0xdca0,0xdca1,0xdca2,0xdca3,0xdca4,0xdca5,0xdca6,0xdca7, + 0xdca8,0xdca9,0xdcaa,0xdcab,0xdcac,0xdcad,0xdcae,0xdcaf, + 0xdcb0,0xdcb1,0xdcb2,0xdcb3,0xdcb4,0xdcb5,0xdcb6,0xdcb7, + 0xdcb8,0xdcb9,0xdcba,0xdcbb,0xdcbc,0xdcbd,0xdcbe,0xdcbf, + 0xdcc0,0xdcc1,0xdcc2,0xdcc3,0xdcc4,0xdcc5,0xdcc6,0xdcc7, + 0xdcc8,0xdcc9,0xdcca,0xdccb,0xdccc,0xdccd,0xdcce,0xdccf, + 0xdcd0,0xdcd1,0xdcd2,0xdcd3,0xdcd4,0xdcd5,0xdcd6,0xdcd7, + 0xdcd8,0xdcd9,0xdcda,0xdcdb,0xdcdc,0xdcdd,0xdcde,0xdcdf, + 0xdce0,0xdce1,0xdce2,0xdce3,0xdce4,0xdce5,0xdce6,0xdce7, + 0xdce8,0xdce9,0xdcea,0xdceb,0xdcec,0xdced,0xdcee,0xdcef, + 0xdcf0,0xdcf1,0xdcf2,0xdcf3,0xdcf4,0xdcf5,0xdcf6,0xdcf7, + 0xdcf8,0xdcf9,0xdcfa,0xdcfb,0xdcfc,0xdcfd,0xdcfe,0xdcff, + 0xdd00,0xdd01,0xdd02,0xdd03,0xdd04,0xdd05,0xdd06,0xdd07, + 0xdd08,0xdd09,0xdd0a,0xdd0b,0xdd0c,0xdd0d,0xdd0e,0xdd0f, + 0xdd10,0xdd11,0xdd12,0xdd13,0xdd14,0xdd15,0xdd16,0xdd17, + 0xdd18,0xdd19,0xdd1a,0xdd1b,0xdd1c,0xdd1d,0xdd1e,0xdd1f, + 0xdd20,0xdd21,0xdd22,0xdd23,0xdd24,0xdd25,0xdd26,0xdd27, + 0xdd28,0xdd29,0xdd2a,0xdd2b,0xdd2c,0xdd2d,0xdd2e,0xdd2f, + 0xdd30,0xdd31,0xdd32,0xdd33,0xdd34,0xdd35,0xdd36,0xdd37, + 0xdd38,0xdd39,0xdd3a,0xdd3b,0xdd3c,0xdd3d,0xdd3e,0xdd3f, + 0xdd40,0xdd41,0xdd42,0xdd43,0xdd44,0xdd45,0xdd46,0xdd47, + 0xdd48,0xdd49,0xdd4a,0xdd4b,0xdd4c,0xdd4d,0xdd4e,0xdd4f, + 0xdd50,0xdd51,0xdd52,0xdd53,0xdd54,0xdd55,0xdd56,0xdd57, + 0xdd58,0xdd59,0xdd5a,0xdd5b,0xdd5c,0xdd5d,0xdd5e,0xdd5f, + 0xdd60,0xdd61,0xdd62,0xdd63,0xdd64,0xdd65,0xdd66,0xdd67, + 0xdd68,0xdd69,0xdd6a,0xdd6b,0xdd6c,0xdd6d,0xdd6e,0xdd6f, + 0xdd70,0xdd71,0xdd72,0xdd73,0xdd74,0xdd75,0xdd76,0xdd77, + 0xdd78,0xdd79,0xdd7a,0xdd7b,0xdd7c,0xdd7d,0xdd7e,0xdd7f, + 0xdd80,0xdd81,0xdd82,0xdd83,0xdd84,0xdd85,0xdd86,0xdd87, + 0xdd88,0xdd89,0xdd8a,0xdd8b,0xdd8c,0xdd8d,0xdd8e,0xdd8f, + 0xdd90,0xdd91,0xdd92,0xdd93,0xdd94,0xdd95,0xdd96,0xdd97, + 0xdd98,0xdd99,0xdd9a,0xdd9b,0xdd9c,0xdd9d,0xdd9e,0xdd9f, + 0xdda0,0xdda1,0xdda2,0xdda3,0xdda4,0xdda5,0xdda6,0xdda7, + 0xdda8,0xdda9,0xddaa,0xddab,0xddac,0xddad,0xddae,0xddaf, + 0xddb0,0xddb1,0xddb2,0xddb3,0xddb4,0xddb5,0xddb6,0xddb7, + 0xddb8,0xddb9,0xddba,0xddbb,0xddbc,0xddbd,0xddbe,0xddbf, + 0xddc0,0xddc1,0xddc2,0xddc3,0xddc4,0xddc5,0xddc6,0xddc7, + 0xddc8,0xddc9,0xddca,0xddcb,0xddcc,0xddcd,0xddce,0xddcf, + 0xddd0,0xddd1,0xddd2,0xddd3,0xddd4,0xddd5,0xddd6,0xddd7, + 0xddd8,0xddd9,0xddda,0xdddb,0xdddc,0xdddd,0xddde,0xdddf, + 0xdde0,0xdde1,0xdde2,0xdde3,0xdde4,0xdde5,0xdde6,0xdde7, + 0xdde8,0xdde9,0xddea,0xddeb,0xddec,0xdded,0xddee,0xddef, + 0xddf0,0xddf1,0xddf2,0xddf3,0xddf4,0xddf5,0xddf6,0xddf7, + 0xddf8,0xddf9,0xddfa,0xddfb,0xddfc,0xddfd,0xddfe,0xddff, + 0xde00,0xde01,0xde02,0xde03,0xde04,0xde05,0xde06,0xde07, + 0xde08,0xde09,0xde0a,0xde0b,0xde0c,0xde0d,0xde0e,0xde0f, + 0xde10,0xde11,0xde12,0xde13,0xde14,0xde15,0xde16,0xde17, + 0xde18,0xde19,0xde1a,0xde1b,0xde1c,0xde1d,0xde1e,0xde1f, + 0xde20,0xde21,0xde22,0xde23,0xde24,0xde25,0xde26,0xde27, + 0xde28,0xde29,0xde2a,0xde2b,0xde2c,0xde2d,0xde2e,0xde2f, + 0xde30,0xde31,0xde32,0xde33,0xde34,0xde35,0xde36,0xde37, + 0xde38,0xde39,0xde3a,0xde3b,0xde3c,0xde3d,0xde3e,0xde3f, + 0xde40,0xde41,0xde42,0xde43,0xde44,0xde45,0xde46,0xde47, + 0xde48,0xde49,0xde4a,0xde4b,0xde4c,0xde4d,0xde4e,0xde4f, + 0xde50,0xde51,0xde52,0xde53,0xde54,0xde55,0xde56,0xde57, + 0xde58,0xde59,0xde5a,0xde5b,0xde5c,0xde5d,0xde5e,0xde5f, + 0xde60,0xde61,0xde62,0xde63,0xde64,0xde65,0xde66,0xde67, + 0xde68,0xde69,0xde6a,0xde6b,0xde6c,0xde6d,0xde6e,0xde6f, + 0xde70,0xde71,0xde72,0xde73,0xde74,0xde75,0xde76,0xde77, + 0xde78,0xde79,0xde7a,0xde7b,0xde7c,0xde7d,0xde7e,0xde7f, + 0xde80,0xde81,0xde82,0xde83,0xde84,0xde85,0xde86,0xde87, + 0xde88,0xde89,0xde8a,0xde8b,0xde8c,0xde8d,0xde8e,0xde8f, + 0xde90,0xde91,0xde92,0xde93,0xde94,0xde95,0xde96,0xde97, + 0xde98,0xde99,0xde9a,0xde9b,0xde9c,0xde9d,0xde9e,0xde9f, + 0xdea0,0xdea1,0xdea2,0xdea3,0xdea4,0xdea5,0xdea6,0xdea7, + 0xdea8,0xdea9,0xdeaa,0xdeab,0xdeac,0xdead,0xdeae,0xdeaf, + 0xdeb0,0xdeb1,0xdeb2,0xdeb3,0xdeb4,0xdeb5,0xdeb6,0xdeb7, + 0xdeb8,0xdeb9,0xdeba,0xdebb,0xdebc,0xdebd,0xdebe,0xdebf, + 0xdec0,0xdec1,0xdec2,0xdec3,0xdec4,0xdec5,0xdec6,0xdec7, + 0xdec8,0xdec9,0xdeca,0xdecb,0xdecc,0xdecd,0xdece,0xdecf, + 0xded0,0xded1,0xded2,0xded3,0xded4,0xded5,0xded6,0xded7, + 0xded8,0xded9,0xdeda,0xdedb,0xdedc,0xdedd,0xdede,0xdedf, + 0xdee0,0xdee1,0xdee2,0xdee3,0xdee4,0xdee5,0xdee6,0xdee7, + 0xdee8,0xdee9,0xdeea,0xdeeb,0xdeec,0xdeed,0xdeee,0xdeef, + 0xdef0,0xdef1,0xdef2,0xdef3,0xdef4,0xdef5,0xdef6,0xdef7, + 0xdef8,0xdef9,0xdefa,0xdefb,0xdefc,0xdefd,0xdefe,0xdeff, + 0xdf00,0xdf01,0xdf02,0xdf03,0xdf04,0xdf05,0xdf06,0xdf07, + 0xdf08,0xdf09,0xdf0a,0xdf0b,0xdf0c,0xdf0d,0xdf0e,0xdf0f, + 0xdf10,0xdf11,0xdf12,0xdf13,0xdf14,0xdf15,0xdf16,0xdf17, + 0xdf18,0xdf19,0xdf1a,0xdf1b,0xdf1c,0xdf1d,0xdf1e,0xdf1f, + 0xdf20,0xdf21,0xdf22,0xdf23,0xdf24,0xdf25,0xdf26,0xdf27, + 0xdf28,0xdf29,0xdf2a,0xdf2b,0xdf2c,0xdf2d,0xdf2e,0xdf2f, + 0xdf30,0xdf31,0xdf32,0xdf33,0xdf34,0xdf35,0xdf36,0xdf37, + 0xdf38,0xdf39,0xdf3a,0xdf3b,0xdf3c,0xdf3d,0xdf3e,0xdf3f, + 0xdf40,0xdf41,0xdf42,0xdf43,0xdf44,0xdf45,0xdf46,0xdf47, + 0xdf48,0xdf49,0xdf4a,0xdf4b,0xdf4c,0xdf4d,0xdf4e,0xdf4f, + 0xdf50,0xdf51,0xdf52,0xdf53,0xdf54,0xdf55,0xdf56,0xdf57, + 0xdf58,0xdf59,0xdf5a,0xdf5b,0xdf5c,0xdf5d,0xdf5e,0xdf5f, + 0xdf60,0xdf61,0xdf62,0xdf63,0xdf64,0xdf65,0xdf66,0xdf67, + 0xdf68,0xdf69,0xdf6a,0xdf6b,0xdf6c,0xdf6d,0xdf6e,0xdf6f, + 0xdf70,0xdf71,0xdf72,0xdf73,0xdf74,0xdf75,0xdf76,0xdf77, + 0xdf78,0xdf79,0xdf7a,0xdf7b,0xdf7c,0xdf7d,0xdf7e,0xdf7f, + 0xdf80,0xdf81,0xdf82,0xdf83,0xdf84,0xdf85,0xdf86,0xdf87, + 0xdf88,0xdf89,0xdf8a,0xdf8b,0xdf8c,0xdf8d,0xdf8e,0xdf8f, + 0xdf90,0xdf91,0xdf92,0xdf93,0xdf94,0xdf95,0xdf96,0xdf97, + 0xdf98,0xdf99,0xdf9a,0xdf9b,0xdf9c,0xdf9d,0xdf9e,0xdf9f, + 0xdfa0,0xdfa1,0xdfa2,0xdfa3,0xdfa4,0xdfa5,0xdfa6,0xdfa7, + 0xdfa8,0xdfa9,0xdfaa,0xdfab,0xdfac,0xdfad,0xdfae,0xdfaf, + 0xdfb0,0xdfb1,0xdfb2,0xdfb3,0xdfb4,0xdfb5,0xdfb6,0xdfb7, + 0xdfb8,0xdfb9,0xdfba,0xdfbb,0xdfbc,0xdfbd,0xdfbe,0xdfbf, + 0xdfc0,0xdfc1,0xdfc2,0xdfc3,0xdfc4,0xdfc5,0xdfc6,0xdfc7, + 0xdfc8,0xdfc9,0xdfca,0xdfcb,0xdfcc,0xdfcd,0xdfce,0xdfcf, + 0xdfd0,0xdfd1,0xdfd2,0xdfd3,0xdfd4,0xdfd5,0xdfd6,0xdfd7, + 0xdfd8,0xdfd9,0xdfda,0xdfdb,0xdfdc,0xdfdd,0xdfde,0xdfdf, + 0xdfe0,0xdfe1,0xdfe2,0xdfe3,0xdfe4,0xdfe5,0xdfe6,0xdfe7, + 0xdfe8,0xdfe9,0xdfea,0xdfeb,0xdfec,0xdfed,0xdfee,0xdfef, + 0xdff0,0xdff1,0xdff2,0xdff3,0xdff4,0xdff5,0xdff6,0xdff7, + 0xdff8,0xdff9,0xdffa,0xdffb,0xdffc,0xdffd,0xdffe,0xdfff, + 0xe000,0xe001,0xe002,0xe003,0xe004,0xe005,0xe006,0xe007, + 0xe008,0xe009,0xe00a,0xe00b,0xe00c,0xe00d,0xe00e,0xe00f, + 0xe010,0xe011,0xe012,0xe013,0xe014,0xe015,0xe016,0xe017, + 0xe018,0xe019,0xe01a,0xe01b,0xe01c,0xe01d,0xe01e,0xe01f, + 0xe020,0xe021,0xe022,0xe023,0xe024,0xe025,0xe026,0xe027, + 0xe028,0xe029,0xe02a,0xe02b,0xe02c,0xe02d,0xe02e,0xe02f, + 0xe030,0xe031,0xe032,0xe033,0xe034,0xe035,0xe036,0xe037, + 0xe038,0xe039,0xe03a,0xe03b,0xe03c,0xe03d,0xe03e,0xe03f, + 0xe040,0xe041,0xe042,0xe043,0xe044,0xe045,0xe046,0xe047, + 0xe048,0xe049,0xe04a,0xe04b,0xe04c,0xe04d,0xe04e,0xe04f, + 0xe050,0xe051,0xe052,0xe053,0xe054,0xe055,0xe056,0xe057, + 0xe058,0xe059,0xe05a,0xe05b,0xe05c,0xe05d,0xe05e,0xe05f, + 0xe060,0xe061,0xe062,0xe063,0xe064,0xe065,0xe066,0xe067, + 0xe068,0xe069,0xe06a,0xe06b,0xe06c,0xe06d,0xe06e,0xe06f, + 0xe070,0xe071,0xe072,0xe073,0xe074,0xe075,0xe076,0xe077, + 0xe078,0xe079,0xe07a,0xe07b,0xe07c,0xe07d,0xe07e,0xe07f, + 0xe080,0xe081,0xe082,0xe083,0xe084,0xe085,0xe086,0xe087, + 0xe088,0xe089,0xe08a,0xe08b,0xe08c,0xe08d,0xe08e,0xe08f, + 0xe090,0xe091,0xe092,0xe093,0xe094,0xe095,0xe096,0xe097, + 0xe098,0xe099,0xe09a,0xe09b,0xe09c,0xe09d,0xe09e,0xe09f, + 0xe0a0,0xe0a1,0xe0a2,0xe0a3,0xe0a4,0xe0a5,0xe0a6,0xe0a7, + 0xe0a8,0xe0a9,0xe0aa,0xe0ab,0xe0ac,0xe0ad,0xe0ae,0xe0af, + 0xe0b0,0xe0b1,0xe0b2,0xe0b3,0xe0b4,0xe0b5,0xe0b6,0xe0b7, + 0xe0b8,0xe0b9,0xe0ba,0xe0bb,0xe0bc,0xe0bd,0xe0be,0xe0bf, + 0xe0c0,0xe0c1,0xe0c2,0xe0c3,0xe0c4,0xe0c5,0xe0c6,0xe0c7, + 0xe0c8,0xe0c9,0xe0ca,0xe0cb,0xe0cc,0xe0cd,0xe0ce,0xe0cf, + 0xe0d0,0xe0d1,0xe0d2,0xe0d3,0xe0d4,0xe0d5,0xe0d6,0xe0d7, + 0xe0d8,0xe0d9,0xe0da,0xe0db,0xe0dc,0xe0dd,0xe0de,0xe0df, + 0xe0e0,0xe0e1,0xe0e2,0xe0e3,0xe0e4,0xe0e5,0xe0e6,0xe0e7, + 0xe0e8,0xe0e9,0xe0ea,0xe0eb,0xe0ec,0xe0ed,0xe0ee,0xe0ef, + 0xe0f0,0xe0f1,0xe0f2,0xe0f3,0xe0f4,0xe0f5,0xe0f6,0xe0f7, + 0xe0f8,0xe0f9,0xe0fa,0xe0fb,0xe0fc,0xe0fd,0xe0fe,0xe0ff, + 0xe100,0xe101,0xe102,0xe103,0xe104,0xe105,0xe106,0xe107, + 0xe108,0xe109,0xe10a,0xe10b,0xe10c,0xe10d,0xe10e,0xe10f, + 0xe110,0xe111,0xe112,0xe113,0xe114,0xe115,0xe116,0xe117, + 0xe118,0xe119,0xe11a,0xe11b,0xe11c,0xe11d,0xe11e,0xe11f, + 0xe120,0xe121,0xe122,0xe123,0xe124,0xe125,0xe126,0xe127, + 0xe128,0xe129,0xe12a,0xe12b,0xe12c,0xe12d,0xe12e,0xe12f, + 0xe130,0xe131,0xe132,0xe133,0xe134,0xe135,0xe136,0xe137, + 0xe138,0xe139,0xe13a,0xe13b,0xe13c,0xe13d,0xe13e,0xe13f, + 0xe140,0xe141,0xe142,0xe143,0xe144,0xe145,0xe146,0xe147, + 0xe148,0xe149,0xe14a,0xe14b,0xe14c,0xe14d,0xe14e,0xe14f, + 0xe150,0xe151,0xe152,0xe153,0xe154,0xe155,0xe156,0xe157, + 0xe158,0xe159,0xe15a,0xe15b,0xe15c,0xe15d,0xe15e,0xe15f, + 0xe160,0xe161,0xe162,0xe163,0xe164,0xe165,0xe166,0xe167, + 0xe168,0xe169,0xe16a,0xe16b,0xe16c,0xe16d,0xe16e,0xe16f, + 0xe170,0xe171,0xe172,0xe173,0xe174,0xe175,0xe176,0xe177, + 0xe178,0xe179,0xe17a,0xe17b,0xe17c,0xe17d,0xe17e,0xe17f, + 0xe180,0xe181,0xe182,0xe183,0xe184,0xe185,0xe186,0xe187, + 0xe188,0xe189,0xe18a,0xe18b,0xe18c,0xe18d,0xe18e,0xe18f, + 0xe190,0xe191,0xe192,0xe193,0xe194,0xe195,0xe196,0xe197, + 0xe198,0xe199,0xe19a,0xe19b,0xe19c,0xe19d,0xe19e,0xe19f, + 0xe1a0,0xe1a1,0xe1a2,0xe1a3,0xe1a4,0xe1a5,0xe1a6,0xe1a7, + 0xe1a8,0xe1a9,0xe1aa,0xe1ab,0xe1ac,0xe1ad,0xe1ae,0xe1af, + 0xe1b0,0xe1b1,0xe1b2,0xe1b3,0xe1b4,0xe1b5,0xe1b6,0xe1b7, + 0xe1b8,0xe1b9,0xe1ba,0xe1bb,0xe1bc,0xe1bd,0xe1be,0xe1bf, + 0xe1c0,0xe1c1,0xe1c2,0xe1c3,0xe1c4,0xe1c5,0xe1c6,0xe1c7, + 0xe1c8,0xe1c9,0xe1ca,0xe1cb,0xe1cc,0xe1cd,0xe1ce,0xe1cf, + 0xe1d0,0xe1d1,0xe1d2,0xe1d3,0xe1d4,0xe1d5,0xe1d6,0xe1d7, + 0xe1d8,0xe1d9,0xe1da,0xe1db,0xe1dc,0xe1dd,0xe1de,0xe1df, + 0xe1e0,0xe1e1,0xe1e2,0xe1e3,0xe1e4,0xe1e5,0xe1e6,0xe1e7, + 0xe1e8,0xe1e9,0xe1ea,0xe1eb,0xe1ec,0xe1ed,0xe1ee,0xe1ef, + 0xe1f0,0xe1f1,0xe1f2,0xe1f3,0xe1f4,0xe1f5,0xe1f6,0xe1f7, + 0xe1f8,0xe1f9,0xe1fa,0xe1fb,0xe1fc,0xe1fd,0xe1fe,0xe1ff, + 0xe200,0xe201,0xe202,0xe203,0xe204,0xe205,0xe206,0xe207, + 0xe208,0xe209,0xe20a,0xe20b,0xe20c,0xe20d,0xe20e,0xe20f, + 0xe210,0xe211,0xe212,0xe213,0xe214,0xe215,0xe216,0xe217, + 0xe218,0xe219,0xe21a,0xe21b,0xe21c,0xe21d,0xe21e,0xe21f, + 0xe220,0xe221,0xe222,0xe223,0xe224,0xe225,0xe226,0xe227, + 0xe228,0xe229,0xe22a,0xe22b,0xe22c,0xe22d,0xe22e,0xe22f, + 0xe230,0xe231,0xe232,0xe233,0xe234,0xe235,0xe236,0xe237, + 0xe238,0xe239,0xe23a,0xe23b,0xe23c,0xe23d,0xe23e,0xe23f, + 0xe240,0xe241,0xe242,0xe243,0xe244,0xe245,0xe246,0xe247, + 0xe248,0xe249,0xe24a,0xe24b,0xe24c,0xe24d,0xe24e,0xe24f, + 0xe250,0xe251,0xe252,0xe253,0xe254,0xe255,0xe256,0xe257, + 0xe258,0xe259,0xe25a,0xe25b,0xe25c,0xe25d,0xe25e,0xe25f, + 0xe260,0xe261,0xe262,0xe263,0xe264,0xe265,0xe266,0xe267, + 0xe268,0xe269,0xe26a,0xe26b,0xe26c,0xe26d,0xe26e,0xe26f, + 0xe270,0xe271,0xe272,0xe273,0xe274,0xe275,0xe276,0xe277, + 0xe278,0xe279,0xe27a,0xe27b,0xe27c,0xe27d,0xe27e,0xe27f, + 0xe280,0xe281,0xe282,0xe283,0xe284,0xe285,0xe286,0xe287, + 0xe288,0xe289,0xe28a,0xe28b,0xe28c,0xe28d,0xe28e,0xe28f, + 0xe290,0xe291,0xe292,0xe293,0xe294,0xe295,0xe296,0xe297, + 0xe298,0xe299,0xe29a,0xe29b,0xe29c,0xe29d,0xe29e,0xe29f, + 0xe2a0,0xe2a1,0xe2a2,0xe2a3,0xe2a4,0xe2a5,0xe2a6,0xe2a7, + 0xe2a8,0xe2a9,0xe2aa,0xe2ab,0xe2ac,0xe2ad,0xe2ae,0xe2af, + 0xe2b0,0xe2b1,0xe2b2,0xe2b3,0xe2b4,0xe2b5,0xe2b6,0xe2b7, + 0xe2b8,0xe2b9,0xe2ba,0xe2bb,0xe2bc,0xe2bd,0xe2be,0xe2bf, + 0xe2c0,0xe2c1,0xe2c2,0xe2c3,0xe2c4,0xe2c5,0xe2c6,0xe2c7, + 0xe2c8,0xe2c9,0xe2ca,0xe2cb,0xe2cc,0xe2cd,0xe2ce,0xe2cf, + 0xe2d0,0xe2d1,0xe2d2,0xe2d3,0xe2d4,0xe2d5,0xe2d6,0xe2d7, + 0xe2d8,0xe2d9,0xe2da,0xe2db,0xe2dc,0xe2dd,0xe2de,0xe2df, + 0xe2e0,0xe2e1,0xe2e2,0xe2e3,0xe2e4,0xe2e5,0xe2e6,0xe2e7, + 0xe2e8,0xe2e9,0xe2ea,0xe2eb,0xe2ec,0xe2ed,0xe2ee,0xe2ef, + 0xe2f0,0xe2f1,0xe2f2,0xe2f3,0xe2f4,0xe2f5,0xe2f6,0xe2f7, + 0xe2f8,0xe2f9,0xe2fa,0xe2fb,0xe2fc,0xe2fd,0xe2fe,0xe2ff, + 0xe300,0xe301,0xe302,0xe303,0xe304,0xe305,0xe306,0xe307, + 0xe308,0xe309,0xe30a,0xe30b,0xe30c,0xe30d,0xe30e,0xe30f, + 0xe310,0xe311,0xe312,0xe313,0xe314,0xe315,0xe316,0xe317, + 0xe318,0xe319,0xe31a,0xe31b,0xe31c,0xe31d,0xe31e,0xe31f, + 0xe320,0xe321,0xe322,0xe323,0xe324,0xe325,0xe326,0xe327, + 0xe328,0xe329,0xe32a,0xe32b,0xe32c,0xe32d,0xe32e,0xe32f, + 0xe330,0xe331,0xe332,0xe333,0xe334,0xe335,0xe336,0xe337, + 0xe338,0xe339,0xe33a,0xe33b,0xe33c,0xe33d,0xe33e,0xe33f, + 0xe340,0xe341,0xe342,0xe343,0xe344,0xe345,0xe346,0xe347, + 0xe348,0xe349,0xe34a,0xe34b,0xe34c,0xe34d,0xe34e,0xe34f, + 0xe350,0xe351,0xe352,0xe353,0xe354,0xe355,0xe356,0xe357, + 0xe358,0xe359,0xe35a,0xe35b,0xe35c,0xe35d,0xe35e,0xe35f, + 0xe360,0xe361,0xe362,0xe363,0xe364,0xe365,0xe366,0xe367, + 0xe368,0xe369,0xe36a,0xe36b,0xe36c,0xe36d,0xe36e,0xe36f, + 0xe370,0xe371,0xe372,0xe373,0xe374,0xe375,0xe376,0xe377, + 0xe378,0xe379,0xe37a,0xe37b,0xe37c,0xe37d,0xe37e,0xe37f, + 0xe380,0xe381,0xe382,0xe383,0xe384,0xe385,0xe386,0xe387, + 0xe388,0xe389,0xe38a,0xe38b,0xe38c,0xe38d,0xe38e,0xe38f, + 0xe390,0xe391,0xe392,0xe393,0xe394,0xe395,0xe396,0xe397, + 0xe398,0xe399,0xe39a,0xe39b,0xe39c,0xe39d,0xe39e,0xe39f, + 0xe3a0,0xe3a1,0xe3a2,0xe3a3,0xe3a4,0xe3a5,0xe3a6,0xe3a7, + 0xe3a8,0xe3a9,0xe3aa,0xe3ab,0xe3ac,0xe3ad,0xe3ae,0xe3af, + 0xe3b0,0xe3b1,0xe3b2,0xe3b3,0xe3b4,0xe3b5,0xe3b6,0xe3b7, + 0xe3b8,0xe3b9,0xe3ba,0xe3bb,0xe3bc,0xe3bd,0xe3be,0xe3bf, + 0xe3c0,0xe3c1,0xe3c2,0xe3c3,0xe3c4,0xe3c5,0xe3c6,0xe3c7, + 0xe3c8,0xe3c9,0xe3ca,0xe3cb,0xe3cc,0xe3cd,0xe3ce,0xe3cf, + 0xe3d0,0xe3d1,0xe3d2,0xe3d3,0xe3d4,0xe3d5,0xe3d6,0xe3d7, + 0xe3d8,0xe3d9,0xe3da,0xe3db,0xe3dc,0xe3dd,0xe3de,0xe3df, + 0xe3e0,0xe3e1,0xe3e2,0xe3e3,0xe3e4,0xe3e5,0xe3e6,0xe3e7, + 0xe3e8,0xe3e9,0xe3ea,0xe3eb,0xe3ec,0xe3ed,0xe3ee,0xe3ef, + 0xe3f0,0xe3f1,0xe3f2,0xe3f3,0xe3f4,0xe3f5,0xe3f6,0xe3f7, + 0xe3f8,0xe3f9,0xe3fa,0xe3fb,0xe3fc,0xe3fd,0xe3fe,0xe3ff, + 0xe400,0xe401,0xe402,0xe403,0xe404,0xe405,0xe406,0xe407, + 0xe408,0xe409,0xe40a,0xe40b,0xe40c,0xe40d,0xe40e,0xe40f, + 0xe410,0xe411,0xe412,0xe413,0xe414,0xe415,0xe416,0xe417, + 0xe418,0xe419,0xe41a,0xe41b,0xe41c,0xe41d,0xe41e,0xe41f, + 0xe420,0xe421,0xe422,0xe423,0xe424,0xe425,0xe426,0xe427, + 0xe428,0xe429,0xe42a,0xe42b,0xe42c,0xe42d,0xe42e,0xe42f, + 0xe430,0xe431,0xe432,0xe433,0xe434,0xe435,0xe436,0xe437, + 0xe438,0xe439,0xe43a,0xe43b,0xe43c,0xe43d,0xe43e,0xe43f, + 0xe440,0xe441,0xe442,0xe443,0xe444,0xe445,0xe446,0xe447, + 0xe448,0xe449,0xe44a,0xe44b,0xe44c,0xe44d,0xe44e,0xe44f, + 0xe450,0xe451,0xe452,0xe453,0xe454,0xe455,0xe456,0xe457, + 0xe458,0xe459,0xe45a,0xe45b,0xe45c,0xe45d,0xe45e,0xe45f, + 0xe460,0xe461,0xe462,0xe463,0xe464,0xe465,0xe466,0xe467, + 0xe468,0xe469,0xe46a,0xe46b,0xe46c,0xe46d,0xe46e,0xe46f, + 0xe470,0xe471,0xe472,0xe473,0xe474,0xe475,0xe476,0xe477, + 0xe478,0xe479,0xe47a,0xe47b,0xe47c,0xe47d,0xe47e,0xe47f, + 0xe480,0xe481,0xe482,0xe483,0xe484,0xe485,0xe486,0xe487, + 0xe488,0xe489,0xe48a,0xe48b,0xe48c,0xe48d,0xe48e,0xe48f, + 0xe490,0xe491,0xe492,0xe493,0xe494,0xe495,0xe496,0xe497, + 0xe498,0xe499,0xe49a,0xe49b,0xe49c,0xe49d,0xe49e,0xe49f, + 0xe4a0,0xe4a1,0xe4a2,0xe4a3,0xe4a4,0xe4a5,0xe4a6,0xe4a7, + 0xe4a8,0xe4a9,0xe4aa,0xe4ab,0xe4ac,0xe4ad,0xe4ae,0xe4af, + 0xe4b0,0xe4b1,0xe4b2,0xe4b3,0xe4b4,0xe4b5,0xe4b6,0xe4b7, + 0xe4b8,0xe4b9,0xe4ba,0xe4bb,0xe4bc,0xe4bd,0xe4be,0xe4bf, + 0xe4c0,0xe4c1,0xe4c2,0xe4c3,0xe4c4,0xe4c5,0xe4c6,0xe4c7, + 0xe4c8,0xe4c9,0xe4ca,0xe4cb,0xe4cc,0xe4cd,0xe4ce,0xe4cf, + 0xe4d0,0xe4d1,0xe4d2,0xe4d3,0xe4d4,0xe4d5,0xe4d6,0xe4d7, + 0xe4d8,0xe4d9,0xe4da,0xe4db,0xe4dc,0xe4dd,0xe4de,0xe4df, + 0xe4e0,0xe4e1,0xe4e2,0xe4e3,0xe4e4,0xe4e5,0xe4e6,0xe4e7, + 0xe4e8,0xe4e9,0xe4ea,0xe4eb,0xe4ec,0xe4ed,0xe4ee,0xe4ef, + 0xe4f0,0xe4f1,0xe4f2,0xe4f3,0xe4f4,0xe4f5,0xe4f6,0xe4f7, + 0xe4f8,0xe4f9,0xe4fa,0xe4fb,0xe4fc,0xe4fd,0xe4fe,0xe4ff, + 0xe500,0xe501,0xe502,0xe503,0xe504,0xe505,0xe506,0xe507, + 0xe508,0xe509,0xe50a,0xe50b,0xe50c,0xe50d,0xe50e,0xe50f, + 0xe510,0xe511,0xe512,0xe513,0xe514,0xe515,0xe516,0xe517, + 0xe518,0xe519,0xe51a,0xe51b,0xe51c,0xe51d,0xe51e,0xe51f, + 0xe520,0xe521,0xe522,0xe523,0xe524,0xe525,0xe526,0xe527, + 0xe528,0xe529,0xe52a,0xe52b,0xe52c,0xe52d,0xe52e,0xe52f, + 0xe530,0xe531,0xe532,0xe533,0xe534,0xe535,0xe536,0xe537, + 0xe538,0xe539,0xe53a,0xe53b,0xe53c,0xe53d,0xe53e,0xe53f, + 0xe540,0xe541,0xe542,0xe543,0xe544,0xe545,0xe546,0xe547, + 0xe548,0xe549,0xe54a,0xe54b,0xe54c,0xe54d,0xe54e,0xe54f, + 0xe550,0xe551,0xe552,0xe553,0xe554,0xe555,0xe556,0xe557, + 0xe558,0xe559,0xe55a,0xe55b,0xe55c,0xe55d,0xe55e,0xe55f, + 0xe560,0xe561,0xe562,0xe563,0xe564,0xe565,0xe566,0xe567, + 0xe568,0xe569,0xe56a,0xe56b,0xe56c,0xe56d,0xe56e,0xe56f, + 0xe570,0xe571,0xe572,0xe573,0xe574,0xe575,0xe576,0xe577, + 0xe578,0xe579,0xe57a,0xe57b,0xe57c,0xe57d,0xe57e,0xe57f, + 0xe580,0xe581,0xe582,0xe583,0xe584,0xe585,0xe586,0xe587, + 0xe588,0xe589,0xe58a,0xe58b,0xe58c,0xe58d,0xe58e,0xe58f, + 0xe590,0xe591,0xe592,0xe593,0xe594,0xe595,0xe596,0xe597, + 0xe598,0xe599,0xe59a,0xe59b,0xe59c,0xe59d,0xe59e,0xe59f, + 0xe5a0,0xe5a1,0xe5a2,0xe5a3,0xe5a4,0xe5a5,0xe5a6,0xe5a7, + 0xe5a8,0xe5a9,0xe5aa,0xe5ab,0xe5ac,0xe5ad,0xe5ae,0xe5af, + 0xe5b0,0xe5b1,0xe5b2,0xe5b3,0xe5b4,0xe5b5,0xe5b6,0xe5b7, + 0xe5b8,0xe5b9,0xe5ba,0xe5bb,0xe5bc,0xe5bd,0xe5be,0xe5bf, + 0xe5c0,0xe5c1,0xe5c2,0xe5c3,0xe5c4,0xe5c5,0xe5c6,0xe5c7, + 0xe5c8,0xe5c9,0xe5ca,0xe5cb,0xe5cc,0xe5cd,0xe5ce,0xe5cf, + 0xe5d0,0xe5d1,0xe5d2,0xe5d3,0xe5d4,0xe5d5,0xe5d6,0xe5d7, + 0xe5d8,0xe5d9,0xe5da,0xe5db,0xe5dc,0xe5dd,0xe5de,0xe5df, + 0xe5e0,0xe5e1,0xe5e2,0xe5e3,0xe5e4,0xe5e5,0xe5e6,0xe5e7, + 0xe5e8,0xe5e9,0xe5ea,0xe5eb,0xe5ec,0xe5ed,0xe5ee,0xe5ef, + 0xe5f0,0xe5f1,0xe5f2,0xe5f3,0xe5f4,0xe5f5,0xe5f6,0xe5f7, + 0xe5f8,0xe5f9,0xe5fa,0xe5fb,0xe5fc,0xe5fd,0xe5fe,0xe5ff, + 0xe600,0xe601,0xe602,0xe603,0xe604,0xe605,0xe606,0xe607, + 0xe608,0xe609,0xe60a,0xe60b,0xe60c,0xe60d,0xe60e,0xe60f, + 0xe610,0xe611,0xe612,0xe613,0xe614,0xe615,0xe616,0xe617, + 0xe618,0xe619,0xe61a,0xe61b,0xe61c,0xe61d,0xe61e,0xe61f, + 0xe620,0xe621,0xe622,0xe623,0xe624,0xe625,0xe626,0xe627, + 0xe628,0xe629,0xe62a,0xe62b,0xe62c,0xe62d,0xe62e,0xe62f, + 0xe630,0xe631,0xe632,0xe633,0xe634,0xe635,0xe636,0xe637, + 0xe638,0xe639,0xe63a,0xe63b,0xe63c,0xe63d,0xe63e,0xe63f, + 0xe640,0xe641,0xe642,0xe643,0xe644,0xe645,0xe646,0xe647, + 0xe648,0xe649,0xe64a,0xe64b,0xe64c,0xe64d,0xe64e,0xe64f, + 0xe650,0xe651,0xe652,0xe653,0xe654,0xe655,0xe656,0xe657, + 0xe658,0xe659,0xe65a,0xe65b,0xe65c,0xe65d,0xe65e,0xe65f, + 0xe660,0xe661,0xe662,0xe663,0xe664,0xe665,0xe666,0xe667, + 0xe668,0xe669,0xe66a,0xe66b,0xe66c,0xe66d,0xe66e,0xe66f, + 0xe670,0xe671,0xe672,0xe673,0xe674,0xe675,0xe676,0xe677, + 0xe678,0xe679,0xe67a,0xe67b,0xe67c,0xe67d,0xe67e,0xe67f, + 0xe680,0xe681,0xe682,0xe683,0xe684,0xe685,0xe686,0xe687, + 0xe688,0xe689,0xe68a,0xe68b,0xe68c,0xe68d,0xe68e,0xe68f, + 0xe690,0xe691,0xe692,0xe693,0xe694,0xe695,0xe696,0xe697, + 0xe698,0xe699,0xe69a,0xe69b,0xe69c,0xe69d,0xe69e,0xe69f, + 0xe6a0,0xe6a1,0xe6a2,0xe6a3,0xe6a4,0xe6a5,0xe6a6,0xe6a7, + 0xe6a8,0xe6a9,0xe6aa,0xe6ab,0xe6ac,0xe6ad,0xe6ae,0xe6af, + 0xe6b0,0xe6b1,0xe6b2,0xe6b3,0xe6b4,0xe6b5,0xe6b6,0xe6b7, + 0xe6b8,0xe6b9,0xe6ba,0xe6bb,0xe6bc,0xe6bd,0xe6be,0xe6bf, + 0xe6c0,0xe6c1,0xe6c2,0xe6c3,0xe6c4,0xe6c5,0xe6c6,0xe6c7, + 0xe6c8,0xe6c9,0xe6ca,0xe6cb,0xe6cc,0xe6cd,0xe6ce,0xe6cf, + 0xe6d0,0xe6d1,0xe6d2,0xe6d3,0xe6d4,0xe6d5,0xe6d6,0xe6d7, + 0xe6d8,0xe6d9,0xe6da,0xe6db,0xe6dc,0xe6dd,0xe6de,0xe6df, + 0xe6e0,0xe6e1,0xe6e2,0xe6e3,0xe6e4,0xe6e5,0xe6e6,0xe6e7, + 0xe6e8,0xe6e9,0xe6ea,0xe6eb,0xe6ec,0xe6ed,0xe6ee,0xe6ef, + 0xe6f0,0xe6f1,0xe6f2,0xe6f3,0xe6f4,0xe6f5,0xe6f6,0xe6f7, + 0xe6f8,0xe6f9,0xe6fa,0xe6fb,0xe6fc,0xe6fd,0xe6fe,0xe6ff, + 0xe700,0xe701,0xe702,0xe703,0xe704,0xe705,0xe706,0xe707, + 0xe708,0xe709,0xe70a,0xe70b,0xe70c,0xe70d,0xe70e,0xe70f, + 0xe710,0xe711,0xe712,0xe713,0xe714,0xe715,0xe716,0xe717, + 0xe718,0xe719,0xe71a,0xe71b,0xe71c,0xe71d,0xe71e,0xe71f, + 0xe720,0xe721,0xe722,0xe723,0xe724,0xe725,0xe726,0xe727, + 0xe728,0xe729,0xe72a,0xe72b,0xe72c,0xe72d,0xe72e,0xe72f, + 0xe730,0xe731,0xe732,0xe733,0xe734,0xe735,0xe736,0xe737, + 0xe738,0xe739,0xe73a,0xe73b,0xe73c,0xe73d,0xe73e,0xe73f, + 0xe740,0xe741,0xe742,0xe743,0xe744,0xe745,0xe746,0xe747, + 0xe748,0xe749,0xe74a,0xe74b,0xe74c,0xe74d,0xe74e,0xe74f, + 0xe750,0xe751,0xe752,0xe753,0xe754,0xe755,0xe756,0xe757, + 0xe758,0xe759,0xe75a,0xe75b,0xe75c,0xe75d,0xe75e,0xe75f, + 0xe760,0xe761,0xe762,0xe763,0xe764,0xe765,0xe766,0xe767, + 0xe768,0xe769,0xe76a,0xe76b,0xe76c,0xe76d,0xe76e,0xe76f, + 0xe770,0xe771,0xe772,0xe773,0xe774,0xe775,0xe776,0xe777, + 0xe778,0xe779,0xe77a,0xe77b,0xe77c,0xe77d,0xe77e,0xe77f, + 0xe780,0xe781,0xe782,0xe783,0xe784,0xe785,0xe786,0xe787, + 0xe788,0xe789,0xe78a,0xe78b,0xe78c,0xe78d,0xe78e,0xe78f, + 0xe790,0xe791,0xe792,0xe793,0xe794,0xe795,0xe796,0xe797, + 0xe798,0xe799,0xe79a,0xe79b,0xe79c,0xe79d,0xe79e,0xe79f, + 0xe7a0,0xe7a1,0xe7a2,0xe7a3,0xe7a4,0xe7a5,0xe7a6,0xe7a7, + 0xe7a8,0xe7a9,0xe7aa,0xe7ab,0xe7ac,0xe7ad,0xe7ae,0xe7af, + 0xe7b0,0xe7b1,0xe7b2,0xe7b3,0xe7b4,0xe7b5,0xe7b6,0xe7b7, + 0xe7b8,0xe7b9,0xe7ba,0xe7bb,0xe7bc,0xe7bd,0xe7be,0xe7bf, + 0xe7c0,0xe7c1,0xe7c2,0xe7c3,0xe7c4,0xe7c5,0xe7c6,0xe7c7, + 0xe7c8,0xe7c9,0xe7ca,0xe7cb,0xe7cc,0xe7cd,0xe7ce,0xe7cf, + 0xe7d0,0xe7d1,0xe7d2,0xe7d3,0xe7d4,0xe7d5,0xe7d6,0xe7d7, + 0xe7d8,0xe7d9,0xe7da,0xe7db,0xe7dc,0xe7dd,0xe7de,0xe7df, + 0xe7e0,0xe7e1,0xe7e2,0xe7e3,0xe7e4,0xe7e5,0xe7e6,0xe7e7, + 0xe7e8,0xe7e9,0xe7ea,0xe7eb,0xe7ec,0xe7ed,0xe7ee,0xe7ef, + 0xe7f0,0xe7f1,0xe7f2,0xe7f3,0xe7f4,0xe7f5,0xe7f6,0xe7f7, + 0xe7f8,0xe7f9,0xe7fa,0xe7fb,0xe7fc,0xe7fd,0xe7fe,0xe7ff, + 0xe800,0xe801,0xe802,0xe803,0xe804,0xe805,0xe806,0xe807, + 0xe808,0xe809,0xe80a,0xe80b,0xe80c,0xe80d,0xe80e,0xe80f, + 0xe810,0xe811,0xe812,0xe813,0xe814,0xe815,0xe816,0xe817, + 0xe818,0xe819,0xe81a,0xe81b,0xe81c,0xe81d,0xe81e,0xe81f, + 0xe820,0xe821,0xe822,0xe823,0xe824,0xe825,0xe826,0xe827, + 0xe828,0xe829,0xe82a,0xe82b,0xe82c,0xe82d,0xe82e,0xe82f, + 0xe830,0xe831,0xe832,0xe833,0xe834,0xe835,0xe836,0xe837, + 0xe838,0xe839,0xe83a,0xe83b,0xe83c,0xe83d,0xe83e,0xe83f, + 0xe840,0xe841,0xe842,0xe843,0xe844,0xe845,0xe846,0xe847, + 0xe848,0xe849,0xe84a,0xe84b,0xe84c,0xe84d,0xe84e,0xe84f, + 0xe850,0xe851,0xe852,0xe853,0xe854,0xe855,0xe856,0xe857, + 0xe858,0xe859,0xe85a,0xe85b,0xe85c,0xe85d,0xe85e,0xe85f, + 0xe860,0xe861,0xe862,0xe863,0xe864,0xe865,0xe866,0xe867, + 0xe868,0xe869,0xe86a,0xe86b,0xe86c,0xe86d,0xe86e,0xe86f, + 0xe870,0xe871,0xe872,0xe873,0xe874,0xe875,0xe876,0xe877, + 0xe878,0xe879,0xe87a,0xe87b,0xe87c,0xe87d,0xe87e,0xe87f, + 0xe880,0xe881,0xe882,0xe883,0xe884,0xe885,0xe886,0xe887, + 0xe888,0xe889,0xe88a,0xe88b,0xe88c,0xe88d,0xe88e,0xe88f, + 0xe890,0xe891,0xe892,0xe893,0xe894,0xe895,0xe896,0xe897, + 0xe898,0xe899,0xe89a,0xe89b,0xe89c,0xe89d,0xe89e,0xe89f, + 0xe8a0,0xe8a1,0xe8a2,0xe8a3,0xe8a4,0xe8a5,0xe8a6,0xe8a7, + 0xe8a8,0xe8a9,0xe8aa,0xe8ab,0xe8ac,0xe8ad,0xe8ae,0xe8af, + 0xe8b0,0xe8b1,0xe8b2,0xe8b3,0xe8b4,0xe8b5,0xe8b6,0xe8b7, + 0xe8b8,0xe8b9,0xe8ba,0xe8bb,0xe8bc,0xe8bd,0xe8be,0xe8bf, + 0xe8c0,0xe8c1,0xe8c2,0xe8c3,0xe8c4,0xe8c5,0xe8c6,0xe8c7, + 0xe8c8,0xe8c9,0xe8ca,0xe8cb,0xe8cc,0xe8cd,0xe8ce,0xe8cf, + 0xe8d0,0xe8d1,0xe8d2,0xe8d3,0xe8d4,0xe8d5,0xe8d6,0xe8d7, + 0xe8d8,0xe8d9,0xe8da,0xe8db,0xe8dc,0xe8dd,0xe8de,0xe8df, + 0xe8e0,0xe8e1,0xe8e2,0xe8e3,0xe8e4,0xe8e5,0xe8e6,0xe8e7, + 0xe8e8,0xe8e9,0xe8ea,0xe8eb,0xe8ec,0xe8ed,0xe8ee,0xe8ef, + 0xe8f0,0xe8f1,0xe8f2,0xe8f3,0xe8f4,0xe8f5,0xe8f6,0xe8f7, + 0xe8f8,0xe8f9,0xe8fa,0xe8fb,0xe8fc,0xe8fd,0xe8fe,0xe8ff, + 0xe900,0xe901,0xe902,0xe903,0xe904,0xe905,0xe906,0xe907, + 0xe908,0xe909,0xe90a,0xe90b,0xe90c,0xe90d,0xe90e,0xe90f, + 0xe910,0xe911,0xe912,0xe913,0xe914,0xe915,0xe916,0xe917, + 0xe918,0xe919,0xe91a,0xe91b,0xe91c,0xe91d,0xe91e,0xe91f, + 0xe920,0xe921,0xe922,0xe923,0xe924,0xe925,0xe926,0xe927, + 0xe928,0xe929,0xe92a,0xe92b,0xe92c,0xe92d,0xe92e,0xe92f, + 0xe930,0xe931,0xe932,0xe933,0xe934,0xe935,0xe936,0xe937, + 0xe938,0xe939,0xe93a,0xe93b,0xe93c,0xe93d,0xe93e,0xe93f, + 0xe940,0xe941,0xe942,0xe943,0xe944,0xe945,0xe946,0xe947, + 0xe948,0xe949,0xe94a,0xe94b,0xe94c,0xe94d,0xe94e,0xe94f, + 0xe950,0xe951,0xe952,0xe953,0xe954,0xe955,0xe956,0xe957, + 0xe958,0xe959,0xe95a,0xe95b,0xe95c,0xe95d,0xe95e,0xe95f, + 0xe960,0xe961,0xe962,0xe963,0xe964,0xe965,0xe966,0xe967, + 0xe968,0xe969,0xe96a,0xe96b,0xe96c,0xe96d,0xe96e,0xe96f, + 0xe970,0xe971,0xe972,0xe973,0xe974,0xe975,0xe976,0xe977, + 0xe978,0xe979,0xe97a,0xe97b,0xe97c,0xe97d,0xe97e,0xe97f, + 0xe980,0xe981,0xe982,0xe983,0xe984,0xe985,0xe986,0xe987, + 0xe988,0xe989,0xe98a,0xe98b,0xe98c,0xe98d,0xe98e,0xe98f, + 0xe990,0xe991,0xe992,0xe993,0xe994,0xe995,0xe996,0xe997, + 0xe998,0xe999,0xe99a,0xe99b,0xe99c,0xe99d,0xe99e,0xe99f, + 0xe9a0,0xe9a1,0xe9a2,0xe9a3,0xe9a4,0xe9a5,0xe9a6,0xe9a7, + 0xe9a8,0xe9a9,0xe9aa,0xe9ab,0xe9ac,0xe9ad,0xe9ae,0xe9af, + 0xe9b0,0xe9b1,0xe9b2,0xe9b3,0xe9b4,0xe9b5,0xe9b6,0xe9b7, + 0xe9b8,0xe9b9,0xe9ba,0xe9bb,0xe9bc,0xe9bd,0xe9be,0xe9bf, + 0xe9c0,0xe9c1,0xe9c2,0xe9c3,0xe9c4,0xe9c5,0xe9c6,0xe9c7, + 0xe9c8,0xe9c9,0xe9ca,0xe9cb,0xe9cc,0xe9cd,0xe9ce,0xe9cf, + 0xe9d0,0xe9d1,0xe9d2,0xe9d3,0xe9d4,0xe9d5,0xe9d6,0xe9d7, + 0xe9d8,0xe9d9,0xe9da,0xe9db,0xe9dc,0xe9dd,0xe9de,0xe9df, + 0xe9e0,0xe9e1,0xe9e2,0xe9e3,0xe9e4,0xe9e5,0xe9e6,0xe9e7, + 0xe9e8,0xe9e9,0xe9ea,0xe9eb,0xe9ec,0xe9ed,0xe9ee,0xe9ef, + 0xe9f0,0xe9f1,0xe9f2,0xe9f3,0xe9f4,0xe9f5,0xe9f6,0xe9f7, + 0xe9f8,0xe9f9,0xe9fa,0xe9fb,0xe9fc,0xe9fd,0xe9fe,0xe9ff, + 0xea00,0xea01,0xea02,0xea03,0xea04,0xea05,0xea06,0xea07, + 0xea08,0xea09,0xea0a,0xea0b,0xea0c,0xea0d,0xea0e,0xea0f, + 0xea10,0xea11,0xea12,0xea13,0xea14,0xea15,0xea16,0xea17, + 0xea18,0xea19,0xea1a,0xea1b,0xea1c,0xea1d,0xea1e,0xea1f, + 0xea20,0xea21,0xea22,0xea23,0xea24,0xea25,0xea26,0xea27, + 0xea28,0xea29,0xea2a,0xea2b,0xea2c,0xea2d,0xea2e,0xea2f, + 0xea30,0xea31,0xea32,0xea33,0xea34,0xea35,0xea36,0xea37, + 0xea38,0xea39,0xea3a,0xea3b,0xea3c,0xea3d,0xea3e,0xea3f, + 0xea40,0xea41,0xea42,0xea43,0xea44,0xea45,0xea46,0xea47, + 0xea48,0xea49,0xea4a,0xea4b,0xea4c,0xea4d,0xea4e,0xea4f, + 0xea50,0xea51,0xea52,0xea53,0xea54,0xea55,0xea56,0xea57, + 0xea58,0xea59,0xea5a,0xea5b,0xea5c,0xea5d,0xea5e,0xea5f, + 0xea60,0xea61,0xea62,0xea63,0xea64,0xea65,0xea66,0xea67, + 0xea68,0xea69,0xea6a,0xea6b,0xea6c,0xea6d,0xea6e,0xea6f, + 0xea70,0xea71,0xea72,0xea73,0xea74,0xea75,0xea76,0xea77, + 0xea78,0xea79,0xea7a,0xea7b,0xea7c,0xea7d,0xea7e,0xea7f, + 0xea80,0xea81,0xea82,0xea83,0xea84,0xea85,0xea86,0xea87, + 0xea88,0xea89,0xea8a,0xea8b,0xea8c,0xea8d,0xea8e,0xea8f, + 0xea90,0xea91,0xea92,0xea93,0xea94,0xea95,0xea96,0xea97, + 0xea98,0xea99,0xea9a,0xea9b,0xea9c,0xea9d,0xea9e,0xea9f, + 0xeaa0,0xeaa1,0xeaa2,0xeaa3,0xeaa4,0xeaa5,0xeaa6,0xeaa7, + 0xeaa8,0xeaa9,0xeaaa,0xeaab,0xeaac,0xeaad,0xeaae,0xeaaf, + 0xeab0,0xeab1,0xeab2,0xeab3,0xeab4,0xeab5,0xeab6,0xeab7, + 0xeab8,0xeab9,0xeaba,0xeabb,0xeabc,0xeabd,0xeabe,0xeabf, + 0xeac0,0xeac1,0xeac2,0xeac3,0xeac4,0xeac5,0xeac6,0xeac7, + 0xeac8,0xeac9,0xeaca,0xeacb,0xeacc,0xeacd,0xeace,0xeacf, + 0xead0,0xead1,0xead2,0xead3,0xead4,0xead5,0xead6,0xead7, + 0xead8,0xead9,0xeada,0xeadb,0xeadc,0xeadd,0xeade,0xeadf, + 0xeae0,0xeae1,0xeae2,0xeae3,0xeae4,0xeae5,0xeae6,0xeae7, + 0xeae8,0xeae9,0xeaea,0xeaeb,0xeaec,0xeaed,0xeaee,0xeaef, + 0xeaf0,0xeaf1,0xeaf2,0xeaf3,0xeaf4,0xeaf5,0xeaf6,0xeaf7, + 0xeaf8,0xeaf9,0xeafa,0xeafb,0xeafc,0xeafd,0xeafe,0xeaff, + 0xeb00,0xeb01,0xeb02,0xeb03,0xeb04,0xeb05,0xeb06,0xeb07, + 0xeb08,0xeb09,0xeb0a,0xeb0b,0xeb0c,0xeb0d,0xeb0e,0xeb0f, + 0xeb10,0xeb11,0xeb12,0xeb13,0xeb14,0xeb15,0xeb16,0xeb17, + 0xeb18,0xeb19,0xeb1a,0xeb1b,0xeb1c,0xeb1d,0xeb1e,0xeb1f, + 0xeb20,0xeb21,0xeb22,0xeb23,0xeb24,0xeb25,0xeb26,0xeb27, + 0xeb28,0xeb29,0xeb2a,0xeb2b,0xeb2c,0xeb2d,0xeb2e,0xeb2f, + 0xeb30,0xeb31,0xeb32,0xeb33,0xeb34,0xeb35,0xeb36,0xeb37, + 0xeb38,0xeb39,0xeb3a,0xeb3b,0xeb3c,0xeb3d,0xeb3e,0xeb3f, + 0xeb40,0xeb41,0xeb42,0xeb43,0xeb44,0xeb45,0xeb46,0xeb47, + 0xeb48,0xeb49,0xeb4a,0xeb4b,0xeb4c,0xeb4d,0xeb4e,0xeb4f, + 0xeb50,0xeb51,0xeb52,0xeb53,0xeb54,0xeb55,0xeb56,0xeb57, + 0xeb58,0xeb59,0xeb5a,0xeb5b,0xeb5c,0xeb5d,0xeb5e,0xeb5f, + 0xeb60,0xeb61,0xeb62,0xeb63,0xeb64,0xeb65,0xeb66,0xeb67, + 0xeb68,0xeb69,0xeb6a,0xeb6b,0xeb6c,0xeb6d,0xeb6e,0xeb6f, + 0xeb70,0xeb71,0xeb72,0xeb73,0xeb74,0xeb75,0xeb76,0xeb77, + 0xeb78,0xeb79,0xeb7a,0xeb7b,0xeb7c,0xeb7d,0xeb7e,0xeb7f, + 0xeb80,0xeb81,0xeb82,0xeb83,0xeb84,0xeb85,0xeb86,0xeb87, + 0xeb88,0xeb89,0xeb8a,0xeb8b,0xeb8c,0xeb8d,0xeb8e,0xeb8f, + 0xeb90,0xeb91,0xeb92,0xeb93,0xeb94,0xeb95,0xeb96,0xeb97, + 0xeb98,0xeb99,0xeb9a,0xeb9b,0xeb9c,0xeb9d,0xeb9e,0xeb9f, + 0xeba0,0xeba1,0xeba2,0xeba3,0xeba4,0xeba5,0xeba6,0xeba7, + 0xeba8,0xeba9,0xebaa,0xebab,0xebac,0xebad,0xebae,0xebaf, + 0xebb0,0xebb1,0xebb2,0xebb3,0xebb4,0xebb5,0xebb6,0xebb7, + 0xebb8,0xebb9,0xebba,0xebbb,0xebbc,0xebbd,0xebbe,0xebbf, + 0xebc0,0xebc1,0xebc2,0xebc3,0xebc4,0xebc5,0xebc6,0xebc7, + 0xebc8,0xebc9,0xebca,0xebcb,0xebcc,0xebcd,0xebce,0xebcf, + 0xebd0,0xebd1,0xebd2,0xebd3,0xebd4,0xebd5,0xebd6,0xebd7, + 0xebd8,0xebd9,0xebda,0xebdb,0xebdc,0xebdd,0xebde,0xebdf, + 0xebe0,0xebe1,0xebe2,0xebe3,0xebe4,0xebe5,0xebe6,0xebe7, + 0xebe8,0xebe9,0xebea,0xebeb,0xebec,0xebed,0xebee,0xebef, + 0xebf0,0xebf1,0xebf2,0xebf3,0xebf4,0xebf5,0xebf6,0xebf7, + 0xebf8,0xebf9,0xebfa,0xebfb,0xebfc,0xebfd,0xebfe,0xebff, + 0xec00,0xec01,0xec02,0xec03,0xec04,0xec05,0xec06,0xec07, + 0xec08,0xec09,0xec0a,0xec0b,0xec0c,0xec0d,0xec0e,0xec0f, + 0xec10,0xec11,0xec12,0xec13,0xec14,0xec15,0xec16,0xec17, + 0xec18,0xec19,0xec1a,0xec1b,0xec1c,0xec1d,0xec1e,0xec1f, + 0xec20,0xec21,0xec22,0xec23,0xec24,0xec25,0xec26,0xec27, + 0xec28,0xec29,0xec2a,0xec2b,0xec2c,0xec2d,0xec2e,0xec2f, + 0xec30,0xec31,0xec32,0xec33,0xec34,0xec35,0xec36,0xec37, + 0xec38,0xec39,0xec3a,0xec3b,0xec3c,0xec3d,0xec3e,0xec3f, + 0xec40,0xec41,0xec42,0xec43,0xec44,0xec45,0xec46,0xec47, + 0xec48,0xec49,0xec4a,0xec4b,0xec4c,0xec4d,0xec4e,0xec4f, + 0xec50,0xec51,0xec52,0xec53,0xec54,0xec55,0xec56,0xec57, + 0xec58,0xec59,0xec5a,0xec5b,0xec5c,0xec5d,0xec5e,0xec5f, + 0xec60,0xec61,0xec62,0xec63,0xec64,0xec65,0xec66,0xec67, + 0xec68,0xec69,0xec6a,0xec6b,0xec6c,0xec6d,0xec6e,0xec6f, + 0xec70,0xec71,0xec72,0xec73,0xec74,0xec75,0xec76,0xec77, + 0xec78,0xec79,0xec7a,0xec7b,0xec7c,0xec7d,0xec7e,0xec7f, + 0xec80,0xec81,0xec82,0xec83,0xec84,0xec85,0xec86,0xec87, + 0xec88,0xec89,0xec8a,0xec8b,0xec8c,0xec8d,0xec8e,0xec8f, + 0xec90,0xec91,0xec92,0xec93,0xec94,0xec95,0xec96,0xec97, + 0xec98,0xec99,0xec9a,0xec9b,0xec9c,0xec9d,0xec9e,0xec9f, + 0xeca0,0xeca1,0xeca2,0xeca3,0xeca4,0xeca5,0xeca6,0xeca7, + 0xeca8,0xeca9,0xecaa,0xecab,0xecac,0xecad,0xecae,0xecaf, + 0xecb0,0xecb1,0xecb2,0xecb3,0xecb4,0xecb5,0xecb6,0xecb7, + 0xecb8,0xecb9,0xecba,0xecbb,0xecbc,0xecbd,0xecbe,0xecbf, + 0xecc0,0xecc1,0xecc2,0xecc3,0xecc4,0xecc5,0xecc6,0xecc7, + 0xecc8,0xecc9,0xecca,0xeccb,0xeccc,0xeccd,0xecce,0xeccf, + 0xecd0,0xecd1,0xecd2,0xecd3,0xecd4,0xecd5,0xecd6,0xecd7, + 0xecd8,0xecd9,0xecda,0xecdb,0xecdc,0xecdd,0xecde,0xecdf, + 0xece0,0xece1,0xece2,0xece3,0xece4,0xece5,0xece6,0xece7, + 0xece8,0xece9,0xecea,0xeceb,0xecec,0xeced,0xecee,0xecef, + 0xecf0,0xecf1,0xecf2,0xecf3,0xecf4,0xecf5,0xecf6,0xecf7, + 0xecf8,0xecf9,0xecfa,0xecfb,0xecfc,0xecfd,0xecfe,0xecff, + 0xed00,0xed01,0xed02,0xed03,0xed04,0xed05,0xed06,0xed07, + 0xed08,0xed09,0xed0a,0xed0b,0xed0c,0xed0d,0xed0e,0xed0f, + 0xed10,0xed11,0xed12,0xed13,0xed14,0xed15,0xed16,0xed17, + 0xed18,0xed19,0xed1a,0xed1b,0xed1c,0xed1d,0xed1e,0xed1f, + 0xed20,0xed21,0xed22,0xed23,0xed24,0xed25,0xed26,0xed27, + 0xed28,0xed29,0xed2a,0xed2b,0xed2c,0xed2d,0xed2e,0xed2f, + 0xed30,0xed31,0xed32,0xed33,0xed34,0xed35,0xed36,0xed37, + 0xed38,0xed39,0xed3a,0xed3b,0xed3c,0xed3d,0xed3e,0xed3f, + 0xed40,0xed41,0xed42,0xed43,0xed44,0xed45,0xed46,0xed47, + 0xed48,0xed49,0xed4a,0xed4b,0xed4c,0xed4d,0xed4e,0xed4f, + 0xed50,0xed51,0xed52,0xed53,0xed54,0xed55,0xed56,0xed57, + 0xed58,0xed59,0xed5a,0xed5b,0xed5c,0xed5d,0xed5e,0xed5f, + 0xed60,0xed61,0xed62,0xed63,0xed64,0xed65,0xed66,0xed67, + 0xed68,0xed69,0xed6a,0xed6b,0xed6c,0xed6d,0xed6e,0xed6f, + 0xed70,0xed71,0xed72,0xed73,0xed74,0xed75,0xed76,0xed77, + 0xed78,0xed79,0xed7a,0xed7b,0xed7c,0xed7d,0xed7e,0xed7f, + 0xed80,0xed81,0xed82,0xed83,0xed84,0xed85,0xed86,0xed87, + 0xed88,0xed89,0xed8a,0xed8b,0xed8c,0xed8d,0xed8e,0xed8f, + 0xed90,0xed91,0xed92,0xed93,0xed94,0xed95,0xed96,0xed97, + 0xed98,0xed99,0xed9a,0xed9b,0xed9c,0xed9d,0xed9e,0xed9f, + 0xeda0,0xeda1,0xeda2,0xeda3,0xeda4,0xeda5,0xeda6,0xeda7, + 0xeda8,0xeda9,0xedaa,0xedab,0xedac,0xedad,0xedae,0xedaf, + 0xedb0,0xedb1,0xedb2,0xedb3,0xedb4,0xedb5,0xedb6,0xedb7, + 0xedb8,0xedb9,0xedba,0xedbb,0xedbc,0xedbd,0xedbe,0xedbf, + 0xedc0,0xedc1,0xedc2,0xedc3,0xedc4,0xedc5,0xedc6,0xedc7, + 0xedc8,0xedc9,0xedca,0xedcb,0xedcc,0xedcd,0xedce,0xedcf, + 0xedd0,0xedd1,0xedd2,0xedd3,0xedd4,0xedd5,0xedd6,0xedd7, + 0xedd8,0xedd9,0xedda,0xeddb,0xeddc,0xeddd,0xedde,0xeddf, + 0xede0,0xede1,0xede2,0xede3,0xede4,0xede5,0xede6,0xede7, + 0xede8,0xede9,0xedea,0xedeb,0xedec,0xeded,0xedee,0xedef, + 0xedf0,0xedf1,0xedf2,0xedf3,0xedf4,0xedf5,0xedf6,0xedf7, + 0xedf8,0xedf9,0xedfa,0xedfb,0xedfc,0xedfd,0xedfe,0xedff, + 0xee00,0xee01,0xee02,0xee03,0xee04,0xee05,0xee06,0xee07, + 0xee08,0xee09,0xee0a,0xee0b,0xee0c,0xee0d,0xee0e,0xee0f, + 0xee10,0xee11,0xee12,0xee13,0xee14,0xee15,0xee16,0xee17, + 0xee18,0xee19,0xee1a,0xee1b,0xee1c,0xee1d,0xee1e,0xee1f, + 0xee20,0xee21,0xee22,0xee23,0xee24,0xee25,0xee26,0xee27, + 0xee28,0xee29,0xee2a,0xee2b,0xee2c,0xee2d,0xee2e,0xee2f, + 0xee30,0xee31,0xee32,0xee33,0xee34,0xee35,0xee36,0xee37, + 0xee38,0xee39,0xee3a,0xee3b,0xee3c,0xee3d,0xee3e,0xee3f, + 0xee40,0xee41,0xee42,0xee43,0xee44,0xee45,0xee46,0xee47, + 0xee48,0xee49,0xee4a,0xee4b,0xee4c,0xee4d,0xee4e,0xee4f, + 0xee50,0xee51,0xee52,0xee53,0xee54,0xee55,0xee56,0xee57, + 0xee58,0xee59,0xee5a,0xee5b,0xee5c,0xee5d,0xee5e,0xee5f, + 0xee60,0xee61,0xee62,0xee63,0xee64,0xee65,0xee66,0xee67, + 0xee68,0xee69,0xee6a,0xee6b,0xee6c,0xee6d,0xee6e,0xee6f, + 0xee70,0xee71,0xee72,0xee73,0xee74,0xee75,0xee76,0xee77, + 0xee78,0xee79,0xee7a,0xee7b,0xee7c,0xee7d,0xee7e,0xee7f, + 0xee80,0xee81,0xee82,0xee83,0xee84,0xee85,0xee86,0xee87, + 0xee88,0xee89,0xee8a,0xee8b,0xee8c,0xee8d,0xee8e,0xee8f, + 0xee90,0xee91,0xee92,0xee93,0xee94,0xee95,0xee96,0xee97, + 0xee98,0xee99,0xee9a,0xee9b,0xee9c,0xee9d,0xee9e,0xee9f, + 0xeea0,0xeea1,0xeea2,0xeea3,0xeea4,0xeea5,0xeea6,0xeea7, + 0xeea8,0xeea9,0xeeaa,0xeeab,0xeeac,0xeead,0xeeae,0xeeaf, + 0xeeb0,0xeeb1,0xeeb2,0xeeb3,0xeeb4,0xeeb5,0xeeb6,0xeeb7, + 0xeeb8,0xeeb9,0xeeba,0xeebb,0xeebc,0xeebd,0xeebe,0xeebf, + 0xeec0,0xeec1,0xeec2,0xeec3,0xeec4,0xeec5,0xeec6,0xeec7, + 0xeec8,0xeec9,0xeeca,0xeecb,0xeecc,0xeecd,0xeece,0xeecf, + 0xeed0,0xeed1,0xeed2,0xeed3,0xeed4,0xeed5,0xeed6,0xeed7, + 0xeed8,0xeed9,0xeeda,0xeedb,0xeedc,0xeedd,0xeede,0xeedf, + 0xeee0,0xeee1,0xeee2,0xeee3,0xeee4,0xeee5,0xeee6,0xeee7, + 0xeee8,0xeee9,0xeeea,0xeeeb,0xeeec,0xeeed,0xeeee,0xeeef, + 0xeef0,0xeef1,0xeef2,0xeef3,0xeef4,0xeef5,0xeef6,0xeef7, + 0xeef8,0xeef9,0xeefa,0xeefb,0xeefc,0xeefd,0xeefe,0xeeff, + 0xef00,0xef01,0xef02,0xef03,0xef04,0xef05,0xef06,0xef07, + 0xef08,0xef09,0xef0a,0xef0b,0xef0c,0xef0d,0xef0e,0xef0f, + 0xef10,0xef11,0xef12,0xef13,0xef14,0xef15,0xef16,0xef17, + 0xef18,0xef19,0xef1a,0xef1b,0xef1c,0xef1d,0xef1e,0xef1f, + 0xef20,0xef21,0xef22,0xef23,0xef24,0xef25,0xef26,0xef27, + 0xef28,0xef29,0xef2a,0xef2b,0xef2c,0xef2d,0xef2e,0xef2f, + 0xef30,0xef31,0xef32,0xef33,0xef34,0xef35,0xef36,0xef37, + 0xef38,0xef39,0xef3a,0xef3b,0xef3c,0xef3d,0xef3e,0xef3f, + 0xef40,0xef41,0xef42,0xef43,0xef44,0xef45,0xef46,0xef47, + 0xef48,0xef49,0xef4a,0xef4b,0xef4c,0xef4d,0xef4e,0xef4f, + 0xef50,0xef51,0xef52,0xef53,0xef54,0xef55,0xef56,0xef57, + 0xef58,0xef59,0xef5a,0xef5b,0xef5c,0xef5d,0xef5e,0xef5f, + 0xef60,0xef61,0xef62,0xef63,0xef64,0xef65,0xef66,0xef67, + 0xef68,0xef69,0xef6a,0xef6b,0xef6c,0xef6d,0xef6e,0xef6f, + 0xef70,0xef71,0xef72,0xef73,0xef74,0xef75,0xef76,0xef77, + 0xef78,0xef79,0xef7a,0xef7b,0xef7c,0xef7d,0xef7e,0xef7f, + 0xef80,0xef81,0xef82,0xef83,0xef84,0xef85,0xef86,0xef87, + 0xef88,0xef89,0xef8a,0xef8b,0xef8c,0xef8d,0xef8e,0xef8f, + 0xef90,0xef91,0xef92,0xef93,0xef94,0xef95,0xef96,0xef97, + 0xef98,0xef99,0xef9a,0xef9b,0xef9c,0xef9d,0xef9e,0xef9f, + 0xefa0,0xefa1,0xefa2,0xefa3,0xefa4,0xefa5,0xefa6,0xefa7, + 0xefa8,0xefa9,0xefaa,0xefab,0xefac,0xefad,0xefae,0xefaf, + 0xefb0,0xefb1,0xefb2,0xefb3,0xefb4,0xefb5,0xefb6,0xefb7, + 0xefb8,0xefb9,0xefba,0xefbb,0xefbc,0xefbd,0xefbe,0xefbf, + 0xefc0,0xefc1,0xefc2,0xefc3,0xefc4,0xefc5,0xefc6,0xefc7, + 0xefc8,0xefc9,0xefca,0xefcb,0xefcc,0xefcd,0xefce,0xefcf, + 0xefd0,0xefd1,0xefd2,0xefd3,0xefd4,0xefd5,0xefd6,0xefd7, + 0xefd8,0xefd9,0xefda,0xefdb,0xefdc,0xefdd,0xefde,0xefdf, + 0xefe0,0xefe1,0xefe2,0xefe3,0xefe4,0xefe5,0xefe6,0xefe7, + 0xefe8,0xefe9,0xefea,0xefeb,0xefec,0xefed,0xefee,0xefef, + 0xeff0,0xeff1,0xeff2,0xeff3,0xeff4,0xeff5,0xeff6,0xeff7, + 0xeff8,0xeff9,0xeffa,0xeffb,0xeffc,0xeffd,0xeffe,0xefff, + 0xf000,0xf001,0xf002,0xf003,0xf004,0xf005,0xf006,0xf007, + 0xf008,0xf009,0xf00a,0xf00b,0xf00c,0xf00d,0xf00e,0xf00f, + 0xf010,0xf011,0xf012,0xf013,0xf014,0xf015,0xf016,0xf017, + 0xf018,0xf019,0xf01a,0xf01b,0xf01c,0xf01d,0xf01e,0xf01f, + 0xf020,0xf021,0xf022,0xf023,0xf024,0xf025,0xf026,0xf027, + 0xf028,0xf029,0xf02a,0xf02b,0xf02c,0xf02d,0xf02e,0xf02f, + 0xf030,0xf031,0xf032,0xf033,0xf034,0xf035,0xf036,0xf037, + 0xf038,0xf039,0xf03a,0xf03b,0xf03c,0xf03d,0xf03e,0xf03f, + 0xf040,0xf041,0xf042,0xf043,0xf044,0xf045,0xf046,0xf047, + 0xf048,0xf049,0xf04a,0xf04b,0xf04c,0xf04d,0xf04e,0xf04f, + 0xf050,0xf051,0xf052,0xf053,0xf054,0xf055,0xf056,0xf057, + 0xf058,0xf059,0xf05a,0xf05b,0xf05c,0xf05d,0xf05e,0xf05f, + 0xf060,0xf061,0xf062,0xf063,0xf064,0xf065,0xf066,0xf067, + 0xf068,0xf069,0xf06a,0xf06b,0xf06c,0xf06d,0xf06e,0xf06f, + 0xf070,0xf071,0xf072,0xf073,0xf074,0xf075,0xf076,0xf077, + 0xf078,0xf079,0xf07a,0xf07b,0xf07c,0xf07d,0xf07e,0xf07f, + 0xf080,0xf081,0xf082,0xf083,0xf084,0xf085,0xf086,0xf087, + 0xf088,0xf089,0xf08a,0xf08b,0xf08c,0xf08d,0xf08e,0xf08f, + 0xf090,0xf091,0xf092,0xf093,0xf094,0xf095,0xf096,0xf097, + 0xf098,0xf099,0xf09a,0xf09b,0xf09c,0xf09d,0xf09e,0xf09f, + 0xf0a0,0xf0a1,0xf0a2,0xf0a3,0xf0a4,0xf0a5,0xf0a6,0xf0a7, + 0xf0a8,0xf0a9,0xf0aa,0xf0ab,0xf0ac,0xf0ad,0xf0ae,0xf0af, + 0xf0b0,0xf0b1,0xf0b2,0xf0b3,0xf0b4,0xf0b5,0xf0b6,0xf0b7, + 0xf0b8,0xf0b9,0xf0ba,0xf0bb,0xf0bc,0xf0bd,0xf0be,0xf0bf, + 0xf0c0,0xf0c1,0xf0c2,0xf0c3,0xf0c4,0xf0c5,0xf0c6,0xf0c7, + 0xf0c8,0xf0c9,0xf0ca,0xf0cb,0xf0cc,0xf0cd,0xf0ce,0xf0cf, + 0xf0d0,0xf0d1,0xf0d2,0xf0d3,0xf0d4,0xf0d5,0xf0d6,0xf0d7, + 0xf0d8,0xf0d9,0xf0da,0xf0db,0xf0dc,0xf0dd,0xf0de,0xf0df, + 0xf0e0,0xf0e1,0xf0e2,0xf0e3,0xf0e4,0xf0e5,0xf0e6,0xf0e7, + 0xf0e8,0xf0e9,0xf0ea,0xf0eb,0xf0ec,0xf0ed,0xf0ee,0xf0ef, + 0xf0f0,0xf0f1,0xf0f2,0xf0f3,0xf0f4,0xf0f5,0xf0f6,0xf0f7, + 0xf0f8,0xf0f9,0xf0fa,0xf0fb,0xf0fc,0xf0fd,0xf0fe,0xf0ff, + 0xf100,0xf101,0xf102,0xf103,0xf104,0xf105,0xf106,0xf107, + 0xf108,0xf109,0xf10a,0xf10b,0xf10c,0xf10d,0xf10e,0xf10f, + 0xf110,0xf111,0xf112,0xf113,0xf114,0xf115,0xf116,0xf117, + 0xf118,0xf119,0xf11a,0xf11b,0xf11c,0xf11d,0xf11e,0xf11f, + 0xf120,0xf121,0xf122,0xf123,0xf124,0xf125,0xf126,0xf127, + 0xf128,0xf129,0xf12a,0xf12b,0xf12c,0xf12d,0xf12e,0xf12f, + 0xf130,0xf131,0xf132,0xf133,0xf134,0xf135,0xf136,0xf137, + 0xf138,0xf139,0xf13a,0xf13b,0xf13c,0xf13d,0xf13e,0xf13f, + 0xf140,0xf141,0xf142,0xf143,0xf144,0xf145,0xf146,0xf147, + 0xf148,0xf149,0xf14a,0xf14b,0xf14c,0xf14d,0xf14e,0xf14f, + 0xf150,0xf151,0xf152,0xf153,0xf154,0xf155,0xf156,0xf157, + 0xf158,0xf159,0xf15a,0xf15b,0xf15c,0xf15d,0xf15e,0xf15f, + 0xf160,0xf161,0xf162,0xf163,0xf164,0xf165,0xf166,0xf167, + 0xf168,0xf169,0xf16a,0xf16b,0xf16c,0xf16d,0xf16e,0xf16f, + 0xf170,0xf171,0xf172,0xf173,0xf174,0xf175,0xf176,0xf177, + 0xf178,0xf179,0xf17a,0xf17b,0xf17c,0xf17d,0xf17e,0xf17f, + 0xf180,0xf181,0xf182,0xf183,0xf184,0xf185,0xf186,0xf187, + 0xf188,0xf189,0xf18a,0xf18b,0xf18c,0xf18d,0xf18e,0xf18f, + 0xf190,0xf191,0xf192,0xf193,0xf194,0xf195,0xf196,0xf197, + 0xf198,0xf199,0xf19a,0xf19b,0xf19c,0xf19d,0xf19e,0xf19f, + 0xf1a0,0xf1a1,0xf1a2,0xf1a3,0xf1a4,0xf1a5,0xf1a6,0xf1a7, + 0xf1a8,0xf1a9,0xf1aa,0xf1ab,0xf1ac,0xf1ad,0xf1ae,0xf1af, + 0xf1b0,0xf1b1,0xf1b2,0xf1b3,0xf1b4,0xf1b5,0xf1b6,0xf1b7, + 0xf1b8,0xf1b9,0xf1ba,0xf1bb,0xf1bc,0xf1bd,0xf1be,0xf1bf, + 0xf1c0,0xf1c1,0xf1c2,0xf1c3,0xf1c4,0xf1c5,0xf1c6,0xf1c7, + 0xf1c8,0xf1c9,0xf1ca,0xf1cb,0xf1cc,0xf1cd,0xf1ce,0xf1cf, + 0xf1d0,0xf1d1,0xf1d2,0xf1d3,0xf1d4,0xf1d5,0xf1d6,0xf1d7, + 0xf1d8,0xf1d9,0xf1da,0xf1db,0xf1dc,0xf1dd,0xf1de,0xf1df, + 0xf1e0,0xf1e1,0xf1e2,0xf1e3,0xf1e4,0xf1e5,0xf1e6,0xf1e7, + 0xf1e8,0xf1e9,0xf1ea,0xf1eb,0xf1ec,0xf1ed,0xf1ee,0xf1ef, + 0xf1f0,0xf1f1,0xf1f2,0xf1f3,0xf1f4,0xf1f5,0xf1f6,0xf1f7, + 0xf1f8,0xf1f9,0xf1fa,0xf1fb,0xf1fc,0xf1fd,0xf1fe,0xf1ff, + 0xf200,0xf201,0xf202,0xf203,0xf204,0xf205,0xf206,0xf207, + 0xf208,0xf209,0xf20a,0xf20b,0xf20c,0xf20d,0xf20e,0xf20f, + 0xf210,0xf211,0xf212,0xf213,0xf214,0xf215,0xf216,0xf217, + 0xf218,0xf219,0xf21a,0xf21b,0xf21c,0xf21d,0xf21e,0xf21f, + 0xf220,0xf221,0xf222,0xf223,0xf224,0xf225,0xf226,0xf227, + 0xf228,0xf229,0xf22a,0xf22b,0xf22c,0xf22d,0xf22e,0xf22f, + 0xf230,0xf231,0xf232,0xf233,0xf234,0xf235,0xf236,0xf237, + 0xf238,0xf239,0xf23a,0xf23b,0xf23c,0xf23d,0xf23e,0xf23f, + 0xf240,0xf241,0xf242,0xf243,0xf244,0xf245,0xf246,0xf247, + 0xf248,0xf249,0xf24a,0xf24b,0xf24c,0xf24d,0xf24e,0xf24f, + 0xf250,0xf251,0xf252,0xf253,0xf254,0xf255,0xf256,0xf257, + 0xf258,0xf259,0xf25a,0xf25b,0xf25c,0xf25d,0xf25e,0xf25f, + 0xf260,0xf261,0xf262,0xf263,0xf264,0xf265,0xf266,0xf267, + 0xf268,0xf269,0xf26a,0xf26b,0xf26c,0xf26d,0xf26e,0xf26f, + 0xf270,0xf271,0xf272,0xf273,0xf274,0xf275,0xf276,0xf277, + 0xf278,0xf279,0xf27a,0xf27b,0xf27c,0xf27d,0xf27e,0xf27f, + 0xf280,0xf281,0xf282,0xf283,0xf284,0xf285,0xf286,0xf287, + 0xf288,0xf289,0xf28a,0xf28b,0xf28c,0xf28d,0xf28e,0xf28f, + 0xf290,0xf291,0xf292,0xf293,0xf294,0xf295,0xf296,0xf297, + 0xf298,0xf299,0xf29a,0xf29b,0xf29c,0xf29d,0xf29e,0xf29f, + 0xf2a0,0xf2a1,0xf2a2,0xf2a3,0xf2a4,0xf2a5,0xf2a6,0xf2a7, + 0xf2a8,0xf2a9,0xf2aa,0xf2ab,0xf2ac,0xf2ad,0xf2ae,0xf2af, + 0xf2b0,0xf2b1,0xf2b2,0xf2b3,0xf2b4,0xf2b5,0xf2b6,0xf2b7, + 0xf2b8,0xf2b9,0xf2ba,0xf2bb,0xf2bc,0xf2bd,0xf2be,0xf2bf, + 0xf2c0,0xf2c1,0xf2c2,0xf2c3,0xf2c4,0xf2c5,0xf2c6,0xf2c7, + 0xf2c8,0xf2c9,0xf2ca,0xf2cb,0xf2cc,0xf2cd,0xf2ce,0xf2cf, + 0xf2d0,0xf2d1,0xf2d2,0xf2d3,0xf2d4,0xf2d5,0xf2d6,0xf2d7, + 0xf2d8,0xf2d9,0xf2da,0xf2db,0xf2dc,0xf2dd,0xf2de,0xf2df, + 0xf2e0,0xf2e1,0xf2e2,0xf2e3,0xf2e4,0xf2e5,0xf2e6,0xf2e7, + 0xf2e8,0xf2e9,0xf2ea,0xf2eb,0xf2ec,0xf2ed,0xf2ee,0xf2ef, + 0xf2f0,0xf2f1,0xf2f2,0xf2f3,0xf2f4,0xf2f5,0xf2f6,0xf2f7, + 0xf2f8,0xf2f9,0xf2fa,0xf2fb,0xf2fc,0xf2fd,0xf2fe,0xf2ff, + 0xf300,0xf301,0xf302,0xf303,0xf304,0xf305,0xf306,0xf307, + 0xf308,0xf309,0xf30a,0xf30b,0xf30c,0xf30d,0xf30e,0xf30f, + 0xf310,0xf311,0xf312,0xf313,0xf314,0xf315,0xf316,0xf317, + 0xf318,0xf319,0xf31a,0xf31b,0xf31c,0xf31d,0xf31e,0xf31f, + 0xf320,0xf321,0xf322,0xf323,0xf324,0xf325,0xf326,0xf327, + 0xf328,0xf329,0xf32a,0xf32b,0xf32c,0xf32d,0xf32e,0xf32f, + 0xf330,0xf331,0xf332,0xf333,0xf334,0xf335,0xf336,0xf337, + 0xf338,0xf339,0xf33a,0xf33b,0xf33c,0xf33d,0xf33e,0xf33f, + 0xf340,0xf341,0xf342,0xf343,0xf344,0xf345,0xf346,0xf347, + 0xf348,0xf349,0xf34a,0xf34b,0xf34c,0xf34d,0xf34e,0xf34f, + 0xf350,0xf351,0xf352,0xf353,0xf354,0xf355,0xf356,0xf357, + 0xf358,0xf359,0xf35a,0xf35b,0xf35c,0xf35d,0xf35e,0xf35f, + 0xf360,0xf361,0xf362,0xf363,0xf364,0xf365,0xf366,0xf367, + 0xf368,0xf369,0xf36a,0xf36b,0xf36c,0xf36d,0xf36e,0xf36f, + 0xf370,0xf371,0xf372,0xf373,0xf374,0xf375,0xf376,0xf377, + 0xf378,0xf379,0xf37a,0xf37b,0xf37c,0xf37d,0xf37e,0xf37f, + 0xf380,0xf381,0xf382,0xf383,0xf384,0xf385,0xf386,0xf387, + 0xf388,0xf389,0xf38a,0xf38b,0xf38c,0xf38d,0xf38e,0xf38f, + 0xf390,0xf391,0xf392,0xf393,0xf394,0xf395,0xf396,0xf397, + 0xf398,0xf399,0xf39a,0xf39b,0xf39c,0xf39d,0xf39e,0xf39f, + 0xf3a0,0xf3a1,0xf3a2,0xf3a3,0xf3a4,0xf3a5,0xf3a6,0xf3a7, + 0xf3a8,0xf3a9,0xf3aa,0xf3ab,0xf3ac,0xf3ad,0xf3ae,0xf3af, + 0xf3b0,0xf3b1,0xf3b2,0xf3b3,0xf3b4,0xf3b5,0xf3b6,0xf3b7, + 0xf3b8,0xf3b9,0xf3ba,0xf3bb,0xf3bc,0xf3bd,0xf3be,0xf3bf, + 0xf3c0,0xf3c1,0xf3c2,0xf3c3,0xf3c4,0xf3c5,0xf3c6,0xf3c7, + 0xf3c8,0xf3c9,0xf3ca,0xf3cb,0xf3cc,0xf3cd,0xf3ce,0xf3cf, + 0xf3d0,0xf3d1,0xf3d2,0xf3d3,0xf3d4,0xf3d5,0xf3d6,0xf3d7, + 0xf3d8,0xf3d9,0xf3da,0xf3db,0xf3dc,0xf3dd,0xf3de,0xf3df, + 0xf3e0,0xf3e1,0xf3e2,0xf3e3,0xf3e4,0xf3e5,0xf3e6,0xf3e7, + 0xf3e8,0xf3e9,0xf3ea,0xf3eb,0xf3ec,0xf3ed,0xf3ee,0xf3ef, + 0xf3f0,0xf3f1,0xf3f2,0xf3f3,0xf3f4,0xf3f5,0xf3f6,0xf3f7, + 0xf3f8,0xf3f9,0xf3fa,0xf3fb,0xf3fc,0xf3fd,0xf3fe,0xf3ff, + 0xf400,0xf401,0xf402,0xf403,0xf404,0xf405,0xf406,0xf407, + 0xf408,0xf409,0xf40a,0xf40b,0xf40c,0xf40d,0xf40e,0xf40f, + 0xf410,0xf411,0xf412,0xf413,0xf414,0xf415,0xf416,0xf417, + 0xf418,0xf419,0xf41a,0xf41b,0xf41c,0xf41d,0xf41e,0xf41f, + 0xf420,0xf421,0xf422,0xf423,0xf424,0xf425,0xf426,0xf427, + 0xf428,0xf429,0xf42a,0xf42b,0xf42c,0xf42d,0xf42e,0xf42f, + 0xf430,0xf431,0xf432,0xf433,0xf434,0xf435,0xf436,0xf437, + 0xf438,0xf439,0xf43a,0xf43b,0xf43c,0xf43d,0xf43e,0xf43f, + 0xf440,0xf441,0xf442,0xf443,0xf444,0xf445,0xf446,0xf447, + 0xf448,0xf449,0xf44a,0xf44b,0xf44c,0xf44d,0xf44e,0xf44f, + 0xf450,0xf451,0xf452,0xf453,0xf454,0xf455,0xf456,0xf457, + 0xf458,0xf459,0xf45a,0xf45b,0xf45c,0xf45d,0xf45e,0xf45f, + 0xf460,0xf461,0xf462,0xf463,0xf464,0xf465,0xf466,0xf467, + 0xf468,0xf469,0xf46a,0xf46b,0xf46c,0xf46d,0xf46e,0xf46f, + 0xf470,0xf471,0xf472,0xf473,0xf474,0xf475,0xf476,0xf477, + 0xf478,0xf479,0xf47a,0xf47b,0xf47c,0xf47d,0xf47e,0xf47f, + 0xf480,0xf481,0xf482,0xf483,0xf484,0xf485,0xf486,0xf487, + 0xf488,0xf489,0xf48a,0xf48b,0xf48c,0xf48d,0xf48e,0xf48f, + 0xf490,0xf491,0xf492,0xf493,0xf494,0xf495,0xf496,0xf497, + 0xf498,0xf499,0xf49a,0xf49b,0xf49c,0xf49d,0xf49e,0xf49f, + 0xf4a0,0xf4a1,0xf4a2,0xf4a3,0xf4a4,0xf4a5,0xf4a6,0xf4a7, + 0xf4a8,0xf4a9,0xf4aa,0xf4ab,0xf4ac,0xf4ad,0xf4ae,0xf4af, + 0xf4b0,0xf4b1,0xf4b2,0xf4b3,0xf4b4,0xf4b5,0xf4b6,0xf4b7, + 0xf4b8,0xf4b9,0xf4ba,0xf4bb,0xf4bc,0xf4bd,0xf4be,0xf4bf, + 0xf4c0,0xf4c1,0xf4c2,0xf4c3,0xf4c4,0xf4c5,0xf4c6,0xf4c7, + 0xf4c8,0xf4c9,0xf4ca,0xf4cb,0xf4cc,0xf4cd,0xf4ce,0xf4cf, + 0xf4d0,0xf4d1,0xf4d2,0xf4d3,0xf4d4,0xf4d5,0xf4d6,0xf4d7, + 0xf4d8,0xf4d9,0xf4da,0xf4db,0xf4dc,0xf4dd,0xf4de,0xf4df, + 0xf4e0,0xf4e1,0xf4e2,0xf4e3,0xf4e4,0xf4e5,0xf4e6,0xf4e7, + 0xf4e8,0xf4e9,0xf4ea,0xf4eb,0xf4ec,0xf4ed,0xf4ee,0xf4ef, + 0xf4f0,0xf4f1,0xf4f2,0xf4f3,0xf4f4,0xf4f5,0xf4f6,0xf4f7, + 0xf4f8,0xf4f9,0xf4fa,0xf4fb,0xf4fc,0xf4fd,0xf4fe,0xf4ff, + 0xf500,0xf501,0xf502,0xf503,0xf504,0xf505,0xf506,0xf507, + 0xf508,0xf509,0xf50a,0xf50b,0xf50c,0xf50d,0xf50e,0xf50f, + 0xf510,0xf511,0xf512,0xf513,0xf514,0xf515,0xf516,0xf517, + 0xf518,0xf519,0xf51a,0xf51b,0xf51c,0xf51d,0xf51e,0xf51f, + 0xf520,0xf521,0xf522,0xf523,0xf524,0xf525,0xf526,0xf527, + 0xf528,0xf529,0xf52a,0xf52b,0xf52c,0xf52d,0xf52e,0xf52f, + 0xf530,0xf531,0xf532,0xf533,0xf534,0xf535,0xf536,0xf537, + 0xf538,0xf539,0xf53a,0xf53b,0xf53c,0xf53d,0xf53e,0xf53f, + 0xf540,0xf541,0xf542,0xf543,0xf544,0xf545,0xf546,0xf547, + 0xf548,0xf549,0xf54a,0xf54b,0xf54c,0xf54d,0xf54e,0xf54f, + 0xf550,0xf551,0xf552,0xf553,0xf554,0xf555,0xf556,0xf557, + 0xf558,0xf559,0xf55a,0xf55b,0xf55c,0xf55d,0xf55e,0xf55f, + 0xf560,0xf561,0xf562,0xf563,0xf564,0xf565,0xf566,0xf567, + 0xf568,0xf569,0xf56a,0xf56b,0xf56c,0xf56d,0xf56e,0xf56f, + 0xf570,0xf571,0xf572,0xf573,0xf574,0xf575,0xf576,0xf577, + 0xf578,0xf579,0xf57a,0xf57b,0xf57c,0xf57d,0xf57e,0xf57f, + 0xf580,0xf581,0xf582,0xf583,0xf584,0xf585,0xf586,0xf587, + 0xf588,0xf589,0xf58a,0xf58b,0xf58c,0xf58d,0xf58e,0xf58f, + 0xf590,0xf591,0xf592,0xf593,0xf594,0xf595,0xf596,0xf597, + 0xf598,0xf599,0xf59a,0xf59b,0xf59c,0xf59d,0xf59e,0xf59f, + 0xf5a0,0xf5a1,0xf5a2,0xf5a3,0xf5a4,0xf5a5,0xf5a6,0xf5a7, + 0xf5a8,0xf5a9,0xf5aa,0xf5ab,0xf5ac,0xf5ad,0xf5ae,0xf5af, + 0xf5b0,0xf5b1,0xf5b2,0xf5b3,0xf5b4,0xf5b5,0xf5b6,0xf5b7, + 0xf5b8,0xf5b9,0xf5ba,0xf5bb,0xf5bc,0xf5bd,0xf5be,0xf5bf, + 0xf5c0,0xf5c1,0xf5c2,0xf5c3,0xf5c4,0xf5c5,0xf5c6,0xf5c7, + 0xf5c8,0xf5c9,0xf5ca,0xf5cb,0xf5cc,0xf5cd,0xf5ce,0xf5cf, + 0xf5d0,0xf5d1,0xf5d2,0xf5d3,0xf5d4,0xf5d5,0xf5d6,0xf5d7, + 0xf5d8,0xf5d9,0xf5da,0xf5db,0xf5dc,0xf5dd,0xf5de,0xf5df, + 0xf5e0,0xf5e1,0xf5e2,0xf5e3,0xf5e4,0xf5e5,0xf5e6,0xf5e7, + 0xf5e8,0xf5e9,0xf5ea,0xf5eb,0xf5ec,0xf5ed,0xf5ee,0xf5ef, + 0xf5f0,0xf5f1,0xf5f2,0xf5f3,0xf5f4,0xf5f5,0xf5f6,0xf5f7, + 0xf5f8,0xf5f9,0xf5fa,0xf5fb,0xf5fc,0xf5fd,0xf5fe,0xf5ff, + 0xf600,0xf601,0xf602,0xf603,0xf604,0xf605,0xf606,0xf607, + 0xf608,0xf609,0xf60a,0xf60b,0xf60c,0xf60d,0xf60e,0xf60f, + 0xf610,0xf611,0xf612,0xf613,0xf614,0xf615,0xf616,0xf617, + 0xf618,0xf619,0xf61a,0xf61b,0xf61c,0xf61d,0xf61e,0xf61f, + 0xf620,0xf621,0xf622,0xf623,0xf624,0xf625,0xf626,0xf627, + 0xf628,0xf629,0xf62a,0xf62b,0xf62c,0xf62d,0xf62e,0xf62f, + 0xf630,0xf631,0xf632,0xf633,0xf634,0xf635,0xf636,0xf637, + 0xf638,0xf639,0xf63a,0xf63b,0xf63c,0xf63d,0xf63e,0xf63f, + 0xf640,0xf641,0xf642,0xf643,0xf644,0xf645,0xf646,0xf647, + 0xf648,0xf649,0xf64a,0xf64b,0xf64c,0xf64d,0xf64e,0xf64f, + 0xf650,0xf651,0xf652,0xf653,0xf654,0xf655,0xf656,0xf657, + 0xf658,0xf659,0xf65a,0xf65b,0xf65c,0xf65d,0xf65e,0xf65f, + 0xf660,0xf661,0xf662,0xf663,0xf664,0xf665,0xf666,0xf667, + 0xf668,0xf669,0xf66a,0xf66b,0xf66c,0xf66d,0xf66e,0xf66f, + 0xf670,0xf671,0xf672,0xf673,0xf674,0xf675,0xf676,0xf677, + 0xf678,0xf679,0xf67a,0xf67b,0xf67c,0xf67d,0xf67e,0xf67f, + 0xf680,0xf681,0xf682,0xf683,0xf684,0xf685,0xf686,0xf687, + 0xf688,0xf689,0xf68a,0xf68b,0xf68c,0xf68d,0xf68e,0xf68f, + 0xf690,0xf691,0xf692,0xf693,0xf694,0xf695,0xf696,0xf697, + 0xf698,0xf699,0xf69a,0xf69b,0xf69c,0xf69d,0xf69e,0xf69f, + 0xf6a0,0xf6a1,0xf6a2,0xf6a3,0xf6a4,0xf6a5,0xf6a6,0xf6a7, + 0xf6a8,0xf6a9,0xf6aa,0xf6ab,0xf6ac,0xf6ad,0xf6ae,0xf6af, + 0xf6b0,0xf6b1,0xf6b2,0xf6b3,0xf6b4,0xf6b5,0xf6b6,0xf6b7, + 0xf6b8,0xf6b9,0xf6ba,0xf6bb,0xf6bc,0xf6bd,0xf6be,0xf6bf, + 0xf6c0,0xf6c1,0xf6c2,0xf6c3,0xf6c4,0xf6c5,0xf6c6,0xf6c7, + 0xf6c8,0xf6c9,0xf6ca,0xf6cb,0xf6cc,0xf6cd,0xf6ce,0xf6cf, + 0xf6d0,0xf6d1,0xf6d2,0xf6d3,0xf6d4,0xf6d5,0xf6d6,0xf6d7, + 0xf6d8,0xf6d9,0xf6da,0xf6db,0xf6dc,0xf6dd,0xf6de,0xf6df, + 0xf6e0,0xf6e1,0xf6e2,0xf6e3,0xf6e4,0xf6e5,0xf6e6,0xf6e7, + 0xf6e8,0xf6e9,0xf6ea,0xf6eb,0xf6ec,0xf6ed,0xf6ee,0xf6ef, + 0xf6f0,0xf6f1,0xf6f2,0xf6f3,0xf6f4,0xf6f5,0xf6f6,0xf6f7, + 0xf6f8,0xf6f9,0xf6fa,0xf6fb,0xf6fc,0xf6fd,0xf6fe,0xf6ff, + 0xf700,0xf701,0xf702,0xf703,0xf704,0xf705,0xf706,0xf707, + 0xf708,0xf709,0xf70a,0xf70b,0xf70c,0xf70d,0xf70e,0xf70f, + 0xf710,0xf711,0xf712,0xf713,0xf714,0xf715,0xf716,0xf717, + 0xf718,0xf719,0xf71a,0xf71b,0xf71c,0xf71d,0xf71e,0xf71f, + 0xf720,0xf721,0xf722,0xf723,0xf724,0xf725,0xf726,0xf727, + 0xf728,0xf729,0xf72a,0xf72b,0xf72c,0xf72d,0xf72e,0xf72f, + 0xf730,0xf731,0xf732,0xf733,0xf734,0xf735,0xf736,0xf737, + 0xf738,0xf739,0xf73a,0xf73b,0xf73c,0xf73d,0xf73e,0xf73f, + 0xf740,0xf741,0xf742,0xf743,0xf744,0xf745,0xf746,0xf747, + 0xf748,0xf749,0xf74a,0xf74b,0xf74c,0xf74d,0xf74e,0xf74f, + 0xf750,0xf751,0xf752,0xf753,0xf754,0xf755,0xf756,0xf757, + 0xf758,0xf759,0xf75a,0xf75b,0xf75c,0xf75d,0xf75e,0xf75f, + 0xf760,0xf761,0xf762,0xf763,0xf764,0xf765,0xf766,0xf767, + 0xf768,0xf769,0xf76a,0xf76b,0xf76c,0xf76d,0xf76e,0xf76f, + 0xf770,0xf771,0xf772,0xf773,0xf774,0xf775,0xf776,0xf777, + 0xf778,0xf779,0xf77a,0xf77b,0xf77c,0xf77d,0xf77e,0xf77f, + 0xf780,0xf781,0xf782,0xf783,0xf784,0xf785,0xf786,0xf787, + 0xf788,0xf789,0xf78a,0xf78b,0xf78c,0xf78d,0xf78e,0xf78f, + 0xf790,0xf791,0xf792,0xf793,0xf794,0xf795,0xf796,0xf797, + 0xf798,0xf799,0xf79a,0xf79b,0xf79c,0xf79d,0xf79e,0xf79f, + 0xf7a0,0xf7a1,0xf7a2,0xf7a3,0xf7a4,0xf7a5,0xf7a6,0xf7a7, + 0xf7a8,0xf7a9,0xf7aa,0xf7ab,0xf7ac,0xf7ad,0xf7ae,0xf7af, + 0xf7b0,0xf7b1,0xf7b2,0xf7b3,0xf7b4,0xf7b5,0xf7b6,0xf7b7, + 0xf7b8,0xf7b9,0xf7ba,0xf7bb,0xf7bc,0xf7bd,0xf7be,0xf7bf, + 0xf7c0,0xf7c1,0xf7c2,0xf7c3,0xf7c4,0xf7c5,0xf7c6,0xf7c7, + 0xf7c8,0xf7c9,0xf7ca,0xf7cb,0xf7cc,0xf7cd,0xf7ce,0xf7cf, + 0xf7d0,0xf7d1,0xf7d2,0xf7d3,0xf7d4,0xf7d5,0xf7d6,0xf7d7, + 0xf7d8,0xf7d9,0xf7da,0xf7db,0xf7dc,0xf7dd,0xf7de,0xf7df, + 0xf7e0,0xf7e1,0xf7e2,0xf7e3,0xf7e4,0xf7e5,0xf7e6,0xf7e7, + 0xf7e8,0xf7e9,0xf7ea,0xf7eb,0xf7ec,0xf7ed,0xf7ee,0xf7ef, + 0xf7f0,0xf7f1,0xf7f2,0xf7f3,0xf7f4,0xf7f5,0xf7f6,0xf7f7, + 0xf7f8,0xf7f9,0xf7fa,0xf7fb,0xf7fc,0xf7fd,0xf7fe,0xf7ff, + 0xf800,0xf801,0xf802,0xf803,0xf804,0xf805,0xf806,0xf807, + 0xf808,0xf809,0xf80a,0xf80b,0xf80c,0xf80d,0xf80e,0xf80f, + 0xf810,0xf811,0xf812,0xf813,0xf814,0xf815,0xf816,0xf817, + 0xf818,0xf819,0xf81a,0xf81b,0xf81c,0xf81d,0xf81e,0xf81f, + 0xf820,0xf821,0xf822,0xf823,0xf824,0xf825,0xf826,0xf827, + 0xf828,0xf829,0xf82a,0xf82b,0xf82c,0xf82d,0xf82e,0xf82f, + 0xf830,0xf831,0xf832,0xf833,0xf834,0xf835,0xf836,0xf837, + 0xf838,0xf839,0xf83a,0xf83b,0xf83c,0xf83d,0xf83e,0xf83f, + 0xf840,0xf841,0xf842,0xf843,0xf844,0xf845,0xf846,0xf847, + 0xf848,0xf849,0xf84a,0xf84b,0xf84c,0xf84d,0xf84e,0xf84f, + 0xf850,0xf851,0xf852,0xf853,0xf854,0xf855,0xf856,0xf857, + 0xf858,0xf859,0xf85a,0xf85b,0xf85c,0xf85d,0xf85e,0xf85f, + 0xf860,0xf861,0xf862,0xf863,0xf864,0xf865,0xf866,0xf867, + 0xf868,0xf869,0xf86a,0xf86b,0xf86c,0xf86d,0xf86e,0xf86f, + 0xf870,0xf871,0xf872,0xf873,0xf874,0xf875,0xf876,0xf877, + 0xf878,0xf879,0xf87a,0xf87b,0xf87c,0xf87d,0xf87e,0xf87f, + 0xf880,0xf881,0xf882,0xf883,0xf884,0xf885,0xf886,0xf887, + 0xf888,0xf889,0xf88a,0xf88b,0xf88c,0xf88d,0xf88e,0xf88f, + 0xf890,0xf891,0xf892,0xf893,0xf894,0xf895,0xf896,0xf897, + 0xf898,0xf899,0xf89a,0xf89b,0xf89c,0xf89d,0xf89e,0xf89f, + 0xf8a0,0xf8a1,0xf8a2,0xf8a3,0xf8a4,0xf8a5,0xf8a6,0xf8a7, + 0xf8a8,0xf8a9,0xf8aa,0xf8ab,0xf8ac,0xf8ad,0xf8ae,0xf8af, + 0xf8b0,0xf8b1,0xf8b2,0xf8b3,0xf8b4,0xf8b5,0xf8b6,0xf8b7, + 0xf8b8,0xf8b9,0xf8ba,0xf8bb,0xf8bc,0xf8bd,0xf8be,0xf8bf, + 0xf8c0,0xf8c1,0xf8c2,0xf8c3,0xf8c4,0xf8c5,0xf8c6,0xf8c7, + 0xf8c8,0xf8c9,0xf8ca,0xf8cb,0xf8cc,0xf8cd,0xf8ce,0xf8cf, + 0xf8d0,0xf8d1,0xf8d2,0xf8d3,0xf8d4,0xf8d5,0xf8d6,0xf8d7, + 0xf8d8,0xf8d9,0xf8da,0xf8db,0xf8dc,0xf8dd,0xf8de,0xf8df, + 0xf8e0,0xf8e1,0xf8e2,0xf8e3,0xf8e4,0xf8e5,0xf8e6,0xf8e7, + 0xf8e8,0xf8e9,0xf8ea,0xf8eb,0xf8ec,0xf8ed,0xf8ee,0xf8ef, + 0xf8f0,0xf8f1,0xf8f2,0xf8f3,0xf8f4,0xf8f5,0xf8f6,0xf8f7, + 0xf8f8,0xf8f9,0xf8fa,0xf8fb,0xf8fc,0xf8fd,0xf8fe,0xf8ff, + 0xf900,0xf901,0xf902,0xf903,0xf904,0xf905,0xf906,0xf907, + 0xf908,0xf909,0xf90a,0xf90b,0xf90c,0xf90d,0xf90e,0xf90f, + 0xf910,0xf911,0xf912,0xf913,0xf914,0xf915,0xf916,0xf917, + 0xf918,0xf919,0xf91a,0xf91b,0xf91c,0xf91d,0xf91e,0xf91f, + 0xf920,0xf921,0xf922,0xf923,0xf924,0xf925,0xf926,0xf927, + 0xf928,0xf929,0xf92a,0xf92b,0xf92c,0xf92d,0xf92e,0xf92f, + 0xf930,0xf931,0xf932,0xf933,0xf934,0xf935,0xf936,0xf937, + 0xf938,0xf939,0xf93a,0xf93b,0xf93c,0xf93d,0xf93e,0xf93f, + 0xf940,0xf941,0xf942,0xf943,0xf944,0xf945,0xf946,0xf947, + 0xf948,0xf949,0xf94a,0xf94b,0xf94c,0xf94d,0xf94e,0xf94f, + 0xf950,0xf951,0xf952,0xf953,0xf954,0xf955,0xf956,0xf957, + 0xf958,0xf959,0xf95a,0xf95b,0xf95c,0xf95d,0xf95e,0xf95f, + 0xf960,0xf961,0xf962,0xf963,0xf964,0xf965,0xf966,0xf967, + 0xf968,0xf969,0xf96a,0xf96b,0xf96c,0xf96d,0xf96e,0xf96f, + 0xf970,0xf971,0xf972,0xf973,0xf974,0xf975,0xf976,0xf977, + 0xf978,0xf979,0xf97a,0xf97b,0xf97c,0xf97d,0xf97e,0xf97f, + 0xf980,0xf981,0xf982,0xf983,0xf984,0xf985,0xf986,0xf987, + 0xf988,0xf989,0xf98a,0xf98b,0xf98c,0xf98d,0xf98e,0xf98f, + 0xf990,0xf991,0xf992,0xf993,0xf994,0xf995,0xf996,0xf997, + 0xf998,0xf999,0xf99a,0xf99b,0xf99c,0xf99d,0xf99e,0xf99f, + 0xf9a0,0xf9a1,0xf9a2,0xf9a3,0xf9a4,0xf9a5,0xf9a6,0xf9a7, + 0xf9a8,0xf9a9,0xf9aa,0xf9ab,0xf9ac,0xf9ad,0xf9ae,0xf9af, + 0xf9b0,0xf9b1,0xf9b2,0xf9b3,0xf9b4,0xf9b5,0xf9b6,0xf9b7, + 0xf9b8,0xf9b9,0xf9ba,0xf9bb,0xf9bc,0xf9bd,0xf9be,0xf9bf, + 0xf9c0,0xf9c1,0xf9c2,0xf9c3,0xf9c4,0xf9c5,0xf9c6,0xf9c7, + 0xf9c8,0xf9c9,0xf9ca,0xf9cb,0xf9cc,0xf9cd,0xf9ce,0xf9cf, + 0xf9d0,0xf9d1,0xf9d2,0xf9d3,0xf9d4,0xf9d5,0xf9d6,0xf9d7, + 0xf9d8,0xf9d9,0xf9da,0xf9db,0xf9dc,0xf9dd,0xf9de,0xf9df, + 0xf9e0,0xf9e1,0xf9e2,0xf9e3,0xf9e4,0xf9e5,0xf9e6,0xf9e7, + 0xf9e8,0xf9e9,0xf9ea,0xf9eb,0xf9ec,0xf9ed,0xf9ee,0xf9ef, + 0xf9f0,0xf9f1,0xf9f2,0xf9f3,0xf9f4,0xf9f5,0xf9f6,0xf9f7, + 0xf9f8,0xf9f9,0xf9fa,0xf9fb,0xf9fc,0xf9fd,0xf9fe,0xf9ff, + 0xfa00,0xfa01,0xfa02,0xfa03,0xfa04,0xfa05,0xfa06,0xfa07, + 0xfa08,0xfa09,0xfa0a,0xfa0b,0xfa0c,0xfa0d,0xfa0e,0xfa0f, + 0xfa10,0xfa11,0xfa12,0xfa13,0xfa14,0xfa15,0xfa16,0xfa17, + 0xfa18,0xfa19,0xfa1a,0xfa1b,0xfa1c,0xfa1d,0xfa1e,0xfa1f, + 0xfa20,0xfa21,0xfa22,0xfa23,0xfa24,0xfa25,0xfa26,0xfa27, + 0xfa28,0xfa29,0xfa2a,0xfa2b,0xfa2c,0xfa2d,0xfa2e,0xfa2f, + 0xfa30,0xfa31,0xfa32,0xfa33,0xfa34,0xfa35,0xfa36,0xfa37, + 0xfa38,0xfa39,0xfa3a,0xfa3b,0xfa3c,0xfa3d,0xfa3e,0xfa3f, + 0xfa40,0xfa41,0xfa42,0xfa43,0xfa44,0xfa45,0xfa46,0xfa47, + 0xfa48,0xfa49,0xfa4a,0xfa4b,0xfa4c,0xfa4d,0xfa4e,0xfa4f, + 0xfa50,0xfa51,0xfa52,0xfa53,0xfa54,0xfa55,0xfa56,0xfa57, + 0xfa58,0xfa59,0xfa5a,0xfa5b,0xfa5c,0xfa5d,0xfa5e,0xfa5f, + 0xfa60,0xfa61,0xfa62,0xfa63,0xfa64,0xfa65,0xfa66,0xfa67, + 0xfa68,0xfa69,0xfa6a,0xfa6b,0xfa6c,0xfa6d,0xfa6e,0xfa6f, + 0xfa70,0xfa71,0xfa72,0xfa73,0xfa74,0xfa75,0xfa76,0xfa77, + 0xfa78,0xfa79,0xfa7a,0xfa7b,0xfa7c,0xfa7d,0xfa7e,0xfa7f, + 0xfa80,0xfa81,0xfa82,0xfa83,0xfa84,0xfa85,0xfa86,0xfa87, + 0xfa88,0xfa89,0xfa8a,0xfa8b,0xfa8c,0xfa8d,0xfa8e,0xfa8f, + 0xfa90,0xfa91,0xfa92,0xfa93,0xfa94,0xfa95,0xfa96,0xfa97, + 0xfa98,0xfa99,0xfa9a,0xfa9b,0xfa9c,0xfa9d,0xfa9e,0xfa9f, + 0xfaa0,0xfaa1,0xfaa2,0xfaa3,0xfaa4,0xfaa5,0xfaa6,0xfaa7, + 0xfaa8,0xfaa9,0xfaaa,0xfaab,0xfaac,0xfaad,0xfaae,0xfaaf, + 0xfab0,0xfab1,0xfab2,0xfab3,0xfab4,0xfab5,0xfab6,0xfab7, + 0xfab8,0xfab9,0xfaba,0xfabb,0xfabc,0xfabd,0xfabe,0xfabf, + 0xfac0,0xfac1,0xfac2,0xfac3,0xfac4,0xfac5,0xfac6,0xfac7, + 0xfac8,0xfac9,0xfaca,0xfacb,0xfacc,0xfacd,0xface,0xfacf, + 0xfad0,0xfad1,0xfad2,0xfad3,0xfad4,0xfad5,0xfad6,0xfad7, + 0xfad8,0xfad9,0xfada,0xfadb,0xfadc,0xfadd,0xfade,0xfadf, + 0xfae0,0xfae1,0xfae2,0xfae3,0xfae4,0xfae5,0xfae6,0xfae7, + 0xfae8,0xfae9,0xfaea,0xfaeb,0xfaec,0xfaed,0xfaee,0xfaef, + 0xfaf0,0xfaf1,0xfaf2,0xfaf3,0xfaf4,0xfaf5,0xfaf6,0xfaf7, + 0xfaf8,0xfaf9,0xfafa,0xfafb,0xfafc,0xfafd,0xfafe,0xfaff, + 0xfb00,0xfb01,0xfb02,0xfb03,0xfb04,0xfb05,0xfb06,0xfb07, + 0xfb08,0xfb09,0xfb0a,0xfb0b,0xfb0c,0xfb0d,0xfb0e,0xfb0f, + 0xfb10,0xfb11,0xfb12,0xfb13,0xfb14,0xfb15,0xfb16,0xfb17, + 0xfb18,0xfb19,0xfb1a,0xfb1b,0xfb1c,0xfb1d,0xfb1e,0xfb1f, + 0xfb20,0xfb21,0xfb22,0xfb23,0xfb24,0xfb25,0xfb26,0xfb27, + 0xfb28,0xfb29,0xfb2a,0xfb2b,0xfb2c,0xfb2d,0xfb2e,0xfb2f, + 0xfb30,0xfb31,0xfb32,0xfb33,0xfb34,0xfb35,0xfb36,0xfb37, + 0xfb38,0xfb39,0xfb3a,0xfb3b,0xfb3c,0xfb3d,0xfb3e,0xfb3f, + 0xfb40,0xfb41,0xfb42,0xfb43,0xfb44,0xfb45,0xfb46,0xfb47, + 0xfb48,0xfb49,0xfb4a,0xfb4b,0xfb4c,0xfb4d,0xfb4e,0xfb4f, + 0xfb50,0xfb51,0xfb52,0xfb53,0xfb54,0xfb55,0xfb56,0xfb57, + 0xfb58,0xfb59,0xfb5a,0xfb5b,0xfb5c,0xfb5d,0xfb5e,0xfb5f, + 0xfb60,0xfb61,0xfb62,0xfb63,0xfb64,0xfb65,0xfb66,0xfb67, + 0xfb68,0xfb69,0xfb6a,0xfb6b,0xfb6c,0xfb6d,0xfb6e,0xfb6f, + 0xfb70,0xfb71,0xfb72,0xfb73,0xfb74,0xfb75,0xfb76,0xfb77, + 0xfb78,0xfb79,0xfb7a,0xfb7b,0xfb7c,0xfb7d,0xfb7e,0xfb7f, + 0xfb80,0xfb81,0xfb82,0xfb83,0xfb84,0xfb85,0xfb86,0xfb87, + 0xfb88,0xfb89,0xfb8a,0xfb8b,0xfb8c,0xfb8d,0xfb8e,0xfb8f, + 0xfb90,0xfb91,0xfb92,0xfb93,0xfb94,0xfb95,0xfb96,0xfb97, + 0xfb98,0xfb99,0xfb9a,0xfb9b,0xfb9c,0xfb9d,0xfb9e,0xfb9f, + 0xfba0,0xfba1,0xfba2,0xfba3,0xfba4,0xfba5,0xfba6,0xfba7, + 0xfba8,0xfba9,0xfbaa,0xfbab,0xfbac,0xfbad,0xfbae,0xfbaf, + 0xfbb0,0xfbb1,0xfbb2,0xfbb3,0xfbb4,0xfbb5,0xfbb6,0xfbb7, + 0xfbb8,0xfbb9,0xfbba,0xfbbb,0xfbbc,0xfbbd,0xfbbe,0xfbbf, + 0xfbc0,0xfbc1,0xfbc2,0xfbc3,0xfbc4,0xfbc5,0xfbc6,0xfbc7, + 0xfbc8,0xfbc9,0xfbca,0xfbcb,0xfbcc,0xfbcd,0xfbce,0xfbcf, + 0xfbd0,0xfbd1,0xfbd2,0xfbd3,0xfbd4,0xfbd5,0xfbd6,0xfbd7, + 0xfbd8,0xfbd9,0xfbda,0xfbdb,0xfbdc,0xfbdd,0xfbde,0xfbdf, + 0xfbe0,0xfbe1,0xfbe2,0xfbe3,0xfbe4,0xfbe5,0xfbe6,0xfbe7, + 0xfbe8,0xfbe9,0xfbea,0xfbeb,0xfbec,0xfbed,0xfbee,0xfbef, + 0xfbf0,0xfbf1,0xfbf2,0xfbf3,0xfbf4,0xfbf5,0xfbf6,0xfbf7, + 0xfbf8,0xfbf9,0xfbfa,0xfbfb,0xfbfc,0xfbfd,0xfbfe,0xfbff, + 0xfc00,0xfc01,0xfc02,0xfc03,0xfc04,0xfc05,0xfc06,0xfc07, + 0xfc08,0xfc09,0xfc0a,0xfc0b,0xfc0c,0xfc0d,0xfc0e,0xfc0f, + 0xfc10,0xfc11,0xfc12,0xfc13,0xfc14,0xfc15,0xfc16,0xfc17, + 0xfc18,0xfc19,0xfc1a,0xfc1b,0xfc1c,0xfc1d,0xfc1e,0xfc1f, + 0xfc20,0xfc21,0xfc22,0xfc23,0xfc24,0xfc25,0xfc26,0xfc27, + 0xfc28,0xfc29,0xfc2a,0xfc2b,0xfc2c,0xfc2d,0xfc2e,0xfc2f, + 0xfc30,0xfc31,0xfc32,0xfc33,0xfc34,0xfc35,0xfc36,0xfc37, + 0xfc38,0xfc39,0xfc3a,0xfc3b,0xfc3c,0xfc3d,0xfc3e,0xfc3f, + 0xfc40,0xfc41,0xfc42,0xfc43,0xfc44,0xfc45,0xfc46,0xfc47, + 0xfc48,0xfc49,0xfc4a,0xfc4b,0xfc4c,0xfc4d,0xfc4e,0xfc4f, + 0xfc50,0xfc51,0xfc52,0xfc53,0xfc54,0xfc55,0xfc56,0xfc57, + 0xfc58,0xfc59,0xfc5a,0xfc5b,0xfc5c,0xfc5d,0xfc5e,0xfc5f, + 0xfc60,0xfc61,0xfc62,0xfc63,0xfc64,0xfc65,0xfc66,0xfc67, + 0xfc68,0xfc69,0xfc6a,0xfc6b,0xfc6c,0xfc6d,0xfc6e,0xfc6f, + 0xfc70,0xfc71,0xfc72,0xfc73,0xfc74,0xfc75,0xfc76,0xfc77, + 0xfc78,0xfc79,0xfc7a,0xfc7b,0xfc7c,0xfc7d,0xfc7e,0xfc7f, + 0xfc80,0xfc81,0xfc82,0xfc83,0xfc84,0xfc85,0xfc86,0xfc87, + 0xfc88,0xfc89,0xfc8a,0xfc8b,0xfc8c,0xfc8d,0xfc8e,0xfc8f, + 0xfc90,0xfc91,0xfc92,0xfc93,0xfc94,0xfc95,0xfc96,0xfc97, + 0xfc98,0xfc99,0xfc9a,0xfc9b,0xfc9c,0xfc9d,0xfc9e,0xfc9f, + 0xfca0,0xfca1,0xfca2,0xfca3,0xfca4,0xfca5,0xfca6,0xfca7, + 0xfca8,0xfca9,0xfcaa,0xfcab,0xfcac,0xfcad,0xfcae,0xfcaf, + 0xfcb0,0xfcb1,0xfcb2,0xfcb3,0xfcb4,0xfcb5,0xfcb6,0xfcb7, + 0xfcb8,0xfcb9,0xfcba,0xfcbb,0xfcbc,0xfcbd,0xfcbe,0xfcbf, + 0xfcc0,0xfcc1,0xfcc2,0xfcc3,0xfcc4,0xfcc5,0xfcc6,0xfcc7, + 0xfcc8,0xfcc9,0xfcca,0xfccb,0xfccc,0xfccd,0xfcce,0xfccf, + 0xfcd0,0xfcd1,0xfcd2,0xfcd3,0xfcd4,0xfcd5,0xfcd6,0xfcd7, + 0xfcd8,0xfcd9,0xfcda,0xfcdb,0xfcdc,0xfcdd,0xfcde,0xfcdf, + 0xfce0,0xfce1,0xfce2,0xfce3,0xfce4,0xfce5,0xfce6,0xfce7, + 0xfce8,0xfce9,0xfcea,0xfceb,0xfcec,0xfced,0xfcee,0xfcef, + 0xfcf0,0xfcf1,0xfcf2,0xfcf3,0xfcf4,0xfcf5,0xfcf6,0xfcf7, + 0xfcf8,0xfcf9,0xfcfa,0xfcfb,0xfcfc,0xfcfd,0xfcfe,0xfcff, + 0xfd00,0xfd01,0xfd02,0xfd03,0xfd04,0xfd05,0xfd06,0xfd07, + 0xfd08,0xfd09,0xfd0a,0xfd0b,0xfd0c,0xfd0d,0xfd0e,0xfd0f, + 0xfd10,0xfd11,0xfd12,0xfd13,0xfd14,0xfd15,0xfd16,0xfd17, + 0xfd18,0xfd19,0xfd1a,0xfd1b,0xfd1c,0xfd1d,0xfd1e,0xfd1f, + 0xfd20,0xfd21,0xfd22,0xfd23,0xfd24,0xfd25,0xfd26,0xfd27, + 0xfd28,0xfd29,0xfd2a,0xfd2b,0xfd2c,0xfd2d,0xfd2e,0xfd2f, + 0xfd30,0xfd31,0xfd32,0xfd33,0xfd34,0xfd35,0xfd36,0xfd37, + 0xfd38,0xfd39,0xfd3a,0xfd3b,0xfd3c,0xfd3d,0xfd3e,0xfd3f, + 0xfd40,0xfd41,0xfd42,0xfd43,0xfd44,0xfd45,0xfd46,0xfd47, + 0xfd48,0xfd49,0xfd4a,0xfd4b,0xfd4c,0xfd4d,0xfd4e,0xfd4f, + 0xfd50,0xfd51,0xfd52,0xfd53,0xfd54,0xfd55,0xfd56,0xfd57, + 0xfd58,0xfd59,0xfd5a,0xfd5b,0xfd5c,0xfd5d,0xfd5e,0xfd5f, + 0xfd60,0xfd61,0xfd62,0xfd63,0xfd64,0xfd65,0xfd66,0xfd67, + 0xfd68,0xfd69,0xfd6a,0xfd6b,0xfd6c,0xfd6d,0xfd6e,0xfd6f, + 0xfd70,0xfd71,0xfd72,0xfd73,0xfd74,0xfd75,0xfd76,0xfd77, + 0xfd78,0xfd79,0xfd7a,0xfd7b,0xfd7c,0xfd7d,0xfd7e,0xfd7f, + 0xfd80,0xfd81,0xfd82,0xfd83,0xfd84,0xfd85,0xfd86,0xfd87, + 0xfd88,0xfd89,0xfd8a,0xfd8b,0xfd8c,0xfd8d,0xfd8e,0xfd8f, + 0xfd90,0xfd91,0xfd92,0xfd93,0xfd94,0xfd95,0xfd96,0xfd97, + 0xfd98,0xfd99,0xfd9a,0xfd9b,0xfd9c,0xfd9d,0xfd9e,0xfd9f, + 0xfda0,0xfda1,0xfda2,0xfda3,0xfda4,0xfda5,0xfda6,0xfda7, + 0xfda8,0xfda9,0xfdaa,0xfdab,0xfdac,0xfdad,0xfdae,0xfdaf, + 0xfdb0,0xfdb1,0xfdb2,0xfdb3,0xfdb4,0xfdb5,0xfdb6,0xfdb7, + 0xfdb8,0xfdb9,0xfdba,0xfdbb,0xfdbc,0xfdbd,0xfdbe,0xfdbf, + 0xfdc0,0xfdc1,0xfdc2,0xfdc3,0xfdc4,0xfdc5,0xfdc6,0xfdc7, + 0xfdc8,0xfdc9,0xfdca,0xfdcb,0xfdcc,0xfdcd,0xfdce,0xfdcf, + 0xfdd0,0xfdd1,0xfdd2,0xfdd3,0xfdd4,0xfdd5,0xfdd6,0xfdd7, + 0xfdd8,0xfdd9,0xfdda,0xfddb,0xfddc,0xfddd,0xfdde,0xfddf, + 0xfde0,0xfde1,0xfde2,0xfde3,0xfde4,0xfde5,0xfde6,0xfde7, + 0xfde8,0xfde9,0xfdea,0xfdeb,0xfdec,0xfded,0xfdee,0xfdef, + 0xfdf0,0xfdf1,0xfdf2,0xfdf3,0xfdf4,0xfdf5,0xfdf6,0xfdf7, + 0xfdf8,0xfdf9,0xfdfa,0xfdfb,0xfdfc,0xfdfd,0xfdfe,0xfdff, + 0xfe00,0xfe01,0xfe02,0xfe03,0xfe04,0xfe05,0xfe06,0xfe07, + 0xfe08,0xfe09,0xfe0a,0xfe0b,0xfe0c,0xfe0d,0xfe0e,0xfe0f, + 0xfe10,0xfe11,0xfe12,0xfe13,0xfe14,0xfe15,0xfe16,0xfe17, + 0xfe18,0xfe19,0xfe1a,0xfe1b,0xfe1c,0xfe1d,0xfe1e,0xfe1f, + 0xfe20,0xfe21,0xfe22,0xfe23,0xfe24,0xfe25,0xfe26,0xfe27, + 0xfe28,0xfe29,0xfe2a,0xfe2b,0xfe2c,0xfe2d,0xfe2e,0xfe2f, + 0xfe30,0xfe31,0xfe32,0xfe33,0xfe34,0xfe35,0xfe36,0xfe37, + 0xfe38,0xfe39,0xfe3a,0xfe3b,0xfe3c,0xfe3d,0xfe3e,0xfe3f, + 0xfe40,0xfe41,0xfe42,0xfe43,0xfe44,0xfe45,0xfe46,0xfe47, + 0xfe48,0xfe49,0xfe4a,0xfe4b,0xfe4c,0xfe4d,0xfe4e,0xfe4f, + 0xfe50,0xfe51,0xfe52,0xfe53,0xfe54,0xfe55,0xfe56,0xfe57, + 0xfe58,0xfe59,0xfe5a,0xfe5b,0xfe5c,0xfe5d,0xfe5e,0xfe5f, + 0xfe60,0xfe61,0xfe62,0xfe63,0xfe64,0xfe65,0xfe66,0xfe67, + 0xfe68,0xfe69,0xfe6a,0xfe6b,0xfe6c,0xfe6d,0xfe6e,0xfe6f, + 0xfe70,0xfe71,0xfe72,0xfe73,0xfe74,0xfe75,0xfe76,0xfe77, + 0xfe78,0xfe79,0xfe7a,0xfe7b,0xfe7c,0xfe7d,0xfe7e,0xfe7f, + 0xfe80,0xfe81,0xfe82,0xfe83,0xfe84,0xfe85,0xfe86,0xfe87, + 0xfe88,0xfe89,0xfe8a,0xfe8b,0xfe8c,0xfe8d,0xfe8e,0xfe8f, + 0xfe90,0xfe91,0xfe92,0xfe93,0xfe94,0xfe95,0xfe96,0xfe97, + 0xfe98,0xfe99,0xfe9a,0xfe9b,0xfe9c,0xfe9d,0xfe9e,0xfe9f, + 0xfea0,0xfea1,0xfea2,0xfea3,0xfea4,0xfea5,0xfea6,0xfea7, + 0xfea8,0xfea9,0xfeaa,0xfeab,0xfeac,0xfead,0xfeae,0xfeaf, + 0xfeb0,0xfeb1,0xfeb2,0xfeb3,0xfeb4,0xfeb5,0xfeb6,0xfeb7, + 0xfeb8,0xfeb9,0xfeba,0xfebb,0xfebc,0xfebd,0xfebe,0xfebf, + 0xfec0,0xfec1,0xfec2,0xfec3,0xfec4,0xfec5,0xfec6,0xfec7, + 0xfec8,0xfec9,0xfeca,0xfecb,0xfecc,0xfecd,0xfece,0xfecf, + 0xfed0,0xfed1,0xfed2,0xfed3,0xfed4,0xfed5,0xfed6,0xfed7, + 0xfed8,0xfed9,0xfeda,0xfedb,0xfedc,0xfedd,0xfede,0xfedf, + 0xfee0,0xfee1,0xfee2,0xfee3,0xfee4,0xfee5,0xfee6,0xfee7, + 0xfee8,0xfee9,0xfeea,0xfeeb,0xfeec,0xfeed,0xfeee,0xfeef, + 0xfef0,0xfef1,0xfef2,0xfef3,0xfef4,0xfef5,0xfef6,0xfef7, + 0xfef8,0xfef9,0xfefa,0xfefb,0xfefc,0xfefd,0xfefe,0xfeff, + 0xff00,0xff01,0xff02,0xff03,0xff04,0xff05,0xff06,0xff07, + 0xff08,0xff09,0xff0a,0xff0b,0xff0c,0xff0d,0xff0e,0xff0f, + 0xff10,0xff11,0xff12,0xff13,0xff14,0xff15,0xff16,0xff17, + 0xff18,0xff19,0xff1a,0xff1b,0xff1c,0xff1d,0xff1e,0xff1f, + 0xff20,0xff21,0xff22,0xff23,0xff24,0xff25,0xff26,0xff27, + 0xff28,0xff29,0xff2a,0xff2b,0xff2c,0xff2d,0xff2e,0xff2f, + 0xff30,0xff31,0xff32,0xff33,0xff34,0xff35,0xff36,0xff37, + 0xff38,0xff39,0xff3a,0xff3b,0xff3c,0xff3d,0xff3e,0xff3f, + 0xff40,0xff21,0xff22,0xff23,0xff24,0xff25,0xff26,0xff27, + 0xff28,0xff29,0xff2a,0xff2b,0xff2c,0xff2d,0xff2e,0xff2f, + 0xff30,0xff31,0xff32,0xff33,0xff34,0xff35,0xff36,0xff37, + 0xff38,0xff39,0xff3a,0xff5b,0xff5c,0xff5d,0xff5e,0xff5f, + 0xff60,0xff61,0xff62,0xff63,0xff64,0xff65,0xff66,0xff67, + 0xff68,0xff69,0xff6a,0xff6b,0xff6c,0xff6d,0xff6e,0xff6f, + 0xff70,0xff71,0xff72,0xff73,0xff74,0xff75,0xff76,0xff77, + 0xff78,0xff79,0xff7a,0xff7b,0xff7c,0xff7d,0xff7e,0xff7f, + 0xff80,0xff81,0xff82,0xff83,0xff84,0xff85,0xff86,0xff87, + 0xff88,0xff89,0xff8a,0xff8b,0xff8c,0xff8d,0xff8e,0xff8f, + 0xff90,0xff91,0xff92,0xff93,0xff94,0xff95,0xff96,0xff97, + 0xff98,0xff99,0xff9a,0xff9b,0xff9c,0xff9d,0xff9e,0xff9f, + 0xffa0,0xffa1,0xffa2,0xffa3,0xffa4,0xffa5,0xffa6,0xffa7, + 0xffa8,0xffa9,0xffaa,0xffab,0xffac,0xffad,0xffae,0xffaf, + 0xffb0,0xffb1,0xffb2,0xffb3,0xffb4,0xffb5,0xffb6,0xffb7, + 0xffb8,0xffb9,0xffba,0xffbb,0xffbc,0xffbd,0xffbe,0xffbf, + 0xffc0,0xffc1,0xffc2,0xffc3,0xffc4,0xffc5,0xffc6,0xffc7, + 0xffc8,0xffc9,0xffca,0xffcb,0xffcc,0xffcd,0xffce,0xffcf, + 0xffd0,0xffd1,0xffd2,0xffd3,0xffd4,0xffd5,0xffd6,0xffd7, + 0xffd8,0xffd9,0xffda,0xffdb,0xffdc,0xffdd,0xffde,0xffdf, + 0xffe0,0xffe1,0xffe2,0xffe3,0xffe4,0xffe5,0xffe6,0xffe7, + 0xffe8,0xffe9,0xffea,0xffeb,0xffec,0xffed,0xffee,0xffef, + 0xfff0,0xfff1,0xfff2,0xfff3,0xfff4,0xfff5,0xfff6,0xfff7, + 0xfff8,0xfff9,0xfffa,0xfffb,0xfffc,0xfffd,0xfffe,0xffff +}; + +void smb_init_locale(void) +{ + /* This is a useful global hook where we can ensure that the + * locale is set from the environment. This is needed so that + * we can use LOCALE as a codepage */ +#ifdef HAVE_SETLOCALE + setlocale(LC_ALL, ""); +#endif +} + +/** + Convert a codepoint_t to upper case. +**/ +_PUBLIC_ codepoint_t toupper_m(codepoint_t val) +{ + if (val >= ARRAY_SIZE(upcase_table)) { + return val; + } + return upcase_table[val]; +} + +/** + Convert a codepoint_t to lower case. +**/ +_PUBLIC_ codepoint_t tolower_m(codepoint_t val) +{ + if (val >= ARRAY_SIZE(lowcase_table)) { + return val; + } + return lowcase_table[val]; +} + +/** + If we upper cased this character, would we get the same character? +**/ +_PUBLIC_ bool islower_m(codepoint_t val) +{ + return (toupper_m(val) != val); +} + +/** + If we lower cased this character, would we get the same character? +**/ +_PUBLIC_ bool isupper_m(codepoint_t val) +{ + return (tolower_m(val) != val); +} + +/** + compare two codepoints case insensitively +*/ +_PUBLIC_ int codepoint_cmpi(codepoint_t c1, codepoint_t c2) +{ + if (c1 == c2 || + toupper_m(c1) == toupper_m(c2)) { + return 0; + } + return c1 - c2; +} + + +struct smb_iconv_handle { + TALLOC_CTX *child_ctx; + const char *unix_charset; + const char *dos_charset; + const char *display_charset; + bool use_builtin_handlers; + smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; +}; + +static struct smb_iconv_handle *global_iconv_handle = NULL; + +struct smb_iconv_handle *get_iconv_handle(void) +{ + if (global_iconv_handle == NULL) { + global_iconv_handle = + smb_iconv_handle_reinit(NULL, + "ASCII", + "UTF-8", + true, + NULL); + } + + return global_iconv_handle; +} + +struct smb_iconv_handle *get_iconv_testing_handle(TALLOC_CTX *mem_ctx, + const char *dos_charset, + const char *unix_charset, + bool use_builtin_handlers) +{ + return smb_iconv_handle_reinit(mem_ctx, + dos_charset, unix_charset, use_builtin_handlers, NULL); +} + +struct smb_iconv_handle *reinit_iconv_handle(TALLOC_CTX *mem_ctx, + const char *dos_charset, + const char *unix_charset) +{ + global_iconv_handle = + smb_iconv_handle_reinit(mem_ctx, + dos_charset, + unix_charset, + true, + global_iconv_handle); + return global_iconv_handle; +} + +void free_iconv_handle(void) +{ + TALLOC_FREE(global_iconv_handle); +} + +/** + * Return the name of a charset to give to iconv(). + **/ +const char *charset_name(struct smb_iconv_handle *ic, charset_t ch) +{ + switch (ch) { + case CH_UTF16: return "UTF-16LE"; + case CH_UNIX: return ic->unix_charset; + case CH_DOS: return ic->dos_charset; + case CH_UTF8: return "UTF8"; + case CH_UTF16BE: return "UTF-16BE"; + case CH_UTF16MUNGED: return "UTF16_MUNGED"; + default: + return "ASCII"; + } +} + +/** + re-initialize iconv conversion descriptors +**/ +static int close_iconv_handle(struct smb_iconv_handle *data) +{ + unsigned c1, c2; + for (c1=0;c1<NUM_CHARSETS;c1++) { + for (c2=0;c2<NUM_CHARSETS;c2++) { + if (data->conv_handles[c1][c2] != NULL) { + if (data->conv_handles[c1][c2] != (smb_iconv_t)-1) { + smb_iconv_close(data->conv_handles[c1][c2]); + } + data->conv_handles[c1][c2] = NULL; + } + } + } + + return 0; +} + +/* + the old_ic is passed in here as the smb_iconv_handle structure + is used as a global pointer in some places (eg. python modules). We + don't want to invalidate those global pointers, but we do want to + update them with the right charset information when loadparm + runs. To do that we need to re-use the structure pointer, but + re-fill the elements in the structure with the updated values + */ +_PUBLIC_ struct smb_iconv_handle *smb_iconv_handle_reinit(TALLOC_CTX *mem_ctx, + const char *dos_charset, + const char *unix_charset, + bool use_builtin_handlers, + struct smb_iconv_handle *old_ic) +{ + struct smb_iconv_handle *ret; + + if (old_ic != NULL) { + ret = old_ic; + close_iconv_handle(ret); + talloc_free(ret->child_ctx); + ZERO_STRUCTP(ret); + } else { + ret = talloc_zero(mem_ctx, struct smb_iconv_handle); + } + if (ret == NULL) { + return NULL; + } + + /* we use a child context to allow us to free all ptrs without + freeing the structure itself */ + ret->child_ctx = talloc_new(ret); + if (ret->child_ctx == NULL) { + return NULL; + } + + talloc_set_destructor(ret, close_iconv_handle); + + if (strcasecmp(dos_charset, "UTF8") == 0 || strcasecmp(dos_charset, "UTF-8") == 0) { + DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not be UTF8, using (default value) CP850 instead\n")); + dos_charset = "CP850"; + } + + ret->dos_charset = talloc_strdup(ret->child_ctx, dos_charset); + ret->unix_charset = talloc_strdup(ret->child_ctx, unix_charset); + ret->use_builtin_handlers = use_builtin_handlers; + + return ret; +} + +/* + on-demand initialisation of conversion handles +*/ +smb_iconv_t get_conv_handle(struct smb_iconv_handle *ic, + charset_t from, charset_t to) +{ + const char *n1, *n2; + + if (ic->conv_handles[from][to]) { + return ic->conv_handles[from][to]; + } + + n1 = charset_name(ic, from); + n2 = charset_name(ic, to); + + ic->conv_handles[from][to] = smb_iconv_open_ex(ic, n2, n1, + ic->use_builtin_handlers); + + if (ic->conv_handles[from][to] == (smb_iconv_t)-1) { + if ((from == CH_DOS || to == CH_DOS) && + strcasecmp(charset_name(ic, CH_DOS), "ASCII") != 0) { + DEBUG(0,("dos charset '%s' unavailable - using ASCII\n", + charset_name(ic, CH_DOS))); + ic->dos_charset = "ASCII"; + + n1 = charset_name(ic, from); + n2 = charset_name(ic, to); + + ic->conv_handles[from][to] = + smb_iconv_open_ex(ic, n2, n1, ic->use_builtin_handlers); + } + } + + return ic->conv_handles[from][to]; +} + +/** + * Return the unicode codepoint for the next character in the input + * string in the given src_charset. + * The unicode codepoint (codepoint_t) is an unsigned 32 bit value. + * + * Also return the number of bytes consumed (which tells the caller + * how many bytes to skip to get to the next src_charset-character). + * + * This is implemented (in the non-ascii-case) by first converting the + * next character in the input string to UTF16_LE and then calculating + * the unicode codepoint from that. + * + * Return INVALID_CODEPOINT if the next character cannot be converted. + */ +_PUBLIC_ codepoint_t next_codepoint_handle_ext( + struct smb_iconv_handle *ic, + const char *str, size_t len, + charset_t src_charset, + size_t *bytes_consumed) +{ + /* it cannot occupy more than 4 bytes in UTF16 format */ + uint8_t buf[4]; + smb_iconv_t descriptor; + size_t ilen_orig; + size_t ilen; + size_t olen; + char *outbuf; + + + if (((str[0] & 0x80) == 0) && (src_charset == CH_DOS || + src_charset == CH_UNIX || + src_charset == CH_UTF8)) { + *bytes_consumed = 1; + return (codepoint_t)str[0]; + } + + /* + * we assume that no multi-byte character can take more than 5 bytes. + * This is OK as we only support codepoints up to 1M (U+100000) + */ + ilen_orig = MIN(len, 5); + ilen = ilen_orig; + + descriptor = get_conv_handle(ic, src_charset, CH_UTF16); + if (descriptor == (smb_iconv_t)-1) { + *bytes_consumed = 1; + return INVALID_CODEPOINT; + } + + /* + * this looks a little strange, but it is needed to cope with + * codepoints above 64k (U+1000) which are encoded as per RFC2781. + */ + olen = 2; + outbuf = (char *)buf; + smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); + if (olen == 2) { + olen = 4; + outbuf = (char *)buf; + smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); + if (olen == 4) { + /* we didn't convert any bytes */ + *bytes_consumed = 1; + return INVALID_CODEPOINT; + } + olen = 4 - olen; + } else { + olen = 2 - olen; + } + + *bytes_consumed = ilen_orig - ilen; + + if (olen == 2) { + return (codepoint_t)SVAL(buf, 0); + } + if (olen == 4) { + /* decode a 4 byte UTF16 character manually */ + return (codepoint_t)0x10000 + + (buf[2] | ((buf[3] & 0x3)<<8) | + (buf[0]<<10) | ((buf[1] & 0x3)<<18)); + } + + /* no other length is valid */ + return INVALID_CODEPOINT; +} + +/* + return the unicode codepoint for the next multi-byte CH_UNIX character + in the string + + also return the number of bytes consumed (which tells the caller + how many bytes to skip to get to the next CH_UNIX character) + + return INVALID_CODEPOINT if the next character cannot be converted +*/ +_PUBLIC_ codepoint_t next_codepoint_handle(struct smb_iconv_handle *ic, + const char *str, size_t *size) +{ + /* + * We assume that no multi-byte character can take more than 5 bytes + * thus avoiding walking all the way down a long string. This is OK as + * Unicode codepoints only go up to (U+10ffff), which can always be + * encoded in 4 bytes or less. + */ + return next_codepoint_handle_ext(ic, str, strnlen(str, 5), CH_UNIX, + size); +} + +/* + push a single codepoint into a CH_UNIX string the target string must + be able to hold the full character, which is guaranteed if it is at + least 5 bytes in size. The caller may pass less than 5 bytes if they + are sure the character will fit (for example, you can assume that + uppercase/lowercase of a character will not add more than 1 byte) + + return the number of bytes occupied by the CH_UNIX character, or + -1 on failure +*/ +_PUBLIC_ ssize_t push_codepoint_handle(struct smb_iconv_handle *ic, + char *str, codepoint_t c) +{ + smb_iconv_t descriptor; + uint8_t buf[4]; + size_t ilen, olen; + const char *inbuf; + + if (c < 128) { + *str = c; + return 1; + } + + descriptor = get_conv_handle(ic, + CH_UTF16, CH_UNIX); + if (descriptor == (smb_iconv_t)-1) { + return -1; + } + + if (c < 0x10000) { + ilen = 2; + olen = 5; + inbuf = (char *)buf; + SSVAL(buf, 0, c); + smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); + if (ilen != 0) { + return -1; + } + return 5 - olen; + } + + c -= 0x10000; + + buf[0] = (c>>10) & 0xFF; + buf[1] = (c>>18) | 0xd8; + buf[2] = c & 0xFF; + buf[3] = ((c>>8) & 0x3) | 0xdc; + + ilen = 4; + olen = 5; + inbuf = (char *)buf; + + smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); + if (ilen != 0) { + return -1; + } + return 5 - olen; +} + +_PUBLIC_ codepoint_t next_codepoint_ext(const char *str, size_t len, + charset_t src_charset, size_t *size) +{ + return next_codepoint_handle_ext(get_iconv_handle(), str, len, + src_charset, size); +} + +_PUBLIC_ codepoint_t next_codepoint(const char *str, size_t *size) +{ + if ((str[0] & 0x80) == 0) { + *size = 1; + return str[0]; + } + return next_codepoint_handle(get_iconv_handle(), str, size); +} + +_PUBLIC_ ssize_t push_codepoint(char *str, codepoint_t c) +{ + return push_codepoint_handle(get_iconv_handle(), str, c); +} diff --git a/lib/util/charset/convert_string.c b/lib/util/charset/convert_string.c new file mode 100644 index 0000000..859b002 --- /dev/null +++ b/lib/util/charset/convert_string.c @@ -0,0 +1,556 @@ +/* + Unix SMB/CIFS implementation. + Character set conversion Extensions + Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001 + Copyright (C) Andrew Tridgell 2001-2011 + Copyright (C) Andrew Bartlett 2011 + Copyright (C) Simo Sorce 2001 + Copyright (C) Martin Pool 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ +#include "replace.h" +#include "system/iconv.h" +#include "charset.h" +#include "lib/util/debug.h" +#include "lib/util/fault.h" + +/** + * @file + * + * @brief Character-set conversion routines built on our iconv. + * + * @note Samba's internal character set (at least in the 3.0 series) + * is always the same as the one for the Unix filesystem. It is + * <b>not</b> necessarily UTF-8 and may be different on machines that + * need i18n filenames to be compatible with Unix software. It does + * have to be a superset of ASCII. All multibyte sequences must start + * with a byte with the high bit set. + * + * @sa lib/iconv.c + */ + + +/** + * Convert string from one encoding to another, making error checking etc + * Slow path version - uses (slow) iconv. + * + * @param src pointer to source string (multibyte or singlebyte) + * @param srclen length of the source string in bytes + * @param dest pointer to destination string (multibyte or singlebyte) + * @param destlen maximal length allowed for string + * @param converted size is the number of bytes occupied in the destination + * + * @returns false and sets errno on fail, true on success. + * + * Ensure the srclen contains the terminating zero. + * + **/ + +static bool convert_string_internal(struct smb_iconv_handle *ic, + charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen, size_t *converted_size) +{ + size_t i_len, o_len; + size_t retval; + const char* inbuf = (const char*)src; + char* outbuf = (char*)dest; + smb_iconv_t descriptor; + + descriptor = get_conv_handle(ic, from, to); + + if (srclen == (size_t)-1) { + if (from == CH_UTF16LE || from == CH_UTF16BE) { + srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2; + } else { + srclen = strlen((const char *)src)+1; + } + } + + + if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { + errno = EINVAL; + return false; + } + + i_len=srclen; + o_len=destlen; + + retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len); + *converted_size = destlen-o_len; + + return (retval != (size_t)-1); +} + +/** + * Convert string from one encoding to another, making error checking etc + * Fast path version - handles ASCII first. + * + * @param src pointer to source string (multibyte or singlebyte) + * @param srclen length of the source string in bytes, or -1 for nul terminated. + * @param dest pointer to destination string (multibyte or singlebyte) + * @param destlen maximal length allowed for string - *NEVER* -1. + * @param converted size is the number of bytes occupied in the destination + * + * @returns false and sets errno on fail, true on success. + * + * Ensure the srclen contains the terminating zero. + * + * This function has been hand-tuned to provide a fast path. + * Don't change unless you really know what you are doing. JRA. + **/ + +bool convert_string_error_handle(struct smb_iconv_handle *ic, + charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen, + size_t *converted_size) +{ + /* + * NB. We deliberately don't do a strlen here if srclen == -1. + * This is very expensive over millions of calls and is taken + * care of in the slow path in convert_string_internal. JRA. + */ + +#ifdef DEVELOPER + SMB_ASSERT(destlen != (size_t)-1); +#endif + + if (srclen == 0) { + *converted_size = 0; + return true; + } + + if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) { + const unsigned char *p = (const unsigned char *)src; + unsigned char *q = (unsigned char *)dest; + size_t slen = srclen; + size_t dlen = destlen; + unsigned char lastp = '\0'; + size_t retval = 0; + + /* If all characters are ascii, fast path here. */ + while (slen && dlen) { + if ((lastp = *p) <= 0x7f) { + *q++ = *p++; + if (slen != (size_t)-1) { + slen--; + } + dlen--; + retval++; + if (!lastp) + break; + } else { +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + goto general_case; +#else + bool ret = convert_string_internal(ic, from, to, p, slen, q, dlen, converted_size); + *converted_size += retval; + return ret; +#endif + } + } + + *converted_size = retval; + + if (!dlen) { + /* Even if we fast path we should note if we ran out of room. */ + if (((slen != (size_t)-1) && slen) || + ((slen == (size_t)-1) && lastp)) { + errno = E2BIG; + return false; + } + } + return true; + } else if (from == CH_UTF16LE && to != CH_UTF16LE) { + const unsigned char *p = (const unsigned char *)src; + unsigned char *q = (unsigned char *)dest; + size_t retval = 0; + size_t slen = srclen; + size_t dlen = destlen; + unsigned char lastp = '\0'; +#ifndef BROKEN_UNICODE_COMPOSE_CHARACTERS + bool ret; +#endif + + if (slen == (size_t)-1) { + while (dlen && + ((lastp = *p) <= 0x7f) && (p[1] == 0)) { + *q++ = *p; + p += 2; + dlen--; + retval++; + if (!lastp) + break; + } + if (lastp != 0) goto slow_path; + } else { + while (slen >= 2 && dlen && + (*p <= 0x7f) && (p[1] == 0)) { + *q++ = *p; + slen -= 2; + p += 2; + dlen--; + retval++; + } + if (slen != 0) goto slow_path; + } + + *converted_size = retval; + + if (!dlen) { + /* Even if we fast path we should note if we ran out of room. */ + if (((slen != (size_t)-1) && slen) || + ((slen == (size_t)-1) && lastp)) { + errno = E2BIG; + return false; + } + } + return true; + + slow_path: + /* come here when we hit a character we can't deal + * with in the fast path + */ +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + goto general_case; +#else + ret = convert_string_internal(ic, from, to, p, slen, q, dlen, converted_size); + *converted_size += retval; + return ret; +#endif + + } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) { + const unsigned char *p = (const unsigned char *)src; + unsigned char *q = (unsigned char *)dest; + size_t retval = 0; + size_t slen = srclen; + size_t dlen = destlen; + unsigned char lastp = '\0'; + + /* If all characters are ascii, fast path here. */ + while (slen && (dlen >= 1)) { + if (dlen >=2 && (lastp = *p) <= 0x7F) { + *q++ = *p++; + *q++ = '\0'; + if (slen != (size_t)-1) { + slen--; + } + dlen -= 2; + retval += 2; + if (!lastp) + break; + } else { +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + goto general_case; +#else + bool ret = convert_string_internal(ic, from, to, p, slen, q, dlen, converted_size); + *converted_size += retval; + return ret; +#endif + } + } + + *converted_size = retval; + + if (!dlen) { + /* Even if we fast path we should note if we ran out of room. */ + if (((slen != (size_t)-1) && slen) || + ((slen == (size_t)-1) && lastp)) { + errno = E2BIG; + return false; + } + } + return true; + } + +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + general_case: +#endif + return convert_string_internal(ic, from, to, src, srclen, dest, destlen, converted_size); +} + +bool convert_string_handle(struct smb_iconv_handle *ic, + charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen, + size_t *converted_size) +{ + bool ret = convert_string_error_handle(ic, from, to, src, srclen, dest, destlen, converted_size); + + if(ret==false) { + const char *reason="unknown error"; + switch(errno) { + case EINVAL: + reason="Incomplete multibyte sequence"; + DBG_NOTICE("Conversion error: %s\n", + reason); + break; + case E2BIG: + { + reason="No more room"; + if (from == CH_UNIX) { + DBG_NOTICE("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u error: %s\n", + charset_name(ic, from), charset_name(ic, to), + (unsigned int)srclen, (unsigned int)destlen, reason); + } else { + DBG_NOTICE("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u error: %s\n", + charset_name(ic, from), charset_name(ic, to), + (unsigned int)srclen, (unsigned int)destlen, reason); + } + break; + } + case EILSEQ: + reason="Illegal multibyte sequence"; + DBG_NOTICE("convert_string_internal: Conversion error: %s\n", + reason); + break; + default: + DBG_ERR("convert_string_internal: Conversion error: %s\n", + reason); + break; + } + /* smb_panic(reason); */ + } + return ret; +} + + +/** + * Convert between character sets, allocating a new buffer using talloc for the result. + * + * @param srclen length of source buffer. + * @param dest always set at least to NULL + * @param converted_size set to the number of bytes occupied by the string in + * the destination on success. + * @note -1 is not accepted for srclen. + * + * @return true if new buffer was correctly allocated, and string was + * converted. + * + * Ensure the srclen contains the terminating zero. + */ +bool convert_string_talloc_handle(TALLOC_CTX *ctx, struct smb_iconv_handle *ic, + charset_t from, charset_t to, + void const *src, size_t srclen, void *dst, + size_t *converted_size) + +{ + size_t i_len, o_len, destlen; + size_t retval; + const char *inbuf = NULL; + char *outbuf = NULL, *ob = NULL; + smb_iconv_t descriptor; + void **dest = dst; + + *dest = NULL; + if (converted_size != NULL) { + *converted_size = 0; + } + + if (src == NULL || srclen == (size_t)-1) { + errno = EINVAL; + return false; + } + + if (srclen == 0) { + /* We really should treat this as an error, but + there are too many callers that need this to + return a NULL terminated string in the correct + character set. */ + if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) { + destlen = 2; + } else { + destlen = 1; + } + ob = talloc_zero_array(ctx, char, destlen); + if (ob == NULL) { + DBG_ERR("Could not talloc destination buffer.\n"); + errno = ENOMEM; + return false; + } + if (converted_size != NULL) { + *converted_size = destlen; + } + *dest = ob; + return true; + } + + descriptor = get_conv_handle(ic, from, to); + + if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { + DEBUG(0,("convert_string_talloc: Conversion not supported.\n")); + errno = EOPNOTSUPP; + return false; + } + + if (srclen >= (SIZE_MAX - 2) / 3) { + DBG_ERR("convert_string_talloc: " + "srclen is %zu, destlen would wrap!\n", + srclen); + errno = EOPNOTSUPP; + return false; + } + destlen = srclen * 3; + + /* +2 is for ucs2 null termination. */ + ob = talloc_realloc(ctx, ob, char, destlen + 2); + + if (!ob) { + DEBUG(0, ("convert_string_talloc: realloc failed!\n")); + errno = ENOMEM; + return false; + } + outbuf = ob; + i_len = srclen; + o_len = destlen; + inbuf = (const char *)src; + + retval = smb_iconv(descriptor, + &inbuf, &i_len, + &outbuf, &o_len); + if(retval == (size_t)-1) { + const char *reason="unknown error"; + switch(errno) { + case EINVAL: + reason="Incomplete multibyte sequence"; + DBG_NOTICE("Conversion error: %s\n", + reason); + break; + case E2BIG: + reason = "output buffer is too small"; + DBG_ERR("Conversion error: %s\n", + reason); + break; + case EILSEQ: + reason="Illegal multibyte sequence"; + DBG_NOTICE("Conversion error: %s\n", + reason); + break; + default: + DBG_ERR("Conversion error: %s\n", + reason); + break; + } + /* smb_panic(reason); */ + TALLOC_FREE(ob); + return false; + } + + destlen = destlen - o_len; + /* Don't shrink unless we're reclaiming a lot of + * space. This is in the hot codepath and these + * reallocs *cost*. JRA. + */ + if (o_len > 1024) { + /* We're shrinking here so we know the +2 is safe from wrap. */ + ob = talloc_realloc(ctx,ob, char, destlen + 2); + } + + if (destlen && !ob) { + DEBUG(0, ("convert_string_talloc: out of memory!\n")); + errno = ENOMEM; + return false; + } + + *dest = ob; + + /* Must ucs2 null terminate in the extra space we allocated. */ + ob[destlen] = '\0'; + ob[destlen+1] = '\0'; + + /* Ensure we can never return a *converted_size of zero. */ + if (destlen == 0) { + /* As we're now returning false on a bad smb_iconv call, + this should never happen. But be safe anyway. */ + if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) { + destlen = 2; + } else { + destlen = 1; + } + } + + if (converted_size != NULL) { + *converted_size = destlen; + } + return true; +} + +/** + * Convert string from one encoding to another, with error checking. + * This version produces more logging information than + * convert_string_error(), but is otherwise functionally identical. + * + * @param src pointer to source string (multibyte or singlebyte) + * @param srclen length of the source string in bytes + * @param dest pointer to destination string (multibyte or singlebyte) + * @param destlen maximal length allowed for string + * @param converted_size the number of bytes occupied in the destination + * + * @returns true on success, false on fail. + **/ +_PUBLIC_ bool convert_string(charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen, + size_t *converted_size) +{ + return convert_string_handle(get_iconv_handle(), from, to, + src, srclen, + dest, destlen, converted_size); +} + +/** + * Convert string from one encoding to another, with error checking. + * This version is less verbose than convert_string(). + * + * @param src pointer to source string (multibyte or singlebyte) + * @param srclen length of the source string in bytes + * @param dest pointer to destination string (multibyte or singlebyte) + * @param destlen maximal length allowed for string + * @param converted_size the number of bytes occupied in the destination + * + * @returns true on success, false on fail. + **/ +_PUBLIC_ bool convert_string_error(charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen, + size_t *converted_size) +{ + return convert_string_error_handle(get_iconv_handle(), from, to, + src, srclen, + dest, destlen, converted_size); +} + +/** + * Convert between character sets, allocating a new buffer using talloc for the result. + * + * @param srclen length of source buffer. + * @param dest always set at least to NULL + * @param converted_size Size in bytes of the converted string + * @note -1 is not accepted for srclen. + * + * @returns boolean indication whether the conversion succeeded + **/ + +_PUBLIC_ bool convert_string_talloc(TALLOC_CTX *ctx, + charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t *converted_size) +{ + return convert_string_talloc_handle(ctx, get_iconv_handle(), + from, to, src, srclen, dest, + converted_size); +} diff --git a/lib/util/charset/iconv.c b/lib/util/charset/iconv.c new file mode 100644 index 0000000..131df64 --- /dev/null +++ b/lib/util/charset/iconv.c @@ -0,0 +1,1196 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/iconv.h" +#include "system/filesys.h" +#include "lib/util/byteorder.h" +#include "lib/util/dlinklist.h" +#include "lib/util/charset/charset.h" +#include "lib/util/charset/charset_proto.h" + +#ifdef HAVE_ICU_I18N +#include <unicode/ustring.h> +#include <unicode/utrans.h> +#endif + +#ifdef strcasecmp +#undef strcasecmp +#endif + +/** + * @file + * + * @brief Samba wrapper/stub for iconv character set conversion. + * + * iconv is the XPG2 interface for converting between character + * encodings. This file provides a Samba wrapper around it, and also + * a simple reimplementation that is used if the system does not + * implement iconv. + * + * Samba only works with encodings that are supersets of ASCII: ascii + * characters like whitespace can be tested for directly, multibyte + * sequences start with a byte with the high bit set, and strings are + * terminated by a nul byte. + * + * Note that the only function provided by iconv is conversion between + * characters. It doesn't directly support operations like + * uppercasing or comparison. We have to convert to UTF-16LE and + * compare there. + * + * @sa Samba Developers Guide + **/ + +static size_t ascii_pull (void *,const char **, size_t *, char **, size_t *); +static size_t ascii_push (void *,const char **, size_t *, char **, size_t *); +static size_t latin1_pull(void *,const char **, size_t *, char **, size_t *); +static size_t latin1_push(void *,const char **, size_t *, char **, size_t *); +static size_t utf8_pull (void *,const char **, size_t *, char **, size_t *); +static size_t utf8_push (void *,const char **, size_t *, char **, size_t *); +static size_t utf16_munged_pull(void *,const char **, size_t *, char **, size_t *); +static size_t ucs2hex_pull(void *,const char **, size_t *, char **, size_t *); +static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *); +static size_t iconv_copy (void *,const char **, size_t *, char **, size_t *); +static size_t iconv_swab (void *,const char **, size_t *, char **, size_t *); + +static const struct charset_functions builtin_functions[] = { + /* windows is closest to UTF-16 */ + { + .name = "UCS-2LE", + .pull = iconv_copy, + .push = iconv_copy + }, + { + .name = "UTF-16LE", + .pull = iconv_copy, + .push = iconv_copy + }, + { + .name = "UCS-2BE", + .pull = iconv_swab, + .push = iconv_swab + }, + { + .name = "UTF-16BE", + .pull = iconv_swab, + .push = iconv_swab + }, + + /* we include the UTF-8 alias to cope with differing locale settings */ + { + .name = "UTF8", + .pull = utf8_pull, + .push = utf8_push + }, + { + .name = "UTF-8", + .pull = utf8_pull, + .push = utf8_push + }, + + /* this handles the munging needed for String2Key */ + { + .name = "UTF16_MUNGED", + .pull = utf16_munged_pull, + .push = iconv_copy, + .samba_internal_charset = true + }, + + { + .name = "ASCII", + .pull = ascii_pull, + .push = ascii_push + }, + { + .name = "646", + .pull = ascii_pull, + .push = ascii_push + }, + { + .name = "ISO-8859-1", + .pull = latin1_pull, + .push = latin1_push + }, +#ifdef DEVELOPER + { + .name = "WEIRD", + .pull = weird_pull, + .push = weird_push, + .samba_internal_charset = true + }, +#endif +#ifdef DARWINOS + { + .name = "MACOSXFS", + .pull = macosxfs_encoding_pull, + .push = macosxfs_encoding_push, + .samba_internal_charset = true + }, +#endif + { + .name = "UCS2-HEX", + .pull = ucs2hex_pull, + .push = ucs2hex_push, + .samba_internal_charset = true + } +}; + +#ifdef HAVE_NATIVE_ICONV +/* if there was an error then reset the internal state, + this ensures that we don't have a shift state remaining for + character sets like SJIS */ +static size_t sys_iconv(void *cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + size_t ret = iconv((iconv_t)cd, + discard_const_p(char *, inbuf), inbytesleft, + outbuf, outbytesleft); + if (ret == (size_t)-1) iconv(cd, NULL, NULL, NULL, NULL); + return ret; +} +#endif + +#ifdef HAVE_ICU_I18N +static size_t sys_uconv(void *cd, + const char **inbuf, + size_t *inbytesleft, + char **outbuf, + size_t *outbytesleft) +{ + UTransliterator *t = (UTransliterator *)cd; + size_t bufsize = *inbytesleft * 2; + UChar ustr[bufsize]; + UChar *up = NULL; + char *p = NULL; + int32_t ustrlen; + int32_t limit; + int32_t converted_len; + size_t inbuf_consumed; + size_t outbut_consumed; + UErrorCode ue; + + /* Convert from UTF8 to UCS2 */ + ue = 0; + up = u_strFromUTF8(ustr, /* dst */ + bufsize, /* dst buflen */ + &converted_len, /* dst written */ + *inbuf, /* src */ + *inbytesleft, /* src length */ + &ue); + if (up == NULL || U_FAILURE(ue)) { + return -1; + } + if (converted_len > bufsize) { + /* + * u_strFromUTF8() returns the required size in + * converted_len. In theory this should never overflow as the + * ustr[] array is allocated with a size twice as big as + * inbytesleft and converted_len should be equal to inbytesleft, + * but you never know... + */ + errno = EOVERFLOW; + return -1; + } + inbuf_consumed = converted_len; + + /* + * The following transliteration function takes two parameters, the + * length of the text to be converted (converted_len) and a limit which + * may be smaller then converted_len. We just set limit to converted_len + * and also ignore the value returned in limit. + */ + limit = converted_len; + + /* Inplace transliteration */ + utrans_transUChars(t, + ustr, /* text */ + &converted_len, /* text length */ + bufsize, /* text buflen */ + 0, /* start */ + &limit, /* limit */ + &ue); + if (U_FAILURE(ue)) { + return -1; + } + if (converted_len > bufsize) { + /* + * In theory this should never happen as the ustr[] array is + * allocated with a size twice as big as inbytesleft and + * converted_len should be equal to inbytesleft, but you never + * know... + */ + errno = EOVERFLOW; + return -1; + } + ustrlen = converted_len; + + /* Convert from UCS2 back to UTF8 */ + ue = 0; + p = u_strToUTF8(*outbuf, /* dst */ + *outbytesleft, /* dst buflen */ + &converted_len, /* dst required length */ + ustr, /* src */ + ustrlen, /* src length */ + &ue); + if (p == NULL || U_FAILURE(ue)) { + return -1; + } + + outbut_consumed = converted_len; + if (converted_len > *outbytesleft) { + /* + * The caller's result buffer is too small... + */ + outbut_consumed = *outbytesleft; + } + + *inbuf += inbuf_consumed; + *inbytesleft -= inbuf_consumed; + *outbuf += outbut_consumed; + *outbytesleft -= outbut_consumed; + + return converted_len; +} +#endif + +/** + * This is a simple portable iconv() implementation. + * + * It only knows about a very small number of character sets - just + * enough that Samba works on systems that don't have iconv. + **/ +_PUBLIC_ size_t smb_iconv(smb_iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + /* in many cases we can go direct */ + if (cd->direct) { + return cd->direct(cd->cd_direct, + inbuf, inbytesleft, outbuf, outbytesleft); + } + + /* otherwise we have to do it chunks at a time */ + { +#ifndef SMB_ICONV_BUFSIZE +#define SMB_ICONV_BUFSIZE 2048 +#endif + size_t bufsize; + char cvtbuf[SMB_ICONV_BUFSIZE]; + + while (*inbytesleft > 0) { + char *bufp1 = cvtbuf; + const char *bufp2 = cvtbuf; + int saved_errno = errno; + bool pull_failed = false; + bufsize = SMB_ICONV_BUFSIZE; + + if (cd->pull(cd->cd_pull, + inbuf, inbytesleft, &bufp1, &bufsize) == -1 + && errno != E2BIG) { + saved_errno = errno; + pull_failed = true; + } + + bufsize = SMB_ICONV_BUFSIZE - bufsize; + + if (cd->push(cd->cd_push, + &bufp2, &bufsize, + outbuf, outbytesleft) == -1) { + return -1; + } else if (pull_failed) { + /* We want the pull errno if possible */ + errno = saved_errno; + return -1; + } + } + } + + return 0; +} + +static bool is_utf16(const char *name) +{ + return strcasecmp(name, "UCS-2LE") == 0 || + strcasecmp(name, "UTF-16LE") == 0; +} + +static int smb_iconv_t_destructor(smb_iconv_t hwd) +{ +#ifdef HAVE_ICU_I18N + /* + * This has to come first, as the cd_direct member won't be an iconv + * handle and must not be passed to iconv_close(). + */ + if (hwd->direct == sys_uconv) { + utrans_close(hwd->cd_direct); + return 0; + } +#endif +#ifdef HAVE_NATIVE_ICONV + if (hwd->cd_pull != NULL && hwd->cd_pull != (iconv_t)-1) + iconv_close(hwd->cd_pull); + if (hwd->cd_push != NULL && hwd->cd_push != (iconv_t)-1) + iconv_close(hwd->cd_push); + if (hwd->cd_direct != NULL && hwd->cd_direct != (iconv_t)-1) + iconv_close(hwd->cd_direct); +#endif + + return 0; +} + +_PUBLIC_ smb_iconv_t smb_iconv_open_ex(TALLOC_CTX *mem_ctx, const char *tocode, + const char *fromcode, bool use_builtin_handlers) +{ + smb_iconv_t ret; + const struct charset_functions *from=NULL, *to=NULL; + int i; + + ret = (smb_iconv_t)talloc_named(mem_ctx, + sizeof(*ret), + "iconv(%s,%s)", tocode, fromcode); + if (!ret) { + errno = ENOMEM; + return (smb_iconv_t)-1; + } + memset(ret, 0, sizeof(*ret)); + talloc_set_destructor(ret, smb_iconv_t_destructor); + + /* check for the simplest null conversion */ + if (strcmp(fromcode, tocode) == 0) { + ret->direct = iconv_copy; + return ret; + } + + /* check if we have a builtin function for this conversion */ + for (i=0;i<ARRAY_SIZE(builtin_functions);i++) { + if (strcasecmp(fromcode, builtin_functions[i].name) == 0) { + if (use_builtin_handlers || builtin_functions[i].samba_internal_charset) { + from = &builtin_functions[i]; + } + } + if (strcasecmp(tocode, builtin_functions[i].name) == 0) { + if (use_builtin_handlers || builtin_functions[i].samba_internal_charset) { + to = &builtin_functions[i]; + } + } + } + +#ifdef HAVE_NATIVE_ICONV + /* the from and to variables indicate a samba module or + * internal conversion, ret->pull and ret->push are + * initialised only in this block for iconv based + * conversions */ + + if (from == NULL) { + ret->cd_pull = iconv_open("UTF-16LE", fromcode); + if (ret->cd_pull == (iconv_t)-1) + ret->cd_pull = iconv_open("UCS-2LE", fromcode); + if (ret->cd_pull != (iconv_t)-1) { + ret->pull = sys_iconv; + } + } + + if (to == NULL) { + ret->cd_push = iconv_open(tocode, "UTF-16LE"); + if (ret->cd_push == (iconv_t)-1) + ret->cd_push = iconv_open(tocode, "UCS-2LE"); + if (ret->cd_push != (iconv_t)-1) { + ret->push = sys_iconv; + } + } +#endif + +#ifdef HAVE_ICU_I18N + if (strcasecmp(fromcode, "UTF8-NFD") == 0 && + strcasecmp(tocode, "UTF8-NFC") == 0) + { + U_STRING_DECL(t, "any-nfc", 7); + UErrorCode ue = 0; + + U_STRING_INIT(t, "any-nfc", 7); + + ret->cd_direct = utrans_openU(t, + strlen("any-nfc"), + UTRANS_FORWARD, + NULL, + 0, + NULL, + &ue); + if (U_FAILURE(ue)) { + return (smb_iconv_t)-1; + } + ret->direct = sys_uconv; + return ret; + } + + if (strcasecmp(fromcode, "UTF8-NFC") == 0 && + strcasecmp(tocode, "UTF8-NFD") == 0) + { + U_STRING_DECL(tname, "any-nfd", 7); + UErrorCode ue = 0; + + U_STRING_INIT(tname, "any-nfd", 7); + + ret->cd_direct = utrans_openU(tname, + 7, + UTRANS_FORWARD, + NULL, + 0, + NULL, + &ue); + if (U_FAILURE(ue)) { + return (smb_iconv_t)-1; + } + ret->direct = sys_uconv; + return ret; + } +#endif + + if (ret->pull == NULL && from == NULL) { + goto failed; + } + + if (ret->push == NULL && to == NULL) { + goto failed; + } + + /* check for conversion to/from ucs2 */ + if (is_utf16(fromcode) && to) { + ret->direct = to->push; + return ret; + } + if (is_utf16(tocode) && from) { + ret->direct = from->pull; + return ret; + } + +#ifdef HAVE_NATIVE_ICONV + if (is_utf16(fromcode)) { + ret->direct = sys_iconv; + ret->cd_direct = ret->cd_push; + ret->cd_push = NULL; + return ret; + } + if (is_utf16(tocode)) { + ret->direct = sys_iconv; + ret->cd_direct = ret->cd_pull; + ret->cd_pull = NULL; + return ret; + } +#endif + + /* the general case has to go via a buffer */ + if (!ret->pull) ret->pull = from->pull; + if (!ret->push) ret->push = to->push; + return ret; + +failed: + talloc_free(ret); + errno = EINVAL; + return (smb_iconv_t)-1; +} + +/* + simple iconv_open() wrapper + */ +_PUBLIC_ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) +{ + return smb_iconv_open_ex(NULL, tocode, fromcode, true); +} + +/* + simple iconv_close() wrapper +*/ +_PUBLIC_ int smb_iconv_close(smb_iconv_t cd) +{ + talloc_free(cd); + return 0; +} + + +/********************************************************************** + the following functions implement the builtin character sets in Samba + and also the "test" character sets that are designed to test + multi-byte character set support for english users +***********************************************************************/ + +/* + this takes an ASCII sequence and produces a UTF16 sequence + + The first 127 codepoints of latin1 matches the first 127 codepoints + of unicode, and so can be put into the first byte of UTF16LE + + */ + +static size_t ascii_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + if (((*inbuf)[0] & 0x7F) != (*inbuf)[0]) { + /* If this is multi-byte, then it isn't legal ASCII */ + errno = EILSEQ; + return -1; + } + (*outbuf)[0] = (*inbuf)[0]; + (*outbuf)[1] = 0; + (*inbytesleft) -= 1; + (*outbytesleft) -= 2; + (*inbuf) += 1; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +/* + this takes a UTF16 sequence and produces an ASCII sequence + + The first 127 codepoints of ASCII matches the first 127 codepoints + of unicode, and so can be read directly from the first byte of UTF16LE + + */ +static size_t ascii_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int ir_count=0; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + if (((*inbuf)[0] & 0x7F) != (*inbuf)[0] || + (*inbuf)[1] != 0) { + /* If this is multi-byte, then it isn't legal ASCII */ + errno = EILSEQ; + return -1; + } + (*outbuf)[0] = (*inbuf)[0]; + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return ir_count; +} + +/* + this takes a latin1/ISO-8859-1 sequence and produces a UTF16 sequence + + The first 256 codepoints of latin1 matches the first 256 codepoints + of unicode, and so can be put into the first byte of UTF16LE + + */ +static size_t latin1_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + (*outbuf)[0] = (*inbuf)[0]; + (*outbuf)[1] = 0; + (*inbytesleft) -= 1; + (*outbytesleft) -= 2; + (*inbuf) += 1; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +/* + this takes a UTF16 sequence and produces a latin1/ISO-8859-1 sequence + + The first 256 codepoints of latin1 matches the first 256 codepoints + of unicode, and so can be read directly from the first byte of UTF16LE + + */ +static size_t latin1_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int ir_count=0; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + (*outbuf)[0] = (*inbuf)[0]; + if ((*inbuf)[1] != 0) { + /* If this is multi-byte, then it isn't legal latin1 */ + errno = EILSEQ; + return -1; + } + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return ir_count; +} + +static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + uint8_t hi = 0, lo = 0; + bool ok; + + if ((*inbuf)[0] != '@') { + /* seven bit ascii case */ + (*outbuf)[0] = (*inbuf)[0]; + (*outbuf)[1] = 0; + (*inbytesleft) -= 1; + (*outbytesleft) -= 2; + (*inbuf) += 1; + (*outbuf) += 2; + continue; + } + /* it's a hex character */ + if (*inbytesleft < 5) { + errno = EINVAL; + return -1; + } + + ok = hex_byte(&(*inbuf)[1], &hi) && hex_byte(&(*inbuf)[3], &lo); + if (!ok) { + errno = EILSEQ; + return -1; + } + + (*outbuf)[0] = lo; + (*outbuf)[1] = hi; + (*inbytesleft) -= 5; + (*outbytesleft) -= 2; + (*inbuf) += 5; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +static size_t ucs2hex_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + char buf[6]; + + if ((*inbuf)[1] == 0 && + ((*inbuf)[0] & 0x80) == 0 && + (*inbuf)[0] != '@') { + (*outbuf)[0] = (*inbuf)[0]; + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + continue; + } + if (*outbytesleft < 5) { + errno = E2BIG; + return -1; + } + snprintf(buf, 6, "@%04x", SVAL(*inbuf, 0)); + memcpy(*outbuf, buf, 5); + (*inbytesleft) -= 2; + (*outbytesleft) -= 5; + (*inbuf) += 2; + (*outbuf) += 5; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return 0; +} + +static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int n; + + n = MIN(*inbytesleft, *outbytesleft); + + swab(*inbuf, *outbuf, (n&~1)); + if (n&1) { + (*outbuf)[n-1] = 0; + } + + (*inbytesleft) -= n; + (*outbytesleft) -= n; + (*inbuf) += n; + (*outbuf) += n; + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + + +static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int n; + + n = MIN(*inbytesleft, *outbytesleft); + + memmove(*outbuf, *inbuf, n); + + (*inbytesleft) -= n; + (*outbytesleft) -= n; + (*inbuf) += n; + (*outbuf) += n; + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +/* + this takes a UTF8 sequence and produces a UTF16 sequence + */ +static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + size_t in_left=*inbytesleft, out_left=*outbytesleft; + const uint8_t *c = (const uint8_t *)*inbuf; + uint8_t *uc = (uint8_t *)*outbuf; + + while (in_left >= 1 && out_left >= 2) { + if ((c[0] & 0x80) == 0) { + uc[0] = c[0]; + uc[1] = 0; + c += 1; + in_left -= 1; + out_left -= 2; + uc += 2; + continue; + } + + if ((c[0] & 0xe0) == 0xc0) { + if (in_left < 2 || + (c[1] & 0xc0) != 0x80) { + errno = EILSEQ; + goto error; + } + uc[1] = (c[0]>>2) & 0x7; + uc[0] = (c[0]<<6) | (c[1]&0x3f); + if (uc[1] == 0 && uc[0] < 0x80) { + /* this should have been a single byte */ + errno = EILSEQ; + goto error; + } + c += 2; + in_left -= 2; + out_left -= 2; + uc += 2; + continue; + } + + if ((c[0] & 0xf0) == 0xe0) { + unsigned int codepoint; + if (in_left < 3 || + (c[1] & 0xc0) != 0x80 || + (c[2] & 0xc0) != 0x80) { + errno = EILSEQ; + goto error; + } + codepoint = ((c[2] & 0x3f) | + ((c[1] & 0x3f) << 6) | + ((c[0] & 0x0f) << 12)); + + if (codepoint < 0x800) { + /* this should be a 1 or 2 byte sequence */ + errno = EILSEQ; + goto error; + } + if (codepoint >= 0xd800 && codepoint <= 0xdfff) { + /* + * This is an invalid codepoint, per + * RFC3629, as it encodes part of a + * UTF-16 surrogate pair for a + * character over U+10000, which ought + * to have been encoded as a four byte + * utf-8 sequence. + * + * Prior to Vista, Windows might + * sometimes produce invalid strings + * where a utf-16 sequence containing + * surrogate pairs was converted + * "verbatim" into utf-8, instead of + * encoding the actual codepoint. This + * format is sometimes called "WTF-8". + * + * If we were to support that, we'd + * have a branch here for the case + * where the codepoint is between + * 0xd800 and 0xdbff (a "high + * surrogate"), and read a *six* + * character sequence from there which + * would include a low surrogate. But + * that would undermine the + * hard-learnt principle that each + * character should only have one + * encoding. + */ + errno = EILSEQ; + goto error; + } + + uc[0] = codepoint & 0xff; + uc[1] = codepoint >> 8; + c += 3; + in_left -= 3; + out_left -= 2; + uc += 2; + continue; + } + + if ((c[0] & 0xf8) == 0xf0) { + unsigned int codepoint; + if (in_left < 4 || + (c[1] & 0xc0) != 0x80 || + (c[2] & 0xc0) != 0x80 || + (c[3] & 0xc0) != 0x80) { + errno = EILSEQ; + goto error; + } + codepoint = + (c[3]&0x3f) | + ((c[2]&0x3f)<<6) | + ((c[1]&0x3f)<<12) | + ((c[0]&0x7)<<18); + if (codepoint < 0x10000) { + /* reject UTF-8 characters that are not + minimally packed */ + errno = EILSEQ; + goto error; + } + if (codepoint > 0x10ffff) { + /* + * Unicode stops at 0x10ffff, and if + * we ignore that, we'll end up + * encoding the wrong characters in + * the surrogate pair. + */ + errno = EILSEQ; + goto error; + } + + codepoint -= 0x10000; + + if (out_left < 4) { + errno = E2BIG; + goto error; + } + + uc[0] = (codepoint>>10) & 0xFF; + uc[1] = (codepoint>>18) | 0xd8; + uc[2] = codepoint & 0xFF; + uc[3] = ((codepoint>>8) & 0x3) | 0xdc; + c += 4; + in_left -= 4; + out_left -= 4; + uc += 4; + continue; + } + + /* we don't handle 5 byte sequences */ + errno = EINVAL; + goto error; + } + + if (in_left > 0) { + errno = E2BIG; + goto error; + } + + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = (const char *)c; + *outbuf = (char *)uc; + return 0; + +error: + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = (const char *)c; + *outbuf = (char *)uc; + return -1; +} + + +/* + this takes a UTF16 sequence and produces a UTF8 sequence + */ +static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + size_t in_left=*inbytesleft, out_left=*outbytesleft; + uint8_t *c = (uint8_t *)*outbuf; + const uint8_t *uc = (const uint8_t *)*inbuf; + + while (in_left >= 2 && out_left >= 1) { + unsigned int codepoint; + + if (uc[1] == 0 && !(uc[0] & 0x80)) { + /* simplest case */ + c[0] = uc[0]; + in_left -= 2; + out_left -= 1; + uc += 2; + c += 1; + continue; + } + + if ((uc[1]&0xf8) == 0) { + /* next simplest case */ + if (out_left < 2) { + errno = E2BIG; + goto error; + } + c[0] = 0xc0 | (uc[0]>>6) | (uc[1]<<2); + c[1] = 0x80 | (uc[0] & 0x3f); + in_left -= 2; + out_left -= 2; + uc += 2; + c += 2; + continue; + } + + if ((uc[1] & 0xfc) == 0xdc) { + errno = EILSEQ; +#ifndef HAVE_ICONV_ERRNO_ILLEGAL_MULTIBYTE + if (in_left < 4) { + errno = EINVAL; + } +#endif + goto error; + } + + if ((uc[1] & 0xfc) != 0xd8) { + codepoint = uc[0] | (uc[1]<<8); + if (out_left < 3) { + errno = E2BIG; + goto error; + } + c[0] = 0xe0 | (codepoint >> 12); + c[1] = 0x80 | ((codepoint >> 6) & 0x3f); + c[2] = 0x80 | (codepoint & 0x3f); + + in_left -= 2; + out_left -= 3; + uc += 2; + c += 3; + continue; + } + + /* its the first part of a 4 byte sequence */ + if (in_left < 4) { + errno = EINVAL; + goto error; + } + if ((uc[3] & 0xfc) != 0xdc) { + errno = EILSEQ; + goto error; + } + codepoint = 0x10000 + (uc[2] | ((uc[3] & 0x3)<<8) | + (uc[0]<<10) | ((uc[1] & 0x3)<<18)); + + if (out_left < 4) { + errno = E2BIG; + goto error; + } + c[0] = 0xf0 | (codepoint >> 18); + c[1] = 0x80 | ((codepoint >> 12) & 0x3f); + c[2] = 0x80 | ((codepoint >> 6) & 0x3f); + c[3] = 0x80 | (codepoint & 0x3f); + + in_left -= 4; + out_left -= 4; + uc += 4; + c += 4; + } + + if (in_left == 1) { + errno = EINVAL; + goto error; + } + + if (in_left > 1) { + errno = E2BIG; + goto error; + } + + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = (const char *)uc; + *outbuf = (char *)c; + + return 0; + +error: + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = (const char *)uc; + *outbuf = (char *)c; + return -1; +} + + +/* + this takes a UTF16 munged sequence, modifies it according to the + string2key rules, and produces a UTF16 sequence + +The rules are: + + 1) any 0x0000 characters are mapped to 0x0001 + + 2) convert any instance of 0xD800 - 0xDBFF (high surrogate) + without an immediately following 0xDC00 - 0x0xDFFF (low surrogate) to + U+FFFD (OBJECT REPLACEMENT CHARACTER). + + 3) the same for any low surrogate that was not preceded by a high surrogate. + + */ +static size_t utf16_munged_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + size_t in_left=*inbytesleft, out_left=*outbytesleft; + uint8_t *c = (uint8_t *)*outbuf; + const uint8_t *uc = (const uint8_t *)*inbuf; + + while (in_left >= 2 && out_left >= 2) { + unsigned int codepoint = uc[0] | (uc[1]<<8); + + if (codepoint == 0) { + codepoint = 1; + } + + if ((codepoint & 0xfc00) == 0xd800) { + /* a high surrogate */ + unsigned int codepoint2; + if (in_left < 4) { + codepoint = 0xfffd; + goto codepoint16; + } + codepoint2 = uc[2] | (uc[3]<<8); + if ((codepoint2 & 0xfc00) != 0xdc00) { + /* high surrogate not followed by low + surrogate: convert to 0xfffd */ + codepoint = 0xfffd; + goto codepoint16; + } + if (out_left < 4) { + errno = E2BIG; + goto error; + } + memcpy(c, uc, 4); + in_left -= 4; + out_left -= 4; + uc += 4; + c += 4; + continue; + } + + if ((codepoint & 0xfc00) == 0xdc00) { + /* low surrogate not preceded by high + surrogate: convert to 0xfffd */ + codepoint = 0xfffd; + } + + codepoint16: + c[0] = codepoint & 0xFF; + c[1] = (codepoint>>8) & 0xFF; + + in_left -= 2; + out_left -= 2; + uc += 2; + c += 2; + continue; + } + + if (in_left == 1) { + errno = EINVAL; + goto error; + } + + if (in_left > 1) { + errno = E2BIG; + goto error; + } + + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = (const char *)uc; + *outbuf = (char *)c; + + return 0; + +error: + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = (const char *)uc; + *outbuf = (char *)c; + return -1; +} + + + diff --git a/lib/util/charset/pull_push.c b/lib/util/charset/pull_push.c new file mode 100644 index 0000000..8ec6498 --- /dev/null +++ b/lib/util/charset/pull_push.c @@ -0,0 +1,160 @@ +/* + Unix SMB/CIFS implementation. + Character set conversion Extensions + Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001 + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Simo Sorce 2001 + Copyright (C) Martin Pool 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "replace.h" +#include "system/locale.h" +#include "charset.h" + +/** + * Copy a string from a unix char* src to a UCS2 destination, + * allocating a buffer using talloc(). + * + * @param dest always set at least to NULL + * @param converted_size set to the number of bytes occupied by the string in + * the destination on success. + * + * @return true if new buffer was correctly allocated, and string was + * converted. + **/ +bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src, + size_t *converted_size) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len, + (void **)dest, converted_size); +} + +/** + * @brief Create a UTF-8 string from a unix charset string. + * + * The resulting UTF-8 string is talloc'ed. + * + * @param[in] ctx The talloc memory context. + * + * @param[in] dest A pointer to store the pointer to the talloc'ed UTF-8 + * string. + * + * @param[in] src The unix charset string to convert. + * + * @param[in] converted_size A pointer to store the length of the talloc'ed + * UTF-8 string including the nul-termination bytes. + * + * The destination string should be free'd using talloc_free() if no longer + * needed. + * + * @return True on success, false otherwise. + */ +bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, + size_t *converted_size) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, + (void**)dest, converted_size); +} + +/** + * Copy a string from a unix char* src to an ASCII destination, + * allocating a buffer using talloc(). + * + * @param dest always set at least to NULL + * + * @param converted_size The number of bytes occupied by the string in the destination + * @returns boolean indicating if the conversion was successful + **/ +bool push_ascii_talloc(TALLOC_CTX *mem_ctx, char **dest, const char *src, size_t *converted_size) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(mem_ctx, CH_UNIX, CH_DOS, src, src_len, + (void **)dest, converted_size); +} + +/** + * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * @param converted_size set to the number of bytes occupied by the string in + * the destination on success. + * + * @return true if new buffer was correctly allocated, and string was + * converted. + **/ + +bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src, + size_t *converted_size) +{ + size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t); + + *dest = NULL; + return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len, + (void **)dest, converted_size); +} + + +/** + * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * @param converted_size set to the number of bytes occupied by the string in + * the destination on success. + * + * @return true if new buffer was correctly allocated, and string was + * converted. + **/ + +bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, + size_t *converted_size) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, + (void **)dest, converted_size); +} + + +/** + * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * @param converted_size set to the number of bytes occupied by the string in + * the destination on success. + * + * @return true if new buffer was correctly allocated, and string was + * converted. + **/ + +bool pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, + size_t *converted_size) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, + (void **)dest, converted_size); +} diff --git a/lib/util/charset/tests/charset.c b/lib/util/charset/tests/charset.c new file mode 100644 index 0000000..547dc51 --- /dev/null +++ b/lib/util/charset/tests/charset.c @@ -0,0 +1,342 @@ +/* + Unix SMB/CIFS implementation. + test suite for the charcnv functions + + Copyright (C) Jelmer Vernooij 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" + +#undef strcasecmp +#undef strncasecmp + +struct torture_suite *torture_local_charset(TALLOC_CTX *mem_ctx); + +static bool test_toupper_m(struct torture_context *tctx) +{ + torture_assert_int_equal(tctx, toupper_m('c'), 'C', "c"); + torture_assert_int_equal(tctx, toupper_m('Z'), 'Z', "z"); + torture_assert_int_equal(tctx, toupper_m(0xFFFF4565), 0xFFFF4565, "0xFFFF4565"); + return true; +} + +static bool test_tolower_m(struct torture_context *tctx) +{ + torture_assert_int_equal(tctx, tolower_m('C'), 'c', "c"); + torture_assert_int_equal(tctx, tolower_m('z'), 'z', "z"); + torture_assert_int_equal(tctx, tolower_m(0xFFFF4565), 0xFFFF4565, "0xFFFF4565"); + return true; +} + +static bool test_codepoint_cmpi(struct torture_context *tctx) +{ + torture_assert_int_equal(tctx, codepoint_cmpi('a', 'a'), 0, "same char"); + torture_assert_int_equal(tctx, codepoint_cmpi('A', 'a'), 0, "upcase version"); + torture_assert_int_equal(tctx, codepoint_cmpi('b', 'a'), 1, "right diff"); + torture_assert_int_equal(tctx, codepoint_cmpi('a', 'b'), -1, "right diff"); + return true; +} + +static bool test_strcasecmp(struct torture_context *tctx) +{ + torture_assert_int_equal(tctx, strcasecmp("foo", "bar"), 4, "different strings both lower"); + torture_assert_int_equal(tctx, strcasecmp("foo", "Bar"), 4, "different strings lower/upper"); + torture_assert_int_equal(tctx, strcasecmp("Foo", "bar"), 4, "different strings upper/lower"); + torture_assert_int_equal(tctx, strcasecmp("AFoo", "_bar"), 2, "different strings upper/lower"); + torture_assert_int_equal(tctx, strcasecmp("foo", "foo"), 0, "same case strings"); + torture_assert_int_equal(tctx, strcasecmp("foo", "Foo"), 0, "different case strings"); + + /* + * Note that strcasecmp() doesn't allow NULL arguments + */ + return true; +} + +static bool test_strcasecmp_m(struct torture_context *tctx) +{ + /* file.{accented e} in iso8859-1 */ + const char file_iso8859_1[7] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xe9, 0 }; + /* file.{accented e} in utf8 */ + const char file_utf8[8] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xc3, 0xa9, 0 }; + torture_assert_int_equal(tctx, strcasecmp_m("foo", "bar"), 4, "different strings both lower"); + torture_assert_int_equal(tctx, strcasecmp_m("foo", "Bar"), 4, "different strings lower/upper"); + torture_assert_int_equal(tctx, strcasecmp_m("Foo", "bar"), 4, "different strings upper/lower"); + torture_assert_int_equal(tctx, strcasecmp_m("AFoo", "_bar"), 2, "different strings upper/lower"); + torture_assert_int_equal(tctx, strcasecmp_m("foo", "foo"), 0, "same case strings"); + torture_assert_int_equal(tctx, strcasecmp_m("foo", "Foo"), 0, "different case strings"); + torture_assert_int_equal(tctx, strcasecmp_m(NULL, "Foo"), -1, "one NULL"); + torture_assert_int_equal(tctx, strcasecmp_m("foo", NULL), 1, "other NULL"); + torture_assert_int_equal(tctx, strcasecmp_m(NULL, NULL), 0, "both NULL"); + torture_assert_int_equal(tctx, strcasecmp_m(file_iso8859_1, file_utf8), 38, + "file.{accented e} should differ"); + return true; +} + + +static bool test_strequal_m(struct torture_context *tctx) +{ + torture_assert(tctx, !strequal_m("foo", "bar"), "different strings"); + torture_assert(tctx, strequal_m("foo", "foo"), "same case strings"); + torture_assert(tctx, strequal_m("foo", "Foo"), "different case strings"); + torture_assert(tctx, !strequal_m(NULL, "Foo"), "one NULL"); + torture_assert(tctx, !strequal_m("foo", NULL), "other NULL"); + torture_assert(tctx, strequal_m(NULL, NULL), "both NULL"); + return true; +} + +static bool test_strcsequal(struct torture_context *tctx) +{ + torture_assert(tctx, !strcsequal("foo", "bar"), "different strings"); + torture_assert(tctx, strcsequal("foo", "foo"), "same case strings"); + torture_assert(tctx, !strcsequal("foo", "Foo"), "different case strings"); + torture_assert(tctx, !strcsequal(NULL, "Foo"), "one NULL"); + torture_assert(tctx, !strcsequal("foo", NULL), "other NULL"); + torture_assert(tctx, strcsequal(NULL, NULL), "both NULL"); + return true; +} + +static bool test_string_replace_m(struct torture_context *tctx) +{ + char data[6] = "bla"; + string_replace_m(data, 'b', 'c'); + torture_assert_str_equal(tctx, data, "cla", "first char replaced"); + memcpy(data, "bab", 4); + string_replace_m(data, 'b', 'c'); + torture_assert_str_equal(tctx, data, "cac", "other chars replaced"); + memcpy(data, "bba", 4); + string_replace_m(data, 'b', 'c'); + torture_assert_str_equal(tctx, data, "cca", "other chars replaced"); + memcpy(data, "blala", 6); + string_replace_m(data, 'o', 'c'); + torture_assert_str_equal(tctx, data, "blala", "no chars replaced"); + string_replace_m(NULL, 'b', 'c'); + return true; +} + +static bool test_strncasecmp(struct torture_context *tctx) +{ + torture_assert_int_equal(tctx, strncasecmp("foo", "bar", 3), 4, "different strings both lower"); + torture_assert_int_equal(tctx, strncasecmp("foo", "Bar", 3), 4, "different strings lower/upper"); + torture_assert_int_equal(tctx, strncasecmp("Foo", "bar", 3), 4, "different strings upper/lower"); + torture_assert_int_equal(tctx, strncasecmp("AFoo", "_bar", 4), 2, "different strings upper/lower"); + torture_assert_int_equal(tctx, strncasecmp("foo", "foo", 3), 0, "same case strings"); + torture_assert_int_equal(tctx, strncasecmp("foo", "Foo", 3), 0, "different case strings"); + torture_assert_int_equal(tctx, strncasecmp("fool", "Foo", 3),0, "different case strings"); + torture_assert_int_equal(tctx, strncasecmp("fool", "Fool", 40), 0, "over size"); + torture_assert_int_equal(tctx, strncasecmp("BLA", "Fool", 0),0, "empty"); + + /* + * Note that strncasecmp() doesn't allow NULL arguments + */ + return true; +} + +static bool test_strncasecmp_m(struct torture_context *tctx) +{ + /* file.{accented e} in iso8859-1 */ + const char file_iso8859_1[7] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xe9, 0 }; + /* file.{accented e} in utf8 */ + const char file_utf8[8] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xc3, 0xa9, 0 }; + torture_assert_int_equal(tctx, strncasecmp_m("foo", "bar", 3), 4, "different strings both lower"); + torture_assert_int_equal(tctx, strncasecmp_m("foo", "Bar", 3), 4, "different strings lower/upper"); + torture_assert_int_equal(tctx, strncasecmp_m("Foo", "bar", 3), 4, "different strings upper/lower"); + torture_assert_int_equal(tctx, strncasecmp_m("AFoo", "_bar", 4), 2, "different strings upper/lower"); + torture_assert_int_equal(tctx, strncasecmp_m("foo", "foo", 3), 0, "same case strings"); + torture_assert_int_equal(tctx, strncasecmp_m("foo", "Foo", 3), 0, "different case strings"); + torture_assert_int_equal(tctx, strncasecmp_m("fool", "Foo", 3),0, "different case strings"); + torture_assert_int_equal(tctx, strncasecmp_m("fool", "Fool", 40), 0, "over size"); + torture_assert_int_equal(tctx, strncasecmp_m("BLA", "Fool", 0),0, "empty"); + torture_assert_int_equal(tctx, strncasecmp_m(NULL, "Foo", 3), -1, "one NULL"); + torture_assert_int_equal(tctx, strncasecmp_m("foo", NULL, 3), 1, "other NULL"); + torture_assert_int_equal(tctx, strncasecmp_m(NULL, NULL, 3), 0, "both NULL"); + torture_assert_int_equal(tctx, strncasecmp_m(file_iso8859_1, file_utf8, 6), 38, + "file.{accented e} should differ"); + return true; +} + +static bool test_next_token_null(struct torture_context *tctx) +{ + char buf[20]; + torture_assert(tctx, !next_token(NULL, buf, " ", 20), "null ptr works"); + return true; +} + +static bool test_next_token(struct torture_context *tctx) +{ + const char *teststr = "foo bar bla"; + char buf[20]; + torture_assert(tctx, next_token(&teststr, buf, " ", 20), "finding token works"); + torture_assert_str_equal(tctx, buf, "foo", "token matches"); + torture_assert_str_equal(tctx, teststr, "bar bla", "ptr modified correctly"); + + torture_assert(tctx, next_token(&teststr, buf, " ", 20), "finding token works"); + torture_assert_str_equal(tctx, buf, "bar", "token matches"); + torture_assert_str_equal(tctx, teststr, "bla", "ptr modified correctly"); + + torture_assert(tctx, next_token(&teststr, buf, " ", 20), "finding token works"); + torture_assert_str_equal(tctx, buf, "bla", "token matches"); + torture_assert_str_equal(tctx, teststr, "", "ptr modified correctly"); + + torture_assert(tctx, !next_token(&teststr, buf, " ", 20), "finding token doesn't work"); + return true; +} + +static bool test_next_token_implicit_sep(struct torture_context *tctx) +{ + const char *teststr = "foo\tbar\n bla"; + char buf[20]; + torture_assert(tctx, next_token(&teststr, buf, NULL, 20), "finding token works"); + torture_assert_str_equal(tctx, buf, "foo", "token matches"); + torture_assert_str_equal(tctx, teststr, "bar\n bla", "ptr modified correctly"); + + torture_assert(tctx, next_token(&teststr, buf, NULL, 20), "finding token works"); + torture_assert_str_equal(tctx, buf, "bar", "token matches"); + torture_assert_str_equal(tctx, teststr, " bla", "ptr modified correctly"); + + torture_assert(tctx, next_token(&teststr, buf, NULL, 20), "finding token works"); + torture_assert_str_equal(tctx, buf, "bla", "token matches"); + torture_assert_str_equal(tctx, teststr, "", "ptr modified correctly"); + + torture_assert(tctx, !next_token(&teststr, buf, NULL, 20), "finding token doesn't work"); + return true; +} + +static bool test_next_token_seps(struct torture_context *tctx) +{ + const char *teststr = ",foo bla"; + char buf[20]; + torture_assert(tctx, next_token(&teststr, buf, ",", 20), "finding token works"); + torture_assert_str_equal(tctx, buf, "foo bla", "token matches"); + torture_assert_str_equal(tctx, teststr, "", "ptr modified correctly"); + + torture_assert(tctx, !next_token(&teststr, buf, ",", 20), "finding token doesn't work"); + return true; +} + +static bool test_next_token_quotes(struct torture_context *tctx) +{ + const char *teststr = "\"foo bar\" bla"; + char buf[20]; + torture_assert(tctx, next_token(&teststr, buf, " ", 20), "finding token works"); + torture_assert_str_equal(tctx, buf, "foo bar", "token matches"); + torture_assert_str_equal(tctx, teststr, "bla", "ptr modified correctly"); + + torture_assert(tctx, next_token(&teststr, buf, " ", 20), "finding token works"); + torture_assert_str_equal(tctx, buf, "bla", "token matches"); + torture_assert_str_equal(tctx, teststr, "", "ptr modified correctly"); + + torture_assert(tctx, !next_token(&teststr, buf, " ", 20), "finding token doesn't work"); + return true; +} + +static bool test_next_token_quote_wrong(struct torture_context *tctx) +{ + const char *teststr = "\"foo bar bla"; + char buf[20]; + torture_assert(tctx, next_token(&teststr, buf, " ", 20), "finding token works"); + torture_assert_str_equal(tctx, buf, "foo bar bla", "token matches"); + torture_assert_str_equal(tctx, teststr, "", "ptr modified correctly"); + + torture_assert(tctx, !next_token(&teststr, buf, " ", 20), "finding token doesn't work"); + return true; +} + +static bool test_strlen_m(struct torture_context *tctx) +{ + torture_assert_int_equal(tctx, strlen_m("foo"), 3, "simple len"); + torture_assert_int_equal(tctx, strlen_m("foo\x83l"), 6, "extended len"); + torture_assert_int_equal(tctx, strlen_m(""), 0, "empty"); + torture_assert_int_equal(tctx, strlen_m(NULL), 0, "NULL"); + return true; +} + +static bool test_strlen_m_term(struct torture_context *tctx) +{ + torture_assert_int_equal(tctx, strlen_m_term("foo"), 4, "simple len"); + torture_assert_int_equal(tctx, strlen_m_term("foo\x83l"), 7, "extended len"); + torture_assert_int_equal(tctx, strlen_m_term(""), 1, "empty"); + torture_assert_int_equal(tctx, strlen_m_term(NULL), 0, "NULL"); + return true; +} + +static bool test_strlen_m_term_null(struct torture_context *tctx) +{ + torture_assert_int_equal(tctx, strlen_m_term_null("foo"), 4, "simple len"); + torture_assert_int_equal(tctx, strlen_m_term_null("foo\x83l"), 7, "extended len"); + torture_assert_int_equal(tctx, strlen_m_term_null(""), 0, "empty"); + torture_assert_int_equal(tctx, strlen_m_term_null(NULL), 0, "NULL"); + return true; +} + +static bool test_strhaslower(struct torture_context *tctx) +{ + torture_assert(tctx, strhaslower("a"), "one low char"); + torture_assert(tctx, strhaslower("aB"), "one low, one up char"); + torture_assert(tctx, !strhaslower("B"), "one up char"); + torture_assert(tctx, !strhaslower(""), "empty string"); + torture_assert(tctx, !strhaslower("3"), "one digit"); + return true; +} + +static bool test_strhasupper(struct torture_context *tctx) +{ + torture_assert(tctx, strhasupper("B"), "one up char"); + torture_assert(tctx, strhasupper("aB"), "one low, one up char"); + torture_assert(tctx, !strhasupper("a"), "one low char"); + torture_assert(tctx, !strhasupper(""), "empty string"); + torture_assert(tctx, !strhasupper("3"), "one digit"); + return true; +} + +static bool test_count_chars_m(struct torture_context *tctx) +{ + torture_assert_int_equal(tctx, count_chars_m("foo", 'o'), 2, "simple"); + torture_assert_int_equal(tctx, count_chars_m("", 'o'), 0, "empty"); + torture_assert_int_equal(tctx, count_chars_m("bla", 'o'), 0, "none"); + torture_assert_int_equal(tctx, count_chars_m("bla", '\0'), 0, "null"); + return true; +} + +struct torture_suite *torture_local_charset(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "charset"); + + torture_suite_add_simple_test(suite, "toupper_m", test_toupper_m); + torture_suite_add_simple_test(suite, "tolower_m", test_tolower_m); + torture_suite_add_simple_test(suite, "codepoint_cmpi", test_codepoint_cmpi); + torture_suite_add_simple_test(suite, "strcasecmp", test_strcasecmp); + torture_suite_add_simple_test(suite, "strcasecmp_m", test_strcasecmp_m); + torture_suite_add_simple_test(suite, "strequal_m", test_strequal_m); + torture_suite_add_simple_test(suite, "strcsequal", test_strcsequal); + torture_suite_add_simple_test(suite, "string_replace_m", test_string_replace_m); + torture_suite_add_simple_test(suite, "strncasecmp", test_strncasecmp); + torture_suite_add_simple_test(suite, "strncasecmp_m", test_strncasecmp_m); + torture_suite_add_simple_test(suite, "next_token", test_next_token); + torture_suite_add_simple_test(suite, "next_token_null", test_next_token_null); + torture_suite_add_simple_test(suite, "next_token_implicit_sep", test_next_token_implicit_sep); + torture_suite_add_simple_test(suite, "next_token_quotes", test_next_token_quotes); + torture_suite_add_simple_test(suite, "next_token_seps", test_next_token_seps); + torture_suite_add_simple_test(suite, "next_token_quote_wrong", test_next_token_quote_wrong); + torture_suite_add_simple_test(suite, "strlen_m", test_strlen_m); + torture_suite_add_simple_test(suite, "strlen_m_term", test_strlen_m_term); + torture_suite_add_simple_test(suite, "strlen_m_term_null", test_strlen_m_term_null); + torture_suite_add_simple_test(suite, "strhaslower", test_strhaslower); + torture_suite_add_simple_test(suite, "strhasupper", test_strhasupper); + torture_suite_add_simple_test(suite, "count_chars_m", test_count_chars_m); + + return suite; +} diff --git a/lib/util/charset/tests/convert_string.c b/lib/util/charset/tests/convert_string.c new file mode 100644 index 0000000..6400ce1 --- /dev/null +++ b/lib/util/charset/tests/convert_string.c @@ -0,0 +1,2196 @@ +/* + Unix SMB/CIFS implementation. + test suite for the charcnv functions + + Copyright (C) Andrew Bartlett 2011 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "lib/util/charset/charset.h" +#include "param/param.h" +#include "lib/util/base64.h" + +struct torture_suite *torture_local_convert_string_handle(TALLOC_CTX *mem_ctx); +struct torture_suite *torture_local_string_case_handle(TALLOC_CTX *mem_ctx); +struct torture_suite *torture_local_convert_string(TALLOC_CTX *mem_ctx); +struct torture_suite *torture_local_string_case(TALLOC_CTX *mem_ctx); + +/* The text below is in ancient and a latin charset transliteration of + * greek, and an english translation. It from Apology by Plato and sourced from + * http://en.wikipedia.org/w/index.php?title=Ancient_Greek&oldid=421361065#Example_text + */ + +const char *plato_english_ascii = + "What you, men of Athens, have learned from my accusers, I do not" + " know: but I, for my part, nearly forgot who I was thanks to them since" + " they spoke so persuasively. And yet, of the truth, they have spoken," + " one might say, nothing at all."; + +const char *plato_english_utf16le_base64 = + "VwBoAGEAdAAgAHkAbwB1ACwAIABtAGUAbgAgAG8AZgAgAEEAdABoAGUAbgBzACwAIABoAGEAdgBl" + "ACAAbABlAGEAcgBuAGUAZAAgAGYAcgBvAG0AIABtAHkAIABhAGMAYwB1AHMAZQByAHMALAAgAEkA" + "IABkAG8AIABuAG8AdAAgAGsAbgBvAHcAOgAgAGIAdQB0ACAASQAsACAAZgBvAHIAIABtAHkAIABw" + "AGEAcgB0ACwAIABuAGUAYQByAGwAeQAgAGYAbwByAGcAbwB0ACAAdwBoAG8AIABJACAAdwBhAHMA" + "IAB0AGgAYQBuAGsAcwAgAHQAbwAgAHQAaABlAG0AIABzAGkAbgBjAGUAIAB0AGgAZQB5ACAAcwBw" + "AG8AawBlACAAcwBvACAAcABlAHIAcwB1AGEAcwBpAHYAZQBsAHkALgAgAEEAbgBkACAAeQBlAHQA" + "LAAgAG8AZgAgAHQAaABlACAAdAByAHUAdABoACwAIAB0AGgAZQB5ACAAaABhAHYAZQAgAHMAcABv" + "AGsAZQBuACwAIABvAG4AZQAgAG0AaQBnAGgAdAAgAHMAYQB5ACwAIABuAG8AdABoAGkAbgBnACAA" + "YQB0ACAAYQBsAGwALgA="; + +static const char *plato_utf8_base64 = + "4b2Nz4TOuSDOvOG9ss69IOG9kc68zrXhv5bPgiwg4b2mIOG8hM69zrTPgc61z4IgzobOuM63zr3O" + "seG/ls6/zrksIM+AzrXPgM+Mzr3OuM6xz4TOtSDhvZHPgOG9uCDPhOG/ts69IOG8kM684b+2zr0g" + "zrrOsc+EzrfOs8+Mz4HPic69LCDOv+G9kM66IM6/4by2zrTOsTog4byQzrPhvbwgzrQnIM6/4b2W" + "zr0gzrrOseG9tiDOseG9kM+E4b24z4Ig4b2Rz4AnIM6x4b2Qz4Thv7bOvSDhvYDOu86vzrPOv8+F" + "IOG8kM68zrHPhc+Ezr/hv6Yg4byQz4DOtc67zrHOuM+MzrzOt869LCDOv+G9lc+Ez4kgz4DOuc64" + "zrHOveG/ts+CIOG8lM67zrXOs86/zr0uIM6azrHOr8+Ezr/OuSDhvIDOu863zrjOrc+CIM6zzrUg" + "4b2hz4Ig4byUz4DOv8+CIM614bywz4DOteG/ls69IM6/4b2QzrThvbLOvSDOteG8sM+Bzq7Ous6x" + "z4POuc69Lg=="; + +static const char *plato_utf16le_base64 = + "TR/EA7kDIAC8A3IfvQMgAFEfvAO1A9YfwgMsACAAZh8gAAQfvQO0A8EDtQPCAyAAhgO4A7cDvQOx" + "A9YfvwO5AywAIADAA7UDwAPMA70DuAOxA8QDtQMgAFEfwAN4HyAAxAP2H70DIAAQH7wD9h+9AyAA" + "ugOxA8QDtwOzA8wDwQPJA70DLAAgAL8DUB+6AyAAvwM2H7QDsQM6ACAAEB+zA3wfIAC0AycAIAC/" + "A1YfvQMgALoDsQN2HyAAsQNQH8QDeB/CAyAAUR/AAycAIACxA1AfxAP2H70DIABAH7sDrwOzA78D" + "xQMgABAfvAOxA8UDxAO/A+YfIAAQH8ADtQO7A7EDuAPMA7wDtwO9AywAIAC/A1UfxAPJAyAAwAO5" + "A7gDsQO9A/YfwgMgABQfuwO1A7MDvwO9Ay4AIACaA7EDrwPEA78DuQMgAAAfuwO3A7gDrQPCAyAA" + "swO1AyAAYR/CAyAAFB/AA78DwgMgALUDMB/AA7UD1h+9AyAAvwNQH7QDch+9AyAAtQMwH8EDrgO6" + "A7EDwwO5A70DLgA="; + +static const char *plato_latin_utf8_base64 = + "SMOzdGkgbcOobiBodW1lw65zLCDDtCDDoW5kcmVzIEF0aMSTbmHDrm9pLCBwZXDDs250aGF0ZSBo" + "dXDDsiB0w7RuIGVtw7RuIGthdMSTZ8OzcsWNbiwgb3VrIG/DrmRhOiBlZ+G5kSBkJyBvw7tuIGth" + "w6wgYXV0w7JzIGh1cCcgYXV0xY1uIG9sw61nb3UgZW1hdXRvw7sgZXBlbGF0aMOzbcSTbiwgaG/D" + "unTFjSBwaXRoYW7DtHMgw6lsZWdvbi4gS2HDrXRvaSBhbMSTdGjDqXMgZ2UgaMWNcyDDqXBvcyBl" + "aXBlw65uIG91ZMOobiBlaXLhuJdrYXNpbi4="; + +static const char *plato_latin_utf16le_base64 = + "SADzAHQAaQAgAG0A6ABuACAAaAB1AG0AZQDuAHMALAAgAPQAIADhAG4AZAByAGUAcwAgAEEAdABo" + "ABMBbgBhAO4AbwBpACwAIABwAGUAcADzAG4AdABoAGEAdABlACAAaAB1AHAA8gAgAHQA9ABuACAA" + "ZQBtAPQAbgAgAGsAYQB0ABMBZwDzAHIATQFuACwAIABvAHUAawAgAG8A7gBkAGEAOgAgAGUAZwBR" + "HiAAZAAnACAAbwD7AG4AIABrAGEA7AAgAGEAdQB0APIAcwAgAGgAdQBwACcAIABhAHUAdABNAW4A" + "IABvAGwA7QBnAG8AdQAgAGUAbQBhAHUAdABvAPsAIABlAHAAZQBsAGEAdABoAPMAbQATAW4ALAAg" + "AGgAbwD6AHQATQEgAHAAaQB0AGgAYQBuAPQAcwAgAOkAbABlAGcAbwBuAC4AIABLAGEA7QB0AG8A" + "aQAgAGEAbAATAXQAaADpAHMAIABnAGUAIABoAE0BcwAgAOkAcABvAHMAIABlAGkAcABlAO4AbgAg" + "AG8AdQBkAOgAbgAgAGUAaQByABceawBhAHMAaQBuAC4A"; + +static const char *gd_utf8_base64 = "R8O8bnRoZXIgRGVzY2huZXI="; +static const char *gd_utf8_upper_base64 = "R8OcTlRIRVIgREVTQ0hORVI="; +static const char *gd_utf8_lower_base64 = "Z8O8bnRoZXIgZGVzY2huZXI="; +static const char *gd_cp850_base64 = "R4FudGhlciBEZXNjaG5lcg=="; +static const char *gd_cp850_upper_base64 = "R5pOVEhFUiBERVNDSE5FUg=="; +static const char *gd_cp850_lower_base64 = "Z4FudGhlciBkZXNjaG5lcg=="; +static const char *gd_iso8859_1_base64 = "R/xudGhlciBEZXNjaG5lcg=="; +static const char *gd_utf16le_base64 = "RwD8AG4AdABoAGUAcgAgAEQAZQBzAGMAaABuAGUAcgA="; +/* täst */ +static const char *utf8_nfc_base64 = "dMOkc3QA"; +/* täst, where ä = a + combining diaeresis */ +static const char *utf8_nfd_base64 = "dGHMiHN0AA=="; + +/* + * These cp850 bytes correspond to high Unicode codes, stretching out to + * 3-byte sequences in utf-8. + */ +static const char *cp850_high_points = "\xb9\xba\xbb\xbc\xcd\xce"; +static const char *utf8_high_points = "╣║╗╝═╬"; + +static bool test_cp850_high_points(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle = NULL; + DATA_BLOB cp850 = data_blob_string_const(cp850_high_points); + DATA_BLOB utf8; + DATA_BLOB cp850_return; + + iconv_handle = get_iconv_testing_handle(tctx, "CP850", "UTF8", + lpcfg_parm_bool(tctx->lp_ctx, + NULL, + "iconv", + "use_builtin_handlers", + true)); + + torture_assert(tctx, iconv_handle, "creating iconv handle"); + + torture_assert(tctx, + convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_UTF8, + cp850.data, cp850.length, + (void *)&utf8.data, &utf8.length), + "conversion from CP850 to UTF-8"); + + torture_assert(tctx, utf8.length == cp850.length * 3, + "CP850 high bytes expand to the right size"); + + torture_assert(tctx, + memcmp(utf8.data, utf8_high_points, utf8.length) == 0, + "cp850 converted to utf8 matches expected value"); + + torture_assert(tctx, + convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_DOS, + utf8.data, utf8.length, + (void *)&cp850_return.data, + &cp850_return.length), + "conversion from UTF-8 back to CP850"); + + torture_assert(tctx, data_blob_cmp(&cp850_return, &cp850) == 0, + "UTF-8 returned to CP850 matches the original"); + return true; +} + + +static bool test_gd_iso8859_cp850_handle(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64); + DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64); + DATA_BLOB gd_iso8859_1 = base64_decode_data_blob(gd_iso8859_1_base64); + DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64); + DATA_BLOB gd_output; + DATA_BLOB gd_output2; + + talloc_steal(tctx, gd_utf8.data); + talloc_steal(tctx, gd_cp850.data); + talloc_steal(tctx, gd_iso8859_1.data); + talloc_steal(tctx, gd_utf16le.data); + + iconv_handle = get_iconv_testing_handle(tctx, "ISO-8859-1", "CP850", + lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + torture_assert(tctx, iconv_handle, "getting iconv handle"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_DOS, + gd_utf8.data, gd_utf8.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from UTF8 to (dos charset) ISO-8859-1"); + torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF8 to (dos charset) ISO-8859-1 incorrect"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_DOS, + gd_utf8.data, gd_utf8.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length), + "conversion from UTF8 to (dos charset) ISO-8859-1"); + torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF8 to (dos charset) ISO-8859-1 incorrect"); + + /* Short output handling confirmation */ + gd_output.length = 1; + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_DOS, + gd_utf8.data, gd_utf8.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF8 to (dos charset) ISO-8859-1 should fail due to too short"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to (dos charset) ISO-8859-1 should fail E2BIG"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); + torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF8 to (dos charset) ISO-8859-1 incorrect"); + + /* Short output handling confirmation */ + gd_output.length = 2; + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_DOS, + gd_utf8.data, gd_utf8.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF8 to (dos charset) ISO-8859-1 should fail due to too short"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to (dos charset) ISO-8859-1 should fail E2BIG"); + torture_assert_int_equal(tctx, gd_output.length, 2, "Should only get 2 char of output"); + + /* Short input handling confirmation */ + gd_output.length = gd_iso8859_1.length; + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_DOS, + gd_utf8.data, 2, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF8 to (dos charset) ISO-8859-1 should fail due to too short"); + torture_assert_errno_equal(tctx, EILSEQ, "conversion from short UTF8 to (dos charset) ISO-8859-1 should fail EINVAL"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); + + /* Short output handling confirmation */ + gd_output.length = 1; + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + gd_utf16le.data, gd_utf16le.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF16 to UTF8 should fail due to too short"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to (utf8 charset) ISO-8859-1 should fail E2BIG"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); + torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF16 to UTF8 incorrect"); + + /* Short output handling confirmation */ + gd_output.length = 3; + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + gd_utf16le.data, gd_utf16le.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF16 to UTF8 should fail due to too short"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to (utf8 charset) ISO-8859-1 should fail E2BIG"); + torture_assert_int_equal(tctx, gd_output.length, 3, "Should get 3 bytes output for UTF8"); + + /* Short input handling confirmation */ + gd_output.length = gd_utf8.length; + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + gd_utf16le.data, 3, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF16 to UTF8 should fail due to too short"); + torture_assert_errno_equal(tctx, EINVAL, "conversion from short UTF16 to UTF8 should fail EINVAL"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UNIX, + gd_utf8.data, gd_utf8.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from UTF8 to (unix charset) CP850"); + torture_assert_data_blob_equal(tctx, gd_output, gd_cp850, "conversion from UTF8 to (unix charset) CP850 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UTF8, + gd_utf8.data, gd_utf8.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from UTF8 to UTF8"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF8 to UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_DOS, + gd_utf16le.data, gd_utf16le.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from UTF16LE to (dos charset) ISO-8859-1"); + torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF16LE to (dos charset) ISO-8859-1 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_UTF16LE, + gd_output.data, gd_output.length, + (void *)&gd_output2.data, &gd_output2.length), + "round trip conversion from (dos charset) ISO-8859-1 back to UTF16LE"); + torture_assert_data_blob_equal(tctx, gd_output2, gd_utf16le, "round trip conversion from (dos charset) ISO-8859-1 back to UTF16LE"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_UNIX, + gd_utf16le.data, gd_utf16le.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from UTF16LE to (unix charset) CP850"); + torture_assert_data_blob_equal(tctx, gd_output, gd_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_UTF8, + gd_utf16le.data, gd_utf16le.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from UTF16LE to UTF8"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF16LE to UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_DOS, + gd_iso8859_1.data, gd_iso8859_1.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from (dos charset) ISO-8859-1 to (dos charset) ISO-8859-1"); + torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF16LE to (dos charset) ISO-8859-1 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_UNIX, + gd_iso8859_1.data, gd_iso8859_1.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from (dos charset) ISO-8859-1 to (unix charset) CP850"); + torture_assert_data_blob_equal(tctx, gd_output, gd_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_UTF8, + gd_iso8859_1.data, gd_iso8859_1.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from (dos charset) ISO-8859-1 to UTF8"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF16LE to UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_UTF16LE, + gd_iso8859_1.data, gd_iso8859_1.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from (dos charset) ISO-8859-1 to UTF16LE"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le, "conversion from (dos charset) ISO-8859-1 to UTF16LE"); + torture_assert_int_equal(tctx, + strlen_m_ext_handle(iconv_handle, + (const char *)gd_iso8859_1.data, + CH_DOS, CH_UTF16LE), + gd_output.length / 2, + "checking strlen_m_ext of round trip conversion of UTF16 latin charset greek to UTF8 and back again"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_UTF8, + gd_iso8859_1.data, gd_iso8859_1.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from (dos charset) ISO-8859-1 to UTF8"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from (dos charset) ISO-8859-1 to UTF8"); + torture_assert_int_equal(tctx, + strlen_m_ext_handle(iconv_handle, + (const char *)gd_iso8859_1.data, + CH_DOS, CH_UTF8), + gd_output.length, + "checking strlen_m_ext of conversion from (dos charset) ISO-8859-1 to UTF8"); + return true; +} + +static bool test_gd_minus_1_handle(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64); + DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64); + DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64); + DATA_BLOB gd_output; + DATA_BLOB gd_utf8_terminated; + DATA_BLOB gd_cp850_terminated; + DATA_BLOB gd_utf16le_terminated; + + talloc_steal(tctx, gd_utf8.data); + talloc_steal(tctx, gd_cp850.data); + talloc_steal(tctx, gd_utf16le.data); + + iconv_handle = get_iconv_testing_handle(tctx, "CP850", "CP850", + lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + torture_assert(tctx, iconv_handle, "getting iconv handle"); + + gd_utf8_terminated = data_blob_talloc(tctx, NULL, gd_utf8.length + 1); + memcpy(gd_utf8_terminated.data, gd_utf8.data, gd_utf8.length); + gd_utf8_terminated.data[gd_utf8.length] = '\0'; + + gd_cp850_terminated = data_blob_talloc(tctx, NULL, gd_cp850.length + 1); + memcpy(gd_cp850_terminated.data, gd_cp850.data, gd_cp850.length); + gd_cp850_terminated.data[gd_cp850.length] = '\0'; + + gd_utf16le_terminated = data_blob_talloc(tctx, NULL, gd_utf16le.length + 2); + memcpy(gd_utf16le_terminated.data, gd_utf16le.data, gd_utf16le.length); + gd_utf16le_terminated.data[gd_utf16le.length] = '\0'; + gd_utf16le_terminated.data[gd_utf16le.length + 1] = '\0'; + + gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + gd_utf8_terminated.data, -1, + (void *)gd_output.data, gd_output.length, &gd_output.length), + "conversion from UTF8 to UTF16LE null terminated"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated"); + + gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10); + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + gd_utf8_terminated.data, -1, + (void *)gd_output.data, gd_utf16le.length, &gd_output.length) == false, + "conversion from UTF8 to UTF16LE null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le, "conversion from UTF8 to UTF16LE null terminated"); + + gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10); + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + gd_utf8_terminated.data, -1, + (void *)gd_output.data, gd_utf16le.length - 1, &gd_output.length) == false, + "conversion from UTF8 to UTF16LE null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG"); + + gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10); + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + gd_utf8_terminated.data, -1, + (void *)gd_output.data, gd_utf16le.length - 2, &gd_output.length) == false, + "conversion from UTF8 to UTF16LE null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG"); + + gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10); + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + gd_utf16le_terminated.data, -1, + (void *)gd_output.data, gd_output.length, &gd_output.length), + "conversion from UTF16LE to UTF8 null terminated"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated"); + + gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + gd_utf16le_terminated.data, -1, + (void *)gd_output.data, gd_utf8.length, &gd_output.length) == false, + "conversion from UTF16LE to UTF8 null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF16LE to UTF8 null terminated"); + + gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + gd_utf16le_terminated.data, -1, + (void *)gd_output.data, gd_utf8.length - 1, &gd_output.length) == false, + "conversion from UTF16LE to UTF8 null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG"); + + gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + gd_utf16le_terminated.data, -1, + (void *)gd_output.data, gd_utf8.length - 2, &gd_output.length) == false, + "conversion from UTF16LE to UTF8 null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG"); + + gd_output = data_blob_talloc(tctx, NULL, gd_cp850.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_DOS, + gd_utf16le_terminated.data, -1, + (void *)gd_output.data, gd_output.length, &gd_output.length), + "conversion from UTF16LE to CP850 (dos) null terminated"); + torture_assert_data_blob_equal(tctx, gd_output, gd_cp850_terminated, "conversion from UTF16LE to CP850 (dos) null terminated"); + + /* Now null terminate the string early, the confirm we don't skip the NULL and convert any further */ + gd_utf8_terminated.data[3] = '\0'; + gd_utf8_terminated.length = 4; /* used for the comparison only */ + + gd_cp850_terminated.data[2] = '\0'; + gd_cp850_terminated.length = 3; /* used for the comparison only */ + + gd_utf16le_terminated.data[4] = '\0'; + gd_utf16le_terminated.data[5] = '\0'; + gd_utf16le_terminated.length = 6; /* used for the comparison only */ + + gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + gd_utf8_terminated.data, -1, + (void *)gd_output.data, gd_output.length, &gd_output.length), + "conversion from UTF8 to UTF16LE null terminated"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early"); + + gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + gd_utf16le_terminated.data, -1, + (void *)gd_output.data, gd_output.length, &gd_output.length), + "conversion from UTF16LE to UTF8 null terminated"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated early"); + + gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_DOS, CH_UTF16LE, + gd_cp850_terminated.data, -1, + (void *)gd_output.data, gd_output.length, &gd_output.length), + "conversion from CP850 to UTF16LE null terminated"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early"); + + gd_output = data_blob_talloc(tctx, NULL, gd_cp850.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_DOS, + gd_utf16le_terminated.data, -1, + (void *)gd_output.data, gd_output.length, &gd_output.length), + "conversion from UTF16LE to UTF8 null terminated"); + torture_assert_data_blob_equal(tctx, gd_output, gd_cp850_terminated, "conversion from UTF16LE to UTF8 null terminated early"); + + /* Now null terminate the string particularly early, the confirm we don't skip the NULL and convert any further */ + gd_utf8_terminated.data[1] = '\0'; + gd_utf8_terminated.length = 2; /* used for the comparison only */ + + gd_utf16le_terminated.data[2] = '\0'; + gd_utf16le_terminated.data[3] = '\0'; + gd_utf16le_terminated.length = 4; /* used for the comparison only */ + + gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, CH_UTF8, CH_UTF16LE, + gd_utf8_terminated.data, -1, + (void *)gd_output.data, gd_output.length, &gd_output.length), + "conversion from UTF8 to UTF16LE null terminated"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated very early"); + + gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + gd_utf16le_terminated.data, -1, + (void *)gd_output.data, gd_output.length, &gd_output.length), + "conversion from UTF16LE to UTF8 null terminated"); + torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated very early"); + + return true; +} + +static bool test_gd_ascii_handle(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64); + DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64); + DATA_BLOB gd_iso8859_1 = base64_decode_data_blob(gd_iso8859_1_base64); + DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64); + DATA_BLOB gd_output; + + talloc_steal(tctx, gd_utf8.data); + talloc_steal(tctx, gd_cp850.data); + talloc_steal(tctx, gd_iso8859_1.data); + talloc_steal(tctx, gd_utf16le.data); + + iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "UTF8", + lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + torture_assert(tctx, iconv_handle, "getting iconv handle"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_DOS, + gd_utf8.data, gd_utf8.length, + (void *)&gd_output.data, &gd_output.length) == false, + "conversion from UTF8 to (dos charset) ASCII should fail"); + + gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_DOS, + gd_utf8.data, gd_utf8.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF8 to (dos charset) ASCII should fail"); + torture_assert_errno_equal(tctx, EILSEQ, "conversion from UTF8 to (dos charset) ISO-8859-1 should fail E2BIG"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); + torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "partial conversion from UTF8 to (dos charset) ASCII incorrect"); + + /* Short output handling confirmation */ + gd_output.length = 1; + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_DOS, + gd_utf8.data, gd_utf8.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF8 to (dos charset) ASCII should fail due to too short"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to (dos charset) ASCII too short"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); + torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF8 to (dos charset) ASCII incorrect"); + + /* Short output handling confirmation */ + gd_output.length = 2; + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_DOS, + gd_utf8.data, gd_utf8.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF8 to (dos charset) ASCII should fail due to illegal sequence"); + torture_assert_errno_equal(tctx, EILSEQ, "conversion from UTF8 to (dos charset) ISO-8859-1 should fail EILSEQ"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 2 char of output"); + + /* Short input handling confirmation */ + gd_output.length = gd_utf8.length; + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_DOS, + gd_utf8.data, 2, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF8 to (dos charset) ASCII should fail due to too short"); + torture_assert_errno_equal(tctx, EILSEQ, "conversion from short UTF8 to (dos charset) ASCII should fail EILSEQ"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); + return true; +} + +static bool test_plato_english_iso8859_cp850_handle(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB plato_english_utf8 = data_blob_string_const(plato_english_ascii); + DATA_BLOB plato_english_cp850 = plato_english_utf8; + DATA_BLOB plato_english_iso8859_1 = plato_english_utf8; + DATA_BLOB plato_english_utf16le = base64_decode_data_blob(plato_english_utf16le_base64); + DATA_BLOB plato_english_output; + DATA_BLOB plato_english_output2; + + talloc_steal(tctx, plato_english_utf16le.data); + + iconv_handle = get_iconv_testing_handle(tctx, "ISO-8859-1", "CP850", + lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + torture_assert(tctx, iconv_handle, "getting iconv handle"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_DOS, + plato_english_utf8.data, plato_english_utf8.length, + (void *)&plato_english_output.data, &plato_english_output.length), + "conversion from UTF8 to (dos charset) ISO-8859-1"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_iso8859_1, "conversion from UTF8 to (dos charset) ISO-8859-1 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UNIX, + plato_english_utf8.data, plato_english_utf8.length, + (void *)&plato_english_output.data, &plato_english_output.length), + "conversion from UTF8 to (unix charset) CP850"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_cp850, "conversion from UTF8 to (unix charset) CP850 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UTF8, + plato_english_utf8.data, plato_english_utf8.length, + (void *)&plato_english_output.data, &plato_english_output.length), + "conversion from UTF8 to UTF8"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF8 to UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_DOS, + plato_english_utf16le.data, plato_english_utf16le.length, + (void *)&plato_english_output.data, &plato_english_output.length), + "conversion from UTF16LE to (dos charset) ISO-8859-1"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_iso8859_1, "conversion from UTF16LE to (dos charset) ISO-8859-1 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_UTF16LE, + plato_english_output.data, plato_english_output.length, + (void *)&plato_english_output2.data, &plato_english_output2.length), + "round trip conversion from (dos charset) ISO-8859-1 back to UTF16LE"); + torture_assert_data_blob_equal(tctx, plato_english_output2, plato_english_utf16le, "round trip conversion from (dos charset) ISO-8859-1 back to UTF16LE"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_english_utf16le.data, plato_english_utf16le.length, + (void *)&plato_english_output.data, &plato_english_output.length), + "conversion from UTF16LE to UTF8"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_english_utf16le.data, plato_english_utf16le.length, + (void *)plato_english_output.data, plato_english_output.length, + &plato_english_output.length), + "conversion from UTF16LE to UTF8"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect"); + + plato_english_output.length = 5; + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_english_utf16le.data, plato_english_utf16le.length, + (void *)plato_english_output.data, plato_english_output.length, + &plato_english_output.length) == false, + "conversion from UTF16LE to UTF8 should fail due to short output"); + torture_assert_data_blob_equal(tctx, plato_english_output, data_blob_string_const("What "), "conversion from UTF16LE to UTF8 incorrect"); + torture_assert_int_equal(tctx, plato_english_output.length, 5, "short conversion failed"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_UNIX, + plato_english_utf16le.data, plato_english_utf16le.length, + (void *)&plato_english_output.data, &plato_english_output.length), + "conversion from UTF16LE to (unix charset) CP850"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_english_utf16le.data, plato_english_utf16le.length, + (void *)&plato_english_output.data, &plato_english_output.length), + "conversion from UTF16LE to UTF8"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_DOS, + plato_english_iso8859_1.data, plato_english_iso8859_1.length, + (void *)&plato_english_output.data, &plato_english_output.length), + "conversion from (dos charset) ISO-8859-1 to (dos charset) ISO-8859-1"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_iso8859_1, "conversion from UTF16LE to (dos charset) ISO-8859-1 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_UNIX, + plato_english_iso8859_1.data, plato_english_iso8859_1.length, + (void *)&plato_english_output.data, &plato_english_output.length), + "conversion from (dos charset) ISO-8859-1 to (unix charset) CP850"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_UTF8, + plato_english_iso8859_1.data, plato_english_iso8859_1.length, + (void *)&plato_english_output.data, &plato_english_output.length), + "conversion from (dos charset) ISO-8859-1 to UTF8"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_DOS, CH_UTF16LE, + plato_english_iso8859_1.data, plato_english_iso8859_1.length, + (void *)&plato_english_output.data, &plato_english_output.length), + "conversion from (dos charset) ISO-8859-1 to UTF16LE"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le, "conversion from (dos charset) ISO-8859-1 to UTF16LE"); + return true; +} + +static bool test_plato_english_minus_1_handle(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB plato_english_utf8 = data_blob_string_const(plato_english_ascii); + DATA_BLOB plato_english_utf16le = base64_decode_data_blob(plato_english_utf16le_base64); + DATA_BLOB plato_english_output; + DATA_BLOB plato_english_utf8_terminated; + DATA_BLOB plato_english_utf16le_terminated; + + talloc_steal(tctx, plato_english_utf16le.data); + + iconv_handle = get_iconv_testing_handle(tctx, "ISO-8859-1", "CP850", + lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + torture_assert(tctx, iconv_handle, "getting iconv handle"); + + plato_english_utf8_terminated = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 1); + memcpy(plato_english_utf8_terminated.data, plato_english_utf8.data, plato_english_utf8.length); + plato_english_utf8_terminated.data[plato_english_utf8.length] = '\0'; + + plato_english_utf16le_terminated = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 2); + memcpy(plato_english_utf16le_terminated.data, plato_english_utf16le.data, plato_english_utf16le.length); + plato_english_utf16le_terminated.data[plato_english_utf16le.length] = '\0'; + plato_english_utf16le_terminated.data[plato_english_utf16le.length + 1] = '\0'; + + plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_english_utf8_terminated.data, -1, + (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length), + "conversion from UTF8 to UTF16LE null terminated"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_english_utf8_terminated.data, -1, + (void *)plato_english_output.data, plato_english_utf16le.length, &plato_english_output.length) == false, + "conversion from UTF8 to UTF16LE null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le, "conversion from UTF8 to UTF16LE null terminated"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_english_utf8_terminated.data, -1, + (void *)plato_english_output.data, plato_english_utf16le.length - 1, &plato_english_output.length) == false, + "conversion from UTF8 to UTF16LE null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_english_utf8_terminated.data, -1, + (void *)plato_english_output.data, plato_english_utf16le.length - 2, &plato_english_output.length) == false, + "conversion from UTF8 to UTF16LE null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG"); + + plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_english_utf16le_terminated.data, -1, + (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length), + "conversion from UTF16LE to UTF8 null terminated"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_english_utf16le_terminated.data, -1, + (void *)plato_english_output.data, plato_english_utf8.length, &plato_english_output.length) == false, + "conversion from UTF16LE to UTF8 null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 null terminated"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_english_utf16le_terminated.data, -1, + (void *)plato_english_output.data, plato_english_utf8.length - 1, &plato_english_output.length) == false, + "conversion from UTF16LE to UTF8 null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_english_utf16le_terminated.data, -1, + (void *)plato_english_output.data, plato_english_utf8.length - 2, &plato_english_output.length) == false, + "conversion from UTF16LE to UTF8 null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG"); + + /* Now null terminate the string early, the confirm we don't skip the NULL and convert any further */ + plato_english_utf8_terminated.data[3] = '\0'; + plato_english_utf8_terminated.length = 4; /* used for the comparison only */ + + plato_english_utf16le_terminated.data[6] = '\0'; + plato_english_utf16le_terminated.data[7] = '\0'; + plato_english_utf16le_terminated.length = 8; /* used for the comparison only */ + + plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_english_utf8_terminated.data, -1, + (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length), + "conversion from UTF8 to UTF16LE null terminated"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early"); + + plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_english_utf16le_terminated.data, -1, + (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length), + "conversion from UTF16LE to UTF8 null terminated"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated early"); + + + /* Now null terminate the string particularly early, the confirm we don't skip the NULL and convert any further */ + plato_english_utf8_terminated.data[1] = '\0'; + plato_english_utf8_terminated.length = 2; /* used for the comparison only */ + + plato_english_utf16le_terminated.data[2] = '\0'; + plato_english_utf16le_terminated.data[3] = '\0'; + plato_english_utf16le_terminated.length = 4; /* used for the comparison only */ + + plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, CH_UTF8, CH_UTF16LE, + plato_english_utf8_terminated.data, -1, + (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length), + "conversion from UTF8 to UTF16LE null terminated"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated very early"); + + plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_english_utf16le_terminated.data, -1, + (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length), + "conversion from UTF16LE to UTF8 null terminated"); + torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated very early"); + + return true; +} + +static bool test_plato_minus_1_handle(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64); + DATA_BLOB plato_utf16le = base64_decode_data_blob(plato_utf16le_base64); + DATA_BLOB plato_output; + DATA_BLOB plato_utf8_terminated; + DATA_BLOB plato_utf16le_terminated; + + talloc_steal(tctx, plato_utf8.data); + talloc_steal(tctx, plato_utf16le.data); + + iconv_handle = get_iconv_testing_handle(tctx, "ISO-8859-1", "CP850", + lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + torture_assert(tctx, iconv_handle, "getting iconv handle"); + + plato_utf8_terminated = data_blob_talloc(tctx, NULL, plato_utf8.length + 1); + memcpy(plato_utf8_terminated.data, plato_utf8.data, plato_utf8.length); + plato_utf8_terminated.data[plato_utf8.length] = '\0'; + + plato_utf16le_terminated = data_blob_talloc(tctx, NULL, plato_utf16le.length + 2); + memcpy(plato_utf16le_terminated.data, plato_utf16le.data, plato_utf16le.length); + plato_utf16le_terminated.data[plato_utf16le.length] = '\0'; + plato_utf16le_terminated.data[plato_utf16le.length + 1] = '\0'; + + plato_output = data_blob_talloc(tctx, NULL, plato_utf16le.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_utf8_terminated.data, -1, + (void *)plato_output.data, plato_output.length, &plato_output.length), + "conversion from UTF8 to UTF16LE null terminated"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_utf8_terminated.data, -1, + (void *)plato_output.data, plato_utf16le.length, &plato_output.length) == false, + "conversion from UTF8 to UTF16LE null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE null terminated"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_utf8_terminated.data, -1, + (void *)plato_output.data, plato_utf16le.length - 1, &plato_output.length) == false, + "conversion from UTF8 to UTF16LE null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_utf8_terminated.data, -1, + (void *)plato_output.data, plato_utf16le.length - 2, &plato_output.length) == false, + "conversion from UTF8 to UTF16LE null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG"); + + plato_output = data_blob_talloc(tctx, NULL, plato_utf8.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_utf16le_terminated.data, -1, + (void *)plato_output.data, plato_output.length, &plato_output.length), + "conversion from UTF16LE to UTF8 null terminated"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_utf16le_terminated.data, -1, + (void *)plato_output.data, plato_utf8.length, &plato_output.length) == false, + "conversion from UTF16LE to UTF8 null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to UTF8 null terminated"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_utf16le_terminated.data, -1, + (void *)plato_output.data, plato_utf8.length - 1, &plato_output.length) == false, + "conversion from UTF16LE to UTF8 null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG"); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_utf16le_terminated.data, -1, + (void *)plato_output.data, plato_utf8.length - 2, &plato_output.length) == false, + "conversion from UTF16LE to UTF8 null terminated should fail"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG"); + + /* Now null terminate the string early, the confirm we don't skip the NULL and convert any further */ + plato_utf8_terminated.data[5] = '\0'; + plato_utf8_terminated.length = 6; /* used for the comparison only */ + + plato_utf16le_terminated.data[4] = '\0'; + plato_utf16le_terminated.data[5] = '\0'; + plato_utf16le_terminated.length = 6; /* used for the comparison only */ + + plato_output = data_blob_talloc(tctx, NULL, plato_utf16le.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_utf8_terminated.data, -1, + (void *)plato_output.data, plato_output.length, &plato_output.length), + "conversion from UTF8 to UTF16LE null terminated"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early"); + + plato_output = data_blob_talloc(tctx, NULL, plato_utf8.length + 10); + + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_utf16le_terminated.data, -1, + (void *)plato_output.data, plato_output.length, &plato_output.length), + "conversion from UTF16LE to UTF8 null terminated"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated early"); + + return true; +} + +static bool test_plato_cp850_utf8_handle(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64); + DATA_BLOB plato_utf16le = base64_decode_data_blob(plato_utf16le_base64); + DATA_BLOB plato_output; + DATA_BLOB plato_output2; + + talloc_steal(tctx, plato_utf8.data); + talloc_steal(tctx, plato_utf16le.data); + + iconv_handle = get_iconv_testing_handle(tctx, "CP850", "UTF8", + lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + torture_assert(tctx, iconv_handle, "creating iconv handle"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_utf8.data, plato_utf8.length, + (void *)&plato_output.data, &plato_output.length), + "conversion of UTF8 ancient greek to UTF16 failed"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect"); + + torture_assert_int_equal(tctx, + strlen_m_ext_handle(iconv_handle, + (const char *)plato_utf8.data, + CH_UTF8, CH_UTF16LE), + plato_output.length / 2, + "checking strlen_m_ext of conversion of UTF8 to UTF16LE"); + + memset(plato_output.data, '\0', plato_output.length); + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_utf8.data, plato_utf8.length, + (void *)plato_output.data, plato_output.length, + &plato_output.length), + "conversion of UTF8 ancient greek to UTF16 failed"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_output.data, plato_output.length, + (void *)&plato_output2.data, &plato_output2.length), + "conversion of UTF8 ancient greek to UTF16 failed"); + torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect"); + + memset(plato_output2.data, '\0', plato_output2.length); + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_output.data, plato_output.length, + (void *)plato_output2.data, plato_output2.length, &plato_output2.length), + "conversion of UTF8 ancient greek to UTF16 failed"); + torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UTF8, + plato_utf8.data, plato_utf8.length, + (void *)&plato_output.data, &plato_output.length), + "conversion of UTF8 to UTF8"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, + "conversion of UTF8 to UTF8"); + torture_assert_int_equal(tctx, + strlen_m_ext_handle(iconv_handle, + (const char *)plato_utf8.data, + CH_UTF8, CH_UTF8), + plato_output.length, + "checking strlen_m_ext of conversion of UTF8 to UTF8"); + memset(plato_output.data, '\0', plato_output.length); + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UTF8, + plato_utf8.data, plato_utf8.length, + (void *)plato_output.data, plato_output.length, + &plato_output.length), + "conversion of UTF8 to UTF8"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_DOS, + plato_utf8.data, plato_utf8.length, + (void *)&plato_output.data, &plato_output.length) == false, + "conversion of UTF8 ancient greek to DOS charset CP850 should fail"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UNIX, + plato_utf8.data, plato_utf8.length, + (void *)&plato_output.data, &plato_output.length), + "conversion of UTF16 ancient greek to unix charset UTF8 failed"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF8 to (unix charset) UTF8 incorrect"); + + memset(plato_output.data, '\0', plato_output.length); + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF8, CH_UNIX, + plato_utf8.data, plato_utf8.length, + (void *)plato_output.data, plato_output.length, + &plato_output.length), + "conversion of UTF16 ancient greek to unix charset UTF8 failed"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF8 to (unix charset) UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UTF8, + plato_utf8.data, plato_utf8.length, + (void *)&plato_output.data, &plato_output.length), + "conversion of UTF16 ancient greek to unix charset UTF8 failed"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF8 to UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_DOS, + plato_utf16le.data, plato_utf16le.length, + (void *)&plato_output.data, &plato_output.length) == false, + "conversion of UTF16 ancient greek to DOS charset CP850 should fail"); + + /* Allocate enough space, if it were possible do do the conversion */ + plato_output = data_blob_talloc(tctx, NULL, plato_utf16le.length); + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_DOS, + plato_utf16le.data, plato_utf16le.length, + (void *)plato_output.data, plato_output.length, + &plato_output.length) == false, + "conversion of UTF16 ancient greek to DOS charset CP850 should fail"); + torture_assert_errno_equal(tctx, EILSEQ, "conversion of UTF16 ancient greek to DOS charset CP850 should fail"); + + /* Allocate only enough space for a partial conversion */ + plato_output = data_blob_talloc(tctx, NULL, 9); + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_utf16le.data, plato_utf16le.length, + (void *)plato_output.data, plato_output.length, + &plato_output.length) == false, + "conversion of UTF16 ancient greek to UTF8 should fail, not enough space"); + torture_assert_errno_equal(tctx, E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space"); + torture_assert_int_equal(tctx, plato_output.length, 8, + "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary"); + + plato_output = data_blob_talloc(tctx, NULL, 2); + torture_assert(tctx, convert_string_error_handle(iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_utf16le.data, plato_utf16le.length, + (void *)plato_output.data, plato_output.length, + &plato_output.length) == false, + "conversion of UTF16 ancient greek to UTF8 should fail, not enough space"); + torture_assert_errno_equal(tctx, E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space"); + torture_assert_int_equal(tctx, plato_output.length, 0, + "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary"); + + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_UNIX, + plato_utf16le.data, plato_utf16le.length, + (void *)&plato_output.data, &plato_output.length), + "conversion of UTF16 ancient greek to unix charset UTF8 failed"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to (unix charset) UTF8 incorrect"); + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_utf16le.data, plato_utf16le.length, + (void *)&plato_output.data, &plato_output.length), + "conversion of UTF16 ancient greek to UTF8 failed"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to UTF8 incorrect"); + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_utf16le.data, plato_utf16le.length, + (void *)&plato_output.data, &plato_output.length), + "conversion of UTF16 ancient greek to UTF8 failed"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_output.data, plato_output.length, + (void *)&plato_output2.data, &plato_output2.length), + "round trip conversion of UTF16 ancient greek to UTF8 and back again failed"); + torture_assert_data_blob_equal(tctx, plato_output2, plato_utf16le, + "round trip conversion of UTF16 ancient greek to UTF8 and back again failed"); + torture_assert_int_equal(tctx, + strlen_m_ext_handle(iconv_handle, + (const char *)plato_output.data, + CH_UTF8, CH_UTF16LE), + plato_output2.length / 2, + "checking strlen_m_ext of round trip conversion of UTF16 latin charset greek to UTF8 and back again"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UTF8, + plato_output.data, plato_output.length, + (void *)&plato_output2.data, &plato_output2.length), + "conversion of UTF8 to UTF8"); + torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, + "conversion of UTF8 to UTF8"); + torture_assert_int_equal(tctx, + strlen_m_ext_handle(iconv_handle, + (const char *)plato_output.data, + CH_UTF8, CH_UTF8), + plato_output2.length, + "checking strlen_m_ext of conversion of UTF8 to UTF8"); + return true; +} + +static bool test_plato_latin_cp850_utf8_handle(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB plato_latin_utf8 = base64_decode_data_blob(plato_latin_utf8_base64); + DATA_BLOB plato_latin_utf16le = base64_decode_data_blob(plato_latin_utf16le_base64); + DATA_BLOB plato_latin_output; + DATA_BLOB plato_latin_output2; + + talloc_steal(tctx, plato_latin_utf8.data); + talloc_steal(tctx, plato_latin_utf16le.data); + + iconv_handle = get_iconv_testing_handle(tctx, "CP850", "UTF8", + lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + torture_assert(tctx, iconv_handle, "creating iconv handle"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_DOS, + plato_latin_utf8.data, plato_latin_utf8.length, + (void *)&plato_latin_output.data, &plato_latin_output.length) == false, + "conversion of UTF8 latin charset greek to DOS charset CP850 should fail"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UNIX, + plato_latin_utf8.data, plato_latin_utf8.length, + (void *)&plato_latin_output.data, &plato_latin_output.length), + "conversion of UTF16 latin charset greek to unix charset UTF8 failed"); + torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF8 to (unix charset) UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UTF8, + plato_latin_utf8.data, plato_latin_utf8.length, + (void *)&plato_latin_output.data, &plato_latin_output.length), + "conversion of UTF16 latin charset greek to unix charset UTF8 failed"); + torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF8 to UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_DOS, + plato_latin_utf16le.data, plato_latin_utf16le.length, + (void *)&plato_latin_output.data, &plato_latin_output.length) == false, + "conversion of UTF16 latin charset greek to DOS charset CP850 should fail"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_UNIX, + plato_latin_utf16le.data, plato_latin_utf16le.length, + (void *)&plato_latin_output.data, &plato_latin_output.length), + "conversion of UTF16 latin charset greek to unix charset UTF8 failed"); + torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF16LE to (unix charset) CP850 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF16LE, CH_UTF8, + plato_latin_utf16le.data, plato_latin_utf16le.length, + (void *)&plato_latin_output.data, &plato_latin_output.length), + "conversion of UTF16 latin charset greek to UTF8 failed"); + torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF16LE to UTF8 incorrect"); + + torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, + CH_UTF8, CH_UTF16LE, + plato_latin_output.data, plato_latin_output.length, + (void *)&plato_latin_output2.data, &plato_latin_output2.length), + "round trip conversion of UTF16 latin charset greek to UTF8 and back again failed"); + torture_assert_data_blob_equal(tctx, plato_latin_output2, plato_latin_utf16le, + "round trip conversion of UTF16 latin charset greek to UTF8 and back again failed"); + torture_assert_int_equal(tctx, + strlen_m_ext_handle(iconv_handle, + (const char *)plato_latin_output.data, + CH_UTF8, CH_UTF16LE), + plato_latin_output2.length / 2, + "checking strlen_m_ext of round trip conversion of UTF16 latin charset greek to UTF8 and back again"); + return true; +} + +static bool test_utf8_nfc_to_nfd_overflow(struct torture_context *tctx) +{ + smb_iconv_t ic; + DATA_BLOB utf8_nfc_blob; + DATA_BLOB utf8_nfd_blob; + DATA_BLOB src_blob; + DATA_BLOB blob; + size_t nconv; + const char *src = NULL; + char *dst = NULL; + size_t dst_left; + size_t srclen; + bool ret = true; + + ic = smb_iconv_open("UTF8-NFD", "UTF8-NFC"); + torture_assert_goto(tctx, ic != (smb_iconv_t)-1, ret, done, + "creating iconv handle\n"); + + utf8_nfc_blob = base64_decode_data_blob_talloc(tctx, utf8_nfc_base64); + torture_assert_not_null_goto(tctx, utf8_nfc_blob.data, ret, done, + "OOM\n"); + + utf8_nfd_blob = base64_decode_data_blob_talloc(tctx, utf8_nfd_base64); + torture_assert_not_null_goto(tctx, utf8_nfd_blob.data, ret, done, + "OOM\n"); + + blob = data_blob_talloc_zero(tctx, 255); + torture_assert_not_null_goto(tctx, blob.data, ret, done, "OOM\n"); + + /* + * Unfortunately the current implementation that performs the conversion + * (using libicu) returns EINVAL if the result buffer is too small, not + * E2BIG like iconv(). + */ + + src = "foo"; + srclen = 3; + dst = (char *)blob.data; + dst_left = 0; + nconv = smb_iconv(ic, + &src, + &srclen, + &dst, + &dst_left); + torture_assert_int_equal_goto(tctx, nconv, -1, ret, done, + "smb_iconv failed\n"); + torture_assert_errno_equal_goto(tctx, EINVAL, ret, done, + "Wrong errno\n"); + + src = "foo"; + srclen = 3; + dst = (char *)blob.data; + dst_left = 1; + nconv = smb_iconv(ic, + &src, + &srclen, + &dst, + &dst_left); + torture_assert_int_equal_goto(tctx, nconv, -1, ret, done, + "smb_iconv failed\n"); + torture_assert_errno_equal_goto(tctx, EINVAL, ret, done, + "Wrong errno\n"); + + src = "foo"; + srclen = 3; + dst = (char *)blob.data; + dst_left = 2; + nconv = smb_iconv(ic, + &src, + &srclen, + &dst, + &dst_left); + torture_assert_int_equal_goto(tctx, nconv, -1, ret, done, + "smb_iconv failed\n"); + torture_assert_errno_equal_goto(tctx, EINVAL, ret, done, + "Wrong errno\n"); + + src_blob = data_blob_const("foo", 3); + src = (const char *)src_blob.data; + srclen = src_blob.length; + dst = (char *)blob.data; + dst_left = 3; + nconv = smb_iconv(ic, + &src, + &srclen, + &dst, + &dst_left); + torture_assert_int_equal_goto(tctx, nconv, 3, ret, done, + "smb_iconv failed\n"); + + blob.length = nconv; + torture_assert_data_blob_equal(tctx, + src_blob, + blob, + "Conversion failed\n"); + + src_blob = data_blob_const("foo", 4); + src = (const char *)src_blob.data; + srclen = src_blob.length; + dst = (char *)blob.data; + dst_left = 4; + nconv = smb_iconv(ic, + &src, + &srclen, + &dst, + &dst_left); + torture_assert_int_equal_goto(tctx, nconv, 4, ret, done, + "smb_iconv failed\n"); + + blob.length = nconv; + torture_assert_data_blob_equal(tctx, + src_blob, + blob, + "Conversion failed\n"); + +done: + return ret; +} + +static bool test_utf8_nfc_to_nfd(struct torture_context *tctx) +{ + smb_iconv_t ic; + DATA_BLOB utf8_nfc_blob; + DATA_BLOB utf8_nfd_blob; + DATA_BLOB blob; + size_t nconv; + const char *src = NULL; + char *dst = NULL; + size_t dst_left; + size_t srclen; + bool ret = true; + + ic = smb_iconv_open("UTF8-NFD", "UTF8-NFC"); + torture_assert_goto(tctx, ic != (smb_iconv_t)-1, ret, done, + "creating iconv handle\n"); + + utf8_nfc_blob = base64_decode_data_blob_talloc(tctx, utf8_nfc_base64); + torture_assert_not_null_goto(tctx, utf8_nfc_blob.data, ret, done, + "OOM\n"); + + utf8_nfd_blob = base64_decode_data_blob_talloc(tctx, utf8_nfd_base64); + torture_assert_not_null_goto(tctx, utf8_nfd_blob.data, ret, done, + "OOM\n"); + + blob = data_blob_talloc_zero(tctx, 255); + torture_assert_not_null_goto(tctx, blob.data, ret, done, "OOM\n"); + + dst = (char *)blob.data; + dst_left = blob.length; + src = (const char *)utf8_nfc_blob.data; + srclen = strlen(src); + + nconv = smb_iconv(ic, + &src, + &srclen, + &dst, + &dst_left); + torture_assert_goto(tctx, nconv != (size_t)-1, ret, done, + "smb_iconv failed\n"); + + blob.length = nconv + 1; /* +1 for the trailing zero */ + torture_assert_data_blob_equal(tctx, + blob, + utf8_nfd_blob, + "Conversion failed\n"); + +done: + return ret; +} + +static bool test_utf8_nfd_to_nfc(struct torture_context *tctx) +{ + smb_iconv_t ic; + DATA_BLOB utf8_nfc_blob; + DATA_BLOB utf8_nfd_blob; + DATA_BLOB blob; + size_t nconv; + const char *src = NULL; + char *dst = NULL; + size_t dst_left; + size_t srclen; + bool ret = true; + + ic = smb_iconv_open("UTF8-NFC", "UTF8-NFD"); + torture_assert_goto(tctx, ic != (smb_iconv_t)-1, ret, done, + "creating iconv handle\n"); + + utf8_nfc_blob = base64_decode_data_blob_talloc(tctx, utf8_nfc_base64); + torture_assert_not_null_goto(tctx, utf8_nfc_blob.data, ret, done, + "OOM\n"); + + utf8_nfd_blob = base64_decode_data_blob_talloc(tctx, utf8_nfd_base64); + torture_assert_not_null_goto(tctx, utf8_nfd_blob.data, ret, done, + "OOM\n"); + + blob = data_blob_talloc_zero(tctx, 255); + torture_assert_not_null_goto(tctx, blob.data, ret, done, "OOM\n"); + + dst = (char *)blob.data; + dst_left = blob.length; + src = (const char *)utf8_nfd_blob.data; + srclen = strlen(src); + + nconv = smb_iconv(ic, + &src, + &srclen, + &dst, + &dst_left); + torture_assert_goto(tctx, nconv != (size_t)-1, ret, done, + "smb_iconv failed\n"); + + blob.length = nconv + 1; /* +1 for the trailing zero */ + torture_assert_data_blob_equal(tctx, + blob, + utf8_nfc_blob, + "Conversion failed\n"); + +done: + return ret; +} + +static bool test_gd_case_utf8_handle(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64); + DATA_BLOB gd_utf8_upper = base64_decode_data_blob(gd_utf8_upper_base64); + DATA_BLOB gd_utf8_lower = base64_decode_data_blob(gd_utf8_lower_base64); + char *gd_lower, *gd_upper; + talloc_steal(tctx, gd_utf8.data); + + iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "UTF8", + lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + torture_assert(tctx, iconv_handle, "getting utf8 iconv handle"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, (const char *)gd_utf8.data), + "GD's name has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, (const char *)gd_utf8.data), + "GD's name has an lower case character"); + gd_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)gd_utf8.data); + torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case"); + torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_lower), gd_utf8_lower, + "convert GD's name into lower case"); + gd_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)gd_utf8.data, gd_utf8.length); + torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case"); + torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_upper), gd_utf8_upper, + "convert GD's name into upper case"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, gd_upper), + "upper case name has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, gd_lower), + "lower case name has an lower case character"); + torture_assert(tctx, + strhasupper_handle(iconv_handle, gd_lower) == false, + "lower case name has no upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, gd_upper) == false, + "upper case name has no lower case character"); + + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data, + gd_upper) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data, + gd_lower) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, gd_upper, + gd_lower) == 0, + "case insensitive comparison upper/lower"); + + /* This string isn't different in length upper/lower */ + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data, + gd_upper, gd_utf8.length) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data, + gd_lower, gd_utf8.length) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, gd_upper, + gd_lower, gd_utf8.length) == 0, + "case insensitive comparison upper/lower"); + + data_blob_free(&gd_utf8); + data_blob_free(&gd_utf8_upper); + data_blob_free(&gd_utf8_lower); + + return true; +} + +static bool test_gd_case_cp850_handle(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64); + DATA_BLOB gd_cp850_upper = base64_decode_data_blob(gd_cp850_upper_base64); + DATA_BLOB gd_cp850_lower = base64_decode_data_blob(gd_cp850_lower_base64); + char *gd_lower, *gd_upper; + talloc_steal(tctx, gd_cp850.data); + + iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "CP850", + lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + torture_assert(tctx, iconv_handle, "getting cp850 iconv handle"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, (const char *)gd_cp850.data), + "GD's name has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, (const char *)gd_cp850.data), + "GD's name has an lower case character"); + gd_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)gd_cp850.data); + torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case"); + torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_lower), gd_cp850_lower, + "convert GD's name into lower case"); + gd_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)gd_cp850.data, gd_cp850.length); + torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case"); + torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_upper), gd_cp850_upper, + "convert GD's name into upper case"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, gd_upper), + "upper case name has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, gd_lower), + "lower case name has an lower case character"); + torture_assert(tctx, + strhasupper_handle(iconv_handle, gd_lower) == false, + "lower case name has no upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, gd_upper) == false, + "upper case name has no lower case character"); + + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data, + gd_upper) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data, + gd_lower) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, gd_upper, + gd_lower) == 0, + "case insensitive comparison upper/lower"); + + /* This string isn't different in length upper/lower */ + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data, + gd_upper, gd_cp850.length) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data, + gd_lower, gd_cp850.length) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, gd_upper, + gd_lower, gd_cp850.length) == 0, + "case insensitive comparison upper/lower"); + + data_blob_free(&gd_cp850); + data_blob_free(&gd_cp850_upper); + data_blob_free(&gd_cp850_lower); + + return true; +} + +static bool test_plato_case_utf8_handle(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64); + char *plato_lower, *plato_upper; + talloc_steal(tctx, plato_utf8.data); + + iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "UTF8", + lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + torture_assert(tctx, iconv_handle, "getting utf8 iconv handle"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, (const char *)plato_utf8.data), + "PLATO's apology has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, (const char *)plato_utf8.data), + "PLATO's apology has an lower case character"); + plato_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)plato_utf8.data); + torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into lower case"); + plato_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)plato_utf8.data, plato_utf8.length); + torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into upper case"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, plato_upper), + "upper case string has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, plato_lower), + "lower case string has an lower case character"); + torture_assert(tctx, + strhasupper_handle(iconv_handle, plato_lower) == false, + "lower case string has no upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, plato_upper) == false, + "upper case string has no lower case character"); + + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)plato_utf8.data, + plato_upper) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)plato_utf8.data, + plato_lower) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, plato_upper, + plato_lower) == 0, + "case insensitive comparison upper/lower"); + return true; +} + +static bool test_gd(struct torture_context *tctx) +{ + DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64); + DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64); + DATA_BLOB gd_iso8859_1 = base64_decode_data_blob(gd_iso8859_1_base64); + DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64); + DATA_BLOB gd_output; + size_t saved_len; + + talloc_steal(tctx, gd_utf8.data); + talloc_steal(tctx, gd_cp850.data); + talloc_steal(tctx, gd_iso8859_1.data); + talloc_steal(tctx, gd_utf16le.data); + + torture_assert(tctx, convert_string_talloc(tctx, CH_UTF8, CH_UTF8, + gd_utf8.data, gd_utf8.length, + (void *)&gd_output.data, &gd_output.length), + "conversion from UTF8 to utf8 charset"); + saved_len = gd_output.length; + + torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8, + gd_utf8.data, gd_utf8.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length), + "conversion from UTF8 to utf8 charset"); + + /* Short output handling confirmation */ + gd_output.length = 1; + torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8, + gd_utf8.data, gd_utf8.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF8 to any utf8 charset should fail due to too short"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to utf8 charset should fail E2BIG"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); + torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF8 to utf8 charset incorrect"); + +#if 0 /* This currently fails as we just copy like-for-like character conversions */ + /* Short output handling confirmation */ + gd_output.length = 2; + torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8, + gd_utf8.data, gd_utf8.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF8 to utf8 charset should fail due to too short"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to utf8 charset should fail E2BIG"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); + + /* Short input handling confirmation */ + gd_output.length = saved_len; + torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8, + gd_utf8.data, 2, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF8 to UTF8 should fail due to too short"); + torture_assert_errno_equal(tctx, EILSEQ, "conversion from short UTF8 to UTF8 should fail EINVAL"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); +#endif + + /* Short output handling confirmation */ + gd_output.length = 1; + torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8, + gd_utf16le.data, gd_utf16le.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF16 to UTF8 should fail due to too short"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to UTF8 should fail E2BIG"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); + torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF16 to UTF8 incorrect"); + + /* Short output handling confirmation */ + gd_output.length = 3; + torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8, + gd_utf16le.data, gd_utf16le.length, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF16 to UTF8 should fail due to too short"); + torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to UTF8 should fail E2BIG"); + torture_assert_int_equal(tctx, gd_output.length, 3, "Should get 3 bytes output for UTF8"); + + /* Short input handling confirmation */ + gd_output.length = saved_len; + torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8, + gd_utf16le.data, 3, + (void *)gd_output.data, gd_output.length, + &gd_output.length) == false, + "conversion from UTF16 to UTF8 should fail due to too short"); + torture_assert_errno_equal(tctx, EINVAL, "conversion from short UTF16 to UTF8 should fail EINVAL"); + torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output"); + + return true; +} + +static bool test_plato(struct torture_context *tctx) +{ + DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64); + DATA_BLOB plato_utf16le = base64_decode_data_blob(plato_utf16le_base64); + DATA_BLOB plato_output; + DATA_BLOB plato_output2; + + talloc_steal(tctx, plato_utf8.data); + talloc_steal(tctx, plato_utf16le.data); + + torture_assert(tctx, convert_string_talloc(tctx, + CH_UTF8, CH_UTF16LE, + plato_utf8.data, plato_utf8.length, + (void *)&plato_output.data, &plato_output.length), + "conversion of UTF8 ancient greek to UTF16 failed"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect"); + + torture_assert_int_equal(tctx, + strlen_m_ext((const char *)plato_utf8.data, + CH_UTF8, CH_UTF16LE), + plato_output.length / 2, + "checking strlen_m_ext of conversion of UTF8 to UTF16LE"); + + memset(plato_output.data, '\0', plato_output.length); + torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF16LE, + plato_utf8.data, plato_utf8.length, + (void *)plato_output.data, plato_output.length, + &plato_output.length), + "conversion of UTF8 ancient greek to UTF16 failed"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect"); + + torture_assert(tctx, convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + plato_output.data, plato_output.length, + (void *)&plato_output2.data, &plato_output2.length), + "conversion of UTF8 ancient greek to UTF16 failed"); + torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect"); + + memset(plato_output2.data, '\0', plato_output2.length); + torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8, + plato_output.data, plato_output.length, + (void *)plato_output2.data, plato_output2.length, &plato_output2.length), + "conversion of UTF8 ancient greek to UTF16 failed"); + torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect"); + + torture_assert(tctx, convert_string_talloc(tctx, + CH_UTF8, CH_UTF8, + plato_utf8.data, plato_utf8.length, + (void *)&plato_output.data, &plato_output.length), + "conversion of UTF8 to UTF8"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, + "conversion of UTF8 to UTF8"); + torture_assert_int_equal(tctx, + strlen_m_ext((const char *)plato_utf8.data, + CH_UTF8, CH_UTF8), + plato_output.length, + "checking strlen_m_ext of conversion of UTF8 to UTF8"); + memset(plato_output.data, '\0', plato_output.length); + torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8, + plato_utf8.data, plato_utf8.length, + (void *)plato_output.data, plato_output.length, + &plato_output.length), + "conversion of UTF8 to UTF8"); + torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, + "conversion of UTF8 to UTF8"); + + memset(plato_output.data, '\0', plato_output.length); + torture_assert(tctx, convert_string_error(CH_UTF8, CH_DOS, + plato_utf8.data, plato_utf8.length, + (void *)plato_output.data, plato_output.length, + &plato_output.length) == false, + "conversion of UTF8 to any dos charset should fail"); + torture_assert_errno_equal(tctx, EILSEQ, "conversion of UTF16 ancient greek to any DOS charset should fail EILSEQ"); + + torture_assert(tctx, convert_string_talloc(tctx, + CH_UTF8, CH_DOS, + plato_utf8.data, plato_utf8.length, + (void *)&plato_output.data, &plato_output.length) == false, + "conversion of UTF8 ancient greek to any DOS charset should fail"); + + /* Allocate only enough space for a partial conversion */ + plato_output = data_blob_talloc(tctx, NULL, 9); + torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8, + plato_utf16le.data, plato_utf16le.length, + (void *)plato_output.data, plato_output.length, + &plato_output.length) == false, + "conversion of UTF16 ancient greek to UTF8 should fail, not enough space"); + torture_assert_errno_equal(tctx, E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space"); + torture_assert_int_equal(tctx, plato_output.length, 8, + "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary"); + + plato_output = data_blob_talloc(tctx, NULL, 2); + torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8, + plato_utf16le.data, plato_utf16le.length, + (void *)plato_output.data, plato_output.length, + &plato_output.length) == false, + "conversion of UTF16 ancient greek to UTF8 should fail, not enough space"); + torture_assert_errno_equal(tctx, E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space"); + torture_assert_int_equal(tctx, plato_output.length, 0, + "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary"); + + + return true; +} + + + +static bool test_short_strings(struct torture_context *tctx) +{ + char zeros[6] = {0}; + char s[6] = {'s'}; + bool ok; + char *out; + size_t out_len; + + ok = convert_string_talloc(tctx, + CH_UTF8, CH_UTF16LE, + zeros, 0, + &out, &out_len); + torture_assert(tctx, ok, "{\"\", 0} to utf16 failed"); + torture_assert(tctx, out_len == 2, "{\"\", 0} length is two"); + torture_assert(tctx, out[0] == 0 && out[1] == 0, "{\"\", 0} utf16 is zero"); + TALLOC_FREE(out); + + ok = convert_string_talloc(tctx, + CH_UTF8, CH_UTF16LE, + zeros, 1, + &out, &out_len); + torture_assert(tctx, ok, "{\"\\0\", 1} to utf16 failed"); + torture_assert(tctx, out_len == 2, "{\"\\0\", 1} length is two"); + torture_assert(tctx, out[0] == 0 && out[1] == 0, "{\"\\0\", 1} utf16 is zero"); + TALLOC_FREE(out); + + ok = convert_string_talloc(tctx, + CH_UTF8, CH_UTF16LE, + zeros, 2, + &out, &out_len); + torture_assert(tctx, ok, "{\"\\0\\0\", 2} to utf16 failed"); + torture_assert(tctx, out_len == 4, "{\"\\0\\0\", 2} length is four"); + torture_assert(tctx, out[0] == 0 && out[1] == 0, "{\"\\0\\0\", 2} utf16 is zero"); + TALLOC_FREE(out); + + ok = convert_string_talloc(tctx, + CH_UTF8, CH_UTF16LE, + s, 0, + &out, &out_len); + torture_assert(tctx, ok, "{\"s\", 0} to utf16 failed"); + torture_assert(tctx, out_len == 2, "{\"s\", 0} length is two"); + torture_assert(tctx, out[0] == 0 && out[1] == 0, + "{\"s\", 0} utf16 is zero"); + TALLOC_FREE(out); + + ok = convert_string_talloc(tctx, + CH_UTF8, CH_UTF16LE, + s, 1, + &out, &out_len); + torture_assert(tctx, ok, "{\"s\", 1} to utf16 failed"); + torture_assert(tctx, out_len == 2, "{\"s\", 1} length is two"); + torture_assert(tctx, out[0] == 's' && out[1] == 0, + "{\"s\", 1} utf16 is s"); + TALLOC_FREE(out); + + ok = convert_string_talloc(tctx, + CH_UTF8, CH_UTF16LE, + s, 2, + &out, &out_len); + torture_assert(tctx, ok, "{\"s\\0\", 2} to utf16 failed"); + torture_assert(tctx, out_len == 4, "{\"s\\0\", 2} length is four"); + torture_assert(tctx, out[0] == 's' && out[1] == 0, + "{\"s\\0\", 0} utf16 is s"); + TALLOC_FREE(out); + + + /* going to utf8 */ + ok = convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + zeros, 0, + &out, &out_len); + torture_assert(tctx, ok, "{\"\", 0} to utf8 failed"); + torture_assert(tctx, out_len == 1, "{\"\", 0} length is one"); + torture_assert(tctx, out[0] == 0, "{\"\", 0} utf8[0] is zero"); + TALLOC_FREE(out); + + ok = convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + zeros, 2, + &out, &out_len); + torture_assert(tctx, ok, "{\"\\0\", 1} to utf8 failed"); + torture_assert(tctx, out_len == 1, "{\"\\0\", 1} length is one"); + torture_assert(tctx, out[0] == 0 && out[1] == 0, + "{\"\\0\", 1} utf8 is zero"); + TALLOC_FREE(out); + + ok = convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + zeros, 4, + &out, &out_len); + torture_assert(tctx, ok, "{\"\\0\\0\\0\\0\", 4} to utf8 failed"); + torture_assert(tctx, out_len == 2, "{\"\\0\\0\\0\\0\", 4} length is two"); + torture_assert(tctx, out[0] == 0 && out[1] == 0, + "{\"\\0\\0\\0\\0\", 4} utf8 is zero"); + TALLOC_FREE(out); + + ok = convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + s, 0, + &out, &out_len); + torture_assert(tctx, ok, "{\"s\", 0} to utf8 failed"); + torture_assert(tctx, out_len == 1, "{\"s\", 0} length is one"); + torture_assert(tctx, out[0] == 0, "{\"s\", 0} utf8 is zero"); + TALLOC_FREE(out); + + ok = convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + s, 2, + &out, &out_len); + torture_assert(tctx, ok, "{\"s\\0\", 2} to utf8 failed"); + torture_assert(tctx, out_len == 1, "{\"s\\0\", 2} length is one"); + torture_assert(tctx, out[0] == 's' && out[1] == 0, + "{\"s\\0\", 2} utf8 is s"); + TALLOC_FREE(out); + + + ok = convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + s, 4, + &out, &out_len); + torture_assert(tctx, ok, "{\"s\\0\\0\\0\", 4} utf8 failed"); + torture_assert(tctx, out_len == 2, "\"s\\0\\0\\0\", 4} utf8 length is two"); + torture_assert(tctx, out[0] == 's' && out[1] == 0, + "{\"s\\0\\0\\0\", 4} utf8 is s"); + TALLOC_FREE(out); + + /* odd numbers of bytes from UTF-16 should fail */ + ok = convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + s, 1, + &out, &out_len); + torture_assert(tctx, ! ok, "{\"s\", 1} to utf8 should have failed"); + + ok = convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + s, 3, + &out, &out_len); + torture_assert(tctx, ! ok, "{\"s\\0\\0\", 3} to utf8 should have failed"); + + ok = convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + zeros, 1, + &out, &out_len); + torture_assert(tctx, ! ok, + "{\"\\0\", 1} to utf8 should have failed"); + + ok = convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + zeros, 5, + &out, &out_len); + torture_assert(tctx, ! ok, + "{\"\\0\\0\\0\\0\", 5} to utf8 should have failed"); + + return true; +} + + +static bool test_plato_latin(struct torture_context *tctx) +{ + DATA_BLOB plato_latin_utf8 = base64_decode_data_blob(plato_latin_utf8_base64); + DATA_BLOB plato_latin_utf16le = base64_decode_data_blob(plato_latin_utf16le_base64); + DATA_BLOB plato_latin_output; + + talloc_steal(tctx, plato_latin_utf8.data); + talloc_steal(tctx, plato_latin_utf16le.data); + + torture_assert(tctx, convert_string_talloc(tctx, + CH_UTF16LE, CH_UTF8, + plato_latin_utf16le.data, plato_latin_utf16le.length, + (void *)&plato_latin_output.data, &plato_latin_output.length), + "conversion of UTF16 latin charset greek to unix charset UTF8 failed"); + torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF16 to UTF8 incorrect"); + + torture_assert_int_equal(tctx, + strlen_m_ext((const char *)plato_latin_output.data, + CH_UTF8, CH_UTF16LE), + plato_latin_utf16le.length / 2, + "checking strlen_m_ext UTF16 latin charset greek to UTF8"); + torture_assert(tctx, convert_string_talloc(tctx, + CH_UTF8, CH_UTF16LE, + plato_latin_utf8.data, plato_latin_utf8.length, + (void *)&plato_latin_output.data, &plato_latin_output.length), + "conversion of UTF16 latin charset greek to UTF16LE failed"); + torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf16le, "conversion from UTF8 to UTF16LE incorrect"); + + return true; +} + +static bool test_gd_case(struct torture_context *tctx) +{ + DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64); + char *gd_unix; + size_t gd_size; + char *gd_lower, *gd_upper; + talloc_steal(tctx, gd_utf8.data); + + torture_assert(tctx, convert_string_talloc(tctx, CH_UTF8, CH_UNIX, + gd_utf8.data, gd_utf8.length, + (void *)&gd_unix, &gd_size), + "conversion of unix charset to UTF8"); + + gd_lower = strlower_talloc(tctx, gd_unix); + torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case"); + gd_upper = strupper_talloc_n(tctx, gd_unix, gd_size); + torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case"); + + torture_assert(tctx, + strhasupper(gd_unix), + "GD's name has an upper case character"); + torture_assert(tctx, + strhaslower(gd_unix), + "GD's name has an lower case character"); + torture_assert(tctx, + strhasupper(gd_upper), + "upper case name has an upper case character"); + torture_assert(tctx, + strhaslower(gd_lower), + "lower case name has an lower case character"); + torture_assert(tctx, + strhasupper(gd_lower) == false, + "lower case name has no upper case character"); + torture_assert(tctx, + strhaslower(gd_upper) == false, + "upper case name has no lower case character"); + + torture_assert(tctx, strcasecmp_m(gd_unix, + gd_upper) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strcasecmp_m(gd_unix, + gd_lower) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strcasecmp_m(gd_upper, + gd_lower) == 0, + "case insensitive comparison upper/lower"); + + /* This string isn't different in length upper/lower, but just check the first 5 chars */ + torture_assert(tctx, strncasecmp_m(gd_unix, + gd_upper, 5) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strncasecmp_m(gd_unix, + gd_lower, 5) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strncasecmp_m(gd_upper, + gd_lower, 5) == 0, + "case insensitive comparison upper/lower"); + return true; +} + +static bool test_plato_case(struct torture_context *tctx) +{ + DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64); + char *plato_unix; + size_t plato_length; + char *plato_lower, *plato_upper; + talloc_steal(tctx, plato_utf8.data); + + torture_assert(tctx, convert_string_talloc(tctx, CH_UTF8, CH_UNIX, + plato_utf8.data, plato_utf8.length, + (void *)&plato_unix, &plato_length), + "conversion of unix charset to UTF8"); + + torture_assert(tctx, + strhasupper(plato_unix), + "PLATO's apology has an upper case character"); + torture_assert(tctx, + strhaslower(plato_unix), + "PLATO's apology has an lower case character"); + plato_lower = strlower_talloc(tctx, plato_unix); + torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into lower case"); + plato_upper = strupper_talloc_n(tctx, plato_unix, plato_utf8.length); + torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into upper case"); + + torture_assert(tctx, + strhasupper(plato_upper), + "upper case string has an upper case character"); + torture_assert(tctx, + strhaslower(plato_lower), + "lower case string has an lower case character"); + torture_assert(tctx, + strhasupper(plato_lower) == false, + "lower case string has no upper case character"); + torture_assert(tctx, + strhaslower(plato_upper) == false, + "upper case string has no lower case character"); + + torture_assert(tctx, strcasecmp_m(plato_unix, + plato_upper) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strcasecmp_m(plato_unix, + plato_lower) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strcasecmp_m(plato_upper, + plato_lower) == 0, + "case insensitive comparison upper/lower"); + return true; +} + +struct torture_suite *torture_local_convert_string_handle(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "convert_string_handle"); + torture_suite_add_simple_test(suite, "cp850 high points", test_cp850_high_points); + + torture_suite_add_simple_test(suite, "gd_ascii", test_gd_ascii_handle); + torture_suite_add_simple_test(suite, "gd_minus_1", test_gd_minus_1_handle); + torture_suite_add_simple_test(suite, "gd_iso8859_cp850", test_gd_iso8859_cp850_handle); + torture_suite_add_simple_test(suite, "plato_english_iso8859_cp850", test_plato_english_iso8859_cp850_handle); + torture_suite_add_simple_test(suite, "plato_english_minus_1", test_plato_english_minus_1_handle); + torture_suite_add_simple_test(suite, "plato_cp850_utf8", test_plato_cp850_utf8_handle); + torture_suite_add_simple_test(suite, "plato_minus_1", test_plato_minus_1_handle); + torture_suite_add_simple_test(suite, "plato_latin_cp850_utf8", test_plato_latin_cp850_utf8_handle); + torture_suite_add_simple_test(suite, "utf8-nfc-to-nfd", test_utf8_nfc_to_nfd); + torture_suite_add_simple_test(suite, "utf8-nfc-to-nfd-overflow", test_utf8_nfc_to_nfd_overflow); + torture_suite_add_simple_test(suite, "utf8-nfd-to-nfc", test_utf8_nfd_to_nfc); + return suite; +} + +struct torture_suite *torture_local_string_case_handle(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "string_case_handle"); + + torture_suite_add_simple_test(suite, "gd_case_utf8", test_gd_case_utf8_handle); + torture_suite_add_simple_test(suite, "gd_case_cp850", test_gd_case_cp850_handle); + torture_suite_add_simple_test(suite, "plato_case_utf8", test_plato_case_utf8_handle); + return suite; +} + +struct torture_suite *torture_local_convert_string(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "convert_string"); + + torture_suite_add_simple_test(suite, "short_strings", test_short_strings); + torture_suite_add_simple_test(suite, "gd", test_gd); + torture_suite_add_simple_test(suite, "plato", test_plato); + torture_suite_add_simple_test(suite, "plato_latin", test_plato_latin); + return suite; +} + +struct torture_suite *torture_local_string_case(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "string_case_handle"); + + torture_suite_add_simple_test(suite, "gd_case", test_gd_case); + torture_suite_add_simple_test(suite, "plato_case", test_plato_case); + return suite; +} diff --git a/lib/util/charset/tests/iconv.c b/lib/util/charset/tests/iconv.c new file mode 100644 index 0000000..3733c3c --- /dev/null +++ b/lib/util/charset/tests/iconv.c @@ -0,0 +1,495 @@ +/* + Unix SMB/CIFS implementation. + + local testing of iconv routines. This tests the system iconv code against + the built-in iconv code + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "system/iconv.h" +#include "system/time.h" +#include "libcli/raw/libcliraw.h" +#include "param/param.h" +#include "torture/util.h" +#include "torture/local/proto.h" +#include "talloc.h" + +#ifdef HAVE_NATIVE_ICONV + +static bool iconv_untestable(struct torture_context *tctx) +{ + iconv_t cd; + + cd = iconv_open("UTF-16LE", "UCS-4LE"); + if (cd == (iconv_t)-1) + torture_skip(tctx, "unable to test - system iconv library does not support UTF-16LE -> UCS-4LE"); + iconv_close(cd); + + cd = iconv_open("UTF-16LE", "CP850"); + if (cd == (iconv_t)-1) + torture_skip(tctx, "unable to test - system iconv library does not support UTF-16LE -> CP850\n"); + iconv_close(cd); + + return false; +} + +/* + generate a UTF-16LE buffer for a given unicode codepoint +*/ +static int gen_codepoint_utf16(unsigned int codepoint, + char *buf, size_t *size) +{ + static iconv_t cd; + uint8_t in[4]; + char *ptr_in; + size_t size_in, size_out, ret; + if (!cd) { + cd = iconv_open("UTF-16LE", "UCS-4LE"); + if (cd == (iconv_t)-1) { + cd = NULL; + return -1; + } + } + + in[0] = codepoint & 0xFF; + in[1] = (codepoint>>8) & 0xFF; + in[2] = (codepoint>>16) & 0xFF; + in[3] = (codepoint>>24) & 0xFF; + + ptr_in = (char *)in; + size_in = 4; + size_out = 8; + + ret = iconv(cd, &ptr_in, &size_in, &buf, &size_out); + + *size = 8 - size_out; + + return ret; +} + + +/* + work out the unicode codepoint of the first UTF-8 character in the buffer +*/ +static unsigned int get_codepoint(char *buf, size_t size, const char *charset) +{ + iconv_t cd; + uint8_t out[4]; + char *ptr_out; + size_t size_out, size_in, ret; + + cd = iconv_open("UCS-4LE", charset); + + size_in = size; + ptr_out = (char *)out; + size_out = sizeof(out); + memset(out, 0, sizeof(out)); + + ret = iconv(cd, &buf, &size_in, &ptr_out, &size_out); + iconv_close(cd); + if (ret == (size_t) -1) { + return (unsigned int)-1; + } + + return out[0] | (out[1]<<8) | (out[2]<<16) | (out[3]<<24); +} + +/* + display a buffer with name prefix +*/ +static void show_buf(const char *name, uint8_t *buf, size_t size) +{ + int i; + printf("%s ", name); + for (i=0;i<size;i++) { + printf("%02x ", buf[i]); + } + printf("\n"); +} + +/* + given a UTF-16LE buffer, test the system and built-in iconv code to + make sure they do exactly the same thing in converting the buffer to + "charset", then convert it back again and ensure we get the same + buffer back +*/ +static bool test_buffer(struct torture_context *test, + uint8_t *inbuf, size_t size, const char *charset) +{ + uint8_t buf1[1000], buf2[1000], buf3[1000]; + size_t outsize1, outsize2, outsize3; + const char *ptr_in1; + char *ptr_in2; + char *ptr_out; + size_t size_in1, size_in2, size_in3; + size_t ret1, ret2, ret3, len1, len2; + int errno1, errno2; + static iconv_t cd; + static smb_iconv_t cd2, cd3; + static const char *last_charset; + + if (cd && last_charset) { + iconv_close(cd); + smb_iconv_close(cd2); + smb_iconv_close(cd3); + cd = NULL; + } + + if (!cd) { + cd = iconv_open(charset, "UTF-16LE"); + if (cd == (iconv_t)-1) { + torture_fail(test, + talloc_asprintf(test, + "failed to open %s to UTF-16LE", + charset)); + } + cd2 = smb_iconv_open_ex(test, charset, "UTF-16LE", lpcfg_parm_bool(test->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + if (cd2 == (iconv_t)-1) { + torture_fail(test, + talloc_asprintf(test, + "failed to open %s to UTF-16LE via smb_iconv_open_ex", + charset)); + } + cd3 = smb_iconv_open_ex(test, "UTF-16LE", charset, lpcfg_parm_bool(test->lp_ctx, NULL, "iconv", "use_builtin_handlers", true)); + if (cd3 == (iconv_t)-1) { + torture_fail(test, + talloc_asprintf(test, + "failed to open UTF-16LE to %s via smb_iconv_open_ex", + charset)); + } + last_charset = charset; + } + + /* internal convert to charset - placing result in buf1 */ + ptr_in1 = (const char *)inbuf; + ptr_out = (char *)buf1; + size_in1 = size; + outsize1 = sizeof(buf1); + + memset(ptr_out, 0, outsize1); + errno = 0; + ret1 = smb_iconv(cd2, &ptr_in1, &size_in1, &ptr_out, &outsize1); + errno1 = errno; + + /* system convert to charset - placing result in buf2 */ + ptr_in2 = (char *)inbuf; + ptr_out = (char *)buf2; + size_in2 = size; + outsize2 = sizeof(buf2); + + memset(ptr_out, 0, outsize2); + errno = 0; + ret2 = iconv(cd, &ptr_in2, &size_in2, &ptr_out, &outsize2); + errno2 = errno; + + len1 = sizeof(buf1) - outsize1; + len2 = sizeof(buf2) - outsize2; + + /* codepoints above 1M are not interesting for now */ + if (len2 > len1 && + memcmp(buf1, buf2, len1) == 0 && + get_codepoint((char *)(buf2+len1), len2-len1, charset) >= (1<<20)) { + return true; + } + if (len1 > len2 && + memcmp(buf1, buf2, len2) == 0 && + get_codepoint((char *)(buf1+len2), len1-len2, charset) >= (1<<20)) { + return true; + } + + torture_assert_int_equal(test, ret1, ret2, "ret mismatch"); + + if (errno1 != errno2) { + show_buf(" rem1:", inbuf+(size-size_in1), size_in1); + show_buf(" rem2:", inbuf+(size-size_in2), size_in2); + torture_fail(test, talloc_asprintf(test, + "errno mismatch with %s internal=%d/%s system=%d/%s", + charset, + errno1, strerror(errno1), + errno2, strerror(errno2))); + } + + torture_assert_int_equal(test, outsize1, outsize2, "outsize mismatch"); + + torture_assert_int_equal(test, size_in1, size_in2, "size_in mismatch"); + + if (len1 != len2 || + memcmp(buf1, buf2, len1) != 0) { + torture_comment(test, "size=%d ret1=%d ret2=%d", (int)size, (int)ret1, (int)ret2); + show_buf(" IN1:", inbuf, size-size_in1); + show_buf(" IN2:", inbuf, size-size_in2); + show_buf("OUT1:", buf1, len1); + show_buf("OUT2:", buf2, len2); + if (len2 > len1 && memcmp(buf1, buf2, len1) == 0) { + torture_comment(test, "next codepoint is %u", + get_codepoint((char *)(buf2+len1), len2-len1, charset)); + } + if (len1 > len2 && memcmp(buf1, buf2, len2) == 0) { + torture_comment(test, "next codepoint is %u", + get_codepoint((char *)(buf1+len2),len1-len2, charset)); + } + + torture_fail(test, "failed"); + } + + /* convert back to UTF-16, putting result in buf3 */ + size = size - size_in1; + ptr_in1 = (const char *)buf1; + ptr_out = (char *)buf3; + size_in3 = len1; + outsize3 = sizeof(buf3); + + memset(ptr_out, 0, outsize3); + ret3 = smb_iconv(cd3, &ptr_in1, &size_in3, &ptr_out, &outsize3); + + /* we only internally support the first 1M codepoints */ + if (outsize3 != sizeof(buf3) - size && + get_codepoint((char *)(inbuf+sizeof(buf3) - outsize3), + size - (sizeof(buf3) - outsize3), + "UTF-16LE") >= (1<<20)) { + return true; + } + + torture_assert_int_equal(test, ret3, 0, talloc_asprintf(test, + "pull failed - %s", strerror(errno))); + + if (strncmp(charset, "UTF", 3) != 0) { + /* don't expect perfect mappings for non UTF charsets */ + return true; + } + + + torture_assert_int_equal(test, outsize3, sizeof(buf3) - size, + "wrong outsize3"); + + if (memcmp(buf3, inbuf, size) != 0) { + torture_comment(test, "pull bytes mismatch:"); + show_buf("inbuf", inbuf, size); + show_buf(" buf3", buf3, sizeof(buf3) - outsize3); + torture_comment(test, "next codepoint is %u\n", + get_codepoint((char *)(inbuf+sizeof(buf3) - outsize3), + size - (sizeof(buf3) - outsize3), + "UTF-16LE")); + torture_fail(test, ""); + } + + return true; +} + + +/* + test the push_codepoint() and next_codepoint() functions for a given + codepoint +*/ +static bool test_codepoint(struct torture_context *tctx, unsigned int codepoint) +{ + uint8_t buf[10]; + size_t size, size2; + codepoint_t c; + + size = push_codepoint_handle(lpcfg_iconv_handle(tctx->lp_ctx), (char *)buf, codepoint); + torture_assert(tctx, size != -1 || (codepoint >= 0xd800 && codepoint <= 0x10000), + "Invalid Codepoint range"); + + if (size == -1) return true; + + buf[size] = random(); + buf[size+1] = random(); + buf[size+2] = random(); + buf[size+3] = random(); + + c = next_codepoint_handle(lpcfg_iconv_handle(tctx->lp_ctx), (char *)buf, &size2); + + torture_assert(tctx, c == codepoint, + talloc_asprintf(tctx, + "next_codepoint(%u) failed - gave %u", codepoint, c)); + + torture_assert(tctx, size2 == size, + talloc_asprintf(tctx, "next_codepoint(%u) gave wrong size %d (should be %d)\n", + codepoint, (int)size2, (int)size)); + + return true; +} + +static bool test_next_codepoint(struct torture_context *tctx) +{ + unsigned int codepoint; + if (iconv_untestable(tctx)) + return true; + + for (codepoint=0;codepoint<(1<<20);codepoint++) { + if (!test_codepoint(tctx, codepoint)) + return false; + } + return true; +} + +static bool test_first_1m(struct torture_context *tctx) +{ + unsigned int codepoint; + size_t size; + unsigned char inbuf[1000]; + + if (iconv_untestable(tctx)) + return true; + + for (codepoint=0;codepoint<(1<<20);codepoint++) { + if (gen_codepoint_utf16(codepoint, (char *)inbuf, &size) != 0) { + continue; + } + + if (codepoint % 1000 == 0) { + if (torture_setting_bool(tctx, "progress", true)) { + torture_comment(tctx, "codepoint=%u \r", codepoint); + fflush(stdout); + } + } + + if (!test_buffer(tctx, inbuf, size, "UTF-8")) + return false; + } + return true; +} + +static bool test_random_5m(struct torture_context *tctx) +{ + unsigned char inbuf[1000]; + unsigned int i; + + if (iconv_untestable(tctx)) + return true; + + for (i=0;i<500000;i++) { + size_t size; + unsigned int c; + + if (i % 1000 == 0) { + if (torture_setting_bool(tctx, "progress", true)) { + torture_comment(tctx, "i=%u \r", i); + fflush(stdout); + } + } + + size = random() % 100; + for (c=0;c<size;c++) { + if (random() % 100 < 80) { + inbuf[c] = random() % 128; + } else { + inbuf[c] = random(); + } + if (random() % 10 == 0) { + inbuf[c] |= 0xd8; + } + if (random() % 10 == 0) { + inbuf[c] |= 0xdc; + } + } + if (!test_buffer(tctx, inbuf, size, "UTF-8")) { + printf("i=%d failed UTF-8\n", i); + return false; + } + + if (!test_buffer(tctx, inbuf, size, "CP850")) { + printf("i=%d failed CP850\n", i); + return false; + } + } + return true; +} + + +static bool test_string2key(struct torture_context *tctx) +{ + uint16_t *buf; + char *dest = NULL; + TALLOC_CTX *mem_ctx = talloc_new(tctx); + size_t len = (random()%1000)+1; + const uint16_t in1[10] = { 'a', 0xd805, 'b', 0xdcf0, 'c', 0, 'd', 'e', 'f', 'g' }; + uint8_t le1[20]; + uint8_t *munged1; + uint8_t *out1; + size_t ret; + int i; + const char *correct = "a\357\277\275b\357\277\275c\001defg"; + + buf = talloc_size(mem_ctx, len*2); + generate_random_buffer((uint8_t *)buf, len*2); + + torture_comment(tctx, "converting random buffer\n"); + + if (!convert_string_talloc(mem_ctx, CH_UTF16MUNGED, CH_UTF8, (void *)buf, len*2, (void**)&dest, &ret)) { + torture_fail(tctx, "Failed to convert random buffer\n"); + } + + for (i=0;i<10;i++) { + SSVAL(&le1[2*i], 0, in1[i]); + } + + torture_comment(tctx, "converting fixed buffer to UTF16\n"); + + if (!convert_string_talloc(mem_ctx, CH_UTF16MUNGED, CH_UTF16, (void *)le1, 20, (void**)&munged1, &ret)) { + torture_fail(tctx, "Failed to convert fixed buffer to UTF16_MUNGED\n"); + } + + torture_assert(tctx, ret == 20, "conversion should give 20 bytes\n"); + + torture_comment(tctx, "converting fixed buffer to UTF8\n"); + + if (!convert_string_talloc(mem_ctx, CH_UTF16MUNGED, CH_UTF8, (void *)le1, 20, (void**)&out1, &ret)) { + torture_fail(tctx, "Failed to convert fixed buffer to UTF8\n"); + } + + torture_assert(tctx, strcmp(correct, (const char *) out1) == 0, + "conversion gave incorrect result\n"); + + talloc_free(mem_ctx); + + return true; +} + +struct torture_suite *torture_local_iconv(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "iconv"); + + torture_suite_add_simple_test(suite, "string2key", + test_string2key); + + torture_suite_add_simple_test(suite, "next_codepoint()", + test_next_codepoint); + + torture_suite_add_simple_test(suite, "first 1M codepoints", + test_first_1m); + + torture_suite_add_simple_test(suite, "5M random UTF-16LE sequences", + test_random_5m); + + torture_suite_add_simple_test(suite, "string2key", + test_string2key); + return suite; +} + +#else + +struct torture_suite *torture_local_iconv(TALLOC_CTX *mem_ctx) +{ + printf("No native iconv library - can't run iconv test\n"); + return NULL; +} + +#endif diff --git a/lib/util/charset/tests/util_unistr.c b/lib/util/charset/tests/util_unistr.c new file mode 100644 index 0000000..1a9fcaa --- /dev/null +++ b/lib/util/charset/tests/util_unistr.c @@ -0,0 +1,166 @@ +/* + Unix SMB/CIFS implementation. + test suite for the util_unistr utility functions + + Copyright (C) Catalyst.Net Ltd. 2023 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" + +#undef strcasecmp +#undef strncasecmp + +struct torture_suite *torture_local_util_unistr(TALLOC_CTX *mem_ctx); + +static bool test_utf16_len(struct torture_context *tctx) +{ + static const uint16_t empty_string[] = {'\0'}; + static const uint16_t foo_bar[] = { + 'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'}; + static const uint16_t foo_bar_alternative[] = {0xd83c, + 0xdd75, + 0xd83c, + 0xdd7e, + 0xd83c, + 0xdd7e, + ' ', + 0xd83c, + 0xdd31, + 0xd83c, + 0xdd30, + 0xd83c, + 0xdd41, + '\0'}; + + torture_assert_size_equal(tctx, + utf16_len(empty_string), + 0, + "length of empty string"); + torture_assert_size_equal(tctx, + utf16_null_terminated_len(empty_string), + 2, + "null‐terminated length of empty string"); + torture_assert_size_equal(tctx, + utf16_len(foo_bar), + 14, + "length of “foo bar”"); + torture_assert_size_equal(tctx, + utf16_null_terminated_len(foo_bar), + 16, + "null‐terminated length of “foo bar”"); + torture_assert_size_equal(tctx, + utf16_len(foo_bar_alternative), + 26, + "length of “🅵🅾🅾 🄱🄰🅁”"); + torture_assert_size_equal(tctx, + utf16_null_terminated_len( + foo_bar_alternative), + 28, + "null‐terminated length of “🅵🅾🅾 🄱🄰🅁”"); + + return true; +} + +static bool test_utf16_len_n(struct torture_context *tctx) +{ + static const uint16_t empty_string[] = {'\0'}; + static const uint16_t foo_bar[] = {'f', 'o', 'o', ' ', 'b', 'a', 'r'}; + static const uint16_t null_terminated_foo_bar[] = { + 'f', 'o', 'o', ' ', 'b', 'a', 'r', '\0'}; + static const uint16_t twice_null_terminated_abc[] = { + 'a', 'b', 'c', '\0', '\0'}; + + torture_assert_size_equal(tctx, + utf16_len_n(empty_string, 0), + 0, + "length of empty string"); + torture_assert_size_equal(tctx, + utf16_null_terminated_len_n(empty_string, 0), + 0, + "null‐terminated length of empty string"); + + torture_assert_size_equal(tctx, + utf16_len_n(empty_string, + sizeof empty_string), + 0, + "length of null‐terminated empty string"); + torture_assert_size_equal( + tctx, + utf16_null_terminated_len_n(empty_string, sizeof empty_string), + 2, + "null‐terminated length of null‐terminated empty string"); + + torture_assert_size_equal(tctx, + utf16_len_n(foo_bar, sizeof foo_bar), + 14, + "length of “foo bar”"); + torture_assert_size_equal(tctx, + utf16_null_terminated_len_n(foo_bar, + sizeof foo_bar), + 14, + "null‐terminated length of “foo bar”"); + + torture_assert_size_equal(tctx, + utf16_len_n(null_terminated_foo_bar, + sizeof null_terminated_foo_bar), + 14, + "length of null‐terminated “foo bar”"); + torture_assert_size_equal( + tctx, + utf16_null_terminated_len_n(null_terminated_foo_bar, + sizeof null_terminated_foo_bar), + 16, + "null‐terminated length of null‐terminated “foo bar”"); + + torture_assert_size_equal(tctx, + utf16_len_n(null_terminated_foo_bar, + sizeof null_terminated_foo_bar - + 1), + 14, + "length of “foo bar” minus one byte"); + torture_assert_size_equal( + tctx, + utf16_null_terminated_len_n(null_terminated_foo_bar, + sizeof null_terminated_foo_bar - 1), + 14, + "null‐terminated length of “foo bar” minus one byte"); + + torture_assert_size_equal(tctx, + utf16_len_n(twice_null_terminated_abc, + sizeof twice_null_terminated_abc), + 6, + "length of twice–null‐terminated “abc”"); + torture_assert_size_equal( + tctx, + utf16_null_terminated_len_n(twice_null_terminated_abc, + sizeof twice_null_terminated_abc), + 8, + "null‐terminated length of twice–null‐terminated “abc”"); + + return true; +} + +struct torture_suite *torture_local_util_unistr(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, + "util_unistr"); + + torture_suite_add_simple_test(suite, "utf16_len", test_utf16_len); + torture_suite_add_simple_test(suite, "utf16_len_n", test_utf16_len_n); + + return suite; +} diff --git a/lib/util/charset/util_str.c b/lib/util/charset/util_str.c new file mode 100644 index 0000000..1650c9b --- /dev/null +++ b/lib/util/charset/util_str.c @@ -0,0 +1,608 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Simo Sorce 2001 + Copyright (C) Andrew Bartlett 2011 + Copyright (C) Jeremy Allison 1992-2007 + Copyright (C) Martin Pool 2003 + Copyright (C) James Peach 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/locale.h" +#include "charset.h" +#include "lib/util/fault.h" + +#ifdef strcasecmp +#undef strcasecmp +#endif +#ifdef strncasecmp +#undef strncasecmp +#endif + + +/** + Case insensitive string comparison, handle specified for testing +**/ +_PUBLIC_ int strcasecmp_m_handle(struct smb_iconv_handle *iconv_handle, + const char *s1, const char *s2) +{ + codepoint_t c1=0, c2=0; + codepoint_t u1=0, u2=0; + codepoint_t l1=0, l2=0; + size_t size1, size2; + + /* handle null ptr comparisons to simplify the use in qsort */ + if (s1 == s2) return 0; + if (s1 == NULL) return -1; + if (s2 == NULL) return 1; + + while (*s1 && *s2) { + c1 = next_codepoint_handle(iconv_handle, s1, &size1); + c2 = next_codepoint_handle(iconv_handle, s2, &size2); + + if (c1 == INVALID_CODEPOINT || + c2 == INVALID_CODEPOINT) { + return strcasecmp(s1, s2); + } + + s1 += size1; + s2 += size2; + + if (c1 == c2) { + continue; + } + + u1 = toupper_m(c1); + u2 = toupper_m(c2); + if (u1 == u2) { + continue; + } + + l1 = tolower_m(c1); + l2 = tolower_m(c2); + if (l1 == l2) { + continue; + } + + return l1 - l2; + } + + return *s1 - *s2; +} + +/** + Case insensitive string comparison +**/ +_PUBLIC_ int strcasecmp_m(const char *s1, const char *s2) +{ + struct smb_iconv_handle *iconv_handle = get_iconv_handle(); + return strcasecmp_m_handle(iconv_handle, s1, s2); +} + +/** + Case insensitive string comparison, length limited, handle specified for + testing +**/ +_PUBLIC_ int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle, + const char *s1, const char *s2, size_t n) +{ + codepoint_t c1=0, c2=0; + codepoint_t u1=0, u2=0; + codepoint_t l1=0, l2=0; + size_t size1, size2; + + /* handle null ptr comparisons to simplify the use in qsort */ + if (s1 == s2) return 0; + if (s1 == NULL) return -1; + if (s2 == NULL) return 1; + + while (*s1 && *s2 && n) { + n--; + + c1 = next_codepoint_handle(iconv_handle, s1, &size1); + c2 = next_codepoint_handle(iconv_handle, s2, &size2); + + if (c1 == INVALID_CODEPOINT || + c2 == INVALID_CODEPOINT) { + /* + * n was specified in characters, + * now we must convert it to bytes. + * As bytes are the smallest + * character unit, the following + * increment and strncasecmp is always + * safe. + * + * The source string was already known + * to be n characters long, so we are + * guaranteed to be able to look at the + * (n remaining + size1) bytes from the + * s1 position). + */ + n += size1; + return strncasecmp(s1, s2, n); + } + + s1 += size1; + s2 += size2; + + if (c1 == c2) { + continue; + } + + u1 = toupper_m(c1); + u2 = toupper_m(c2); + if (u1 == u2) { + continue; + } + + l1 = tolower_m(c1); + l2 = tolower_m(c2); + if (l1 == l2) { + continue; + } + + return l1 - l2; + } + + if (n == 0) { + return 0; + } + + return *s1 - *s2; +} + +/** + Case insensitive string comparison, length limited +**/ +_PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n) +{ + struct smb_iconv_handle *iconv_handle = get_iconv_handle(); + return strncasecmp_m_handle(iconv_handle, s1, s2, n); +} + +/** + * Compare 2 strings. + * + * @note The comparison is case-insensitive. + **/ +_PUBLIC_ bool strequal_m(const char *s1, const char *s2) +{ + return strcasecmp_m(s1,s2) == 0; +} + +/** + Compare 2 strings (case sensitive). +**/ +_PUBLIC_ bool strcsequal(const char *s1,const char *s2) +{ + if (s1 == s2) + return true; + if (!s1 || !s2) + return false; + + return strcmp(s1,s2) == 0; +} + +/** + * Calculate the number of units (8 or 16-bit, depending on the + * destination charset) that would be needed to convert the input + * string, which is expected to be in src_charset encoding, to the + * destination charset (which should be a unicode charset). + */ +_PUBLIC_ size_t strlen_m_ext_handle(struct smb_iconv_handle *ic, + const char *s, charset_t src_charset, charset_t dst_charset) +{ + size_t count = 0; + +#ifdef DEVELOPER + switch (dst_charset) { + case CH_DOS: + case CH_UNIX: + smb_panic("cannot call strlen_m_ext() with a variable dest charset (must be UTF16* or UTF8)"); + default: + break; + } + + switch (src_charset) { + case CH_UTF16LE: + case CH_UTF16BE: + smb_panic("cannot call strlen_m_ext() with a UTF16 src charset (must be DOS, UNIX, DISPLAY or UTF8)"); + default: + break; + } +#endif + if (!s) { + return 0; + } + + while (*s && !(((uint8_t)*s) & 0x80)) { + s++; + count++; + } + + if (!*s) { + return count; + } + + while (*s) { + size_t c_size; + codepoint_t c = next_codepoint_handle_ext(ic, s, strnlen(s, 5), + src_charset, &c_size); + s += c_size; + + switch (dst_charset) { + case CH_UTF16LE: + case CH_UTF16BE: + case CH_UTF16MUNGED: + if (c < 0x10000) { + /* Unicode char fits into 16 bits. */ + count += 1; + } else { + /* Double-width unicode char - 32 bits. */ + count += 2; + } + break; + case CH_UTF8: + /* + * this only checks ranges, and does not + * check for invalid codepoints + */ + if (c < 0x80) { + count += 1; + } else if (c < 0x800) { + count += 2; + } else if (c < 0x10000) { + count += 3; + } else { + count += 4; + } + break; + default: + /* + * non-unicode encoding: + * assume that each codepoint fits into + * one unit in the destination encoding. + */ + count += 1; + } + } + + return count; +} + +/** + * Calculate the number of units (8 or 16-bit, depending on the + * destination charset) that would be needed to convert the input + * string, which is expected to be in src_charset encoding, to the + * destination charset (which should be a unicode charset). + */ +_PUBLIC_ size_t strlen_m_ext(const char *s, charset_t src_charset, charset_t dst_charset) +{ + struct smb_iconv_handle *ic = get_iconv_handle(); + return strlen_m_ext_handle(ic, s, src_charset, dst_charset); +} + +_PUBLIC_ size_t strlen_m_ext_term(const char *s, const charset_t src_charset, + const charset_t dst_charset) +{ + if (!s) { + return 0; + } + return strlen_m_ext(s, src_charset, dst_charset) + 1; +} + +_PUBLIC_ size_t strlen_m_ext_term_null(const char *s, + const charset_t src_charset, + const charset_t dst_charset) +{ + size_t len; + if (!s) { + return 0; + } + len = strlen_m_ext(s, src_charset, dst_charset); + if (len == 0) { + return 0; + } + + return len+1; +} + +/** + * Calculate the number of 16-bit units that would be needed to convert + * the input string, which is expected to be in CH_UNIX encoding, to UTF16. + * + * This will be the same as the number of bytes in a string for single + * byte strings, but will be different for multibyte. + */ +_PUBLIC_ size_t strlen_m(const char *s) +{ + return strlen_m_ext(s, CH_UNIX, CH_UTF16LE); +} + +/** + Work out the number of multibyte chars in a string, including the NULL + terminator. +**/ +_PUBLIC_ size_t strlen_m_term(const char *s) +{ + return strlen_m_ext_term(s, CH_UNIX, CH_UTF16LE); +} + +/* + * Weird helper routine for the winreg pipe: If nothing is around, return 0, + * if a string is there, include the terminator. + */ + +_PUBLIC_ size_t strlen_m_term_null(const char *s) +{ + return strlen_m_ext_term_null(s, CH_UNIX, CH_UTF16LE); +} + +/** + Strchr and strrchr_m are a bit complex on general multi-byte strings. +**/ +_PUBLIC_ char *strchr_m(const char *src, char c) +{ + const char *s; + struct smb_iconv_handle *ic = get_iconv_handle(); + if (src == NULL) { + return NULL; + } + /* characters below 0x3F are guaranteed to not appear in + non-initial position in multi-byte charsets */ + if ((c & 0xC0) == 0) { + return strchr(src, c); + } + + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars) */ + + for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) { + if (*s == c) + return discard_const_p(char, s); + } + + if (!*s) + return NULL; + +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + /* With compose characters we must restart from the beginning. JRA. */ + s = src; +#endif + + while (*s) { + size_t size; + codepoint_t c2 = next_codepoint_handle(ic, s, &size); + if (c2 == c) { + return discard_const_p(char, s); + } + s += size; + } + + return NULL; +} + +/** + * Multibyte-character version of strrchr + */ +_PUBLIC_ char *strrchr_m(const char *s, char c) +{ + struct smb_iconv_handle *ic; + char *ret = NULL; + + if (s == NULL) { + return NULL; + } + + /* characters below 0x3F are guaranteed to not appear in + non-initial position in multi-byte charsets */ + if ((c & 0xC0) == 0) { + return strrchr(s, c); + } + + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars). Also, in Samba + we only search for ascii characters in 'c' and that + in all mb character sets with a compound character + containing c, if 'c' is not a match at position + p, then p[-1] > 0x7f. JRA. */ + + { + size_t len = strlen(s); + const char *cp = s; + bool got_mb = false; + + if (len == 0) + return NULL; + cp += (len - 1); + do { + if (c == *cp) { + /* Could be a match. Part of a multibyte ? */ + if ((cp > s) && + (((unsigned char)cp[-1]) & 0x80)) { + /* Yep - go slow :-( */ + got_mb = true; + break; + } + /* No - we have a match ! */ + return discard_const_p(char , cp); + } + } while (cp-- != s); + if (!got_mb) + return NULL; + } + + ic = get_iconv_handle(); + + while (*s) { + size_t size; + codepoint_t c2 = next_codepoint_handle(ic, s, &size); + if (c2 == c) { + ret = discard_const_p(char, s); + } + s += size; + } + + return ret; +} + +/** + return True if any (multi-byte) character is lower case +*/ +_PUBLIC_ bool strhaslower_handle(struct smb_iconv_handle *ic, + const char *string) +{ + while (*string) { + size_t c_size; + codepoint_t s; + codepoint_t t; + + s = next_codepoint_handle(ic, string, &c_size); + string += c_size; + + t = toupper_m(s); + + if (s != t) { + return true; /* that means it has lower case chars */ + } + } + + return false; +} + +_PUBLIC_ bool strhaslower(const char *string) +{ + struct smb_iconv_handle *ic = get_iconv_handle(); + return strhaslower_handle(ic, string); +} + +/** + return True if any (multi-byte) character is upper case +*/ +_PUBLIC_ bool strhasupper_handle(struct smb_iconv_handle *ic, + const char *string) +{ + while (*string) { + size_t c_size; + codepoint_t s; + codepoint_t t; + + s = next_codepoint_handle(ic, string, &c_size); + string += c_size; + + t = tolower_m(s); + + if (s != t) { + return true; /* that means it has upper case chars */ + } + } + + return false; +} + +_PUBLIC_ bool strhasupper(const char *string) +{ + struct smb_iconv_handle *ic = get_iconv_handle(); + return strhasupper_handle(ic, string); +} + +/*********************************************************************** + strstr_m - We convert via ucs2 for now. +***********************************************************************/ + +char *strstr_m(const char *src, const char *findstr) +{ + TALLOC_CTX *mem_ctx = NULL; + smb_ucs2_t *p; + smb_ucs2_t *src_w, *find_w; + const char *s; + char *s2; + char *retp = NULL; + size_t converted_size, findstr_len = 0; + + /* for correctness */ + if (!findstr[0]) { + return discard_const_p(char, src); + } + + /* Samba does single character findstr calls a *lot*. */ + if (findstr[1] == '\0') + return strchr_m(src, *findstr); + + /* We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars) */ + + for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) { + if (*s == *findstr) { + if (!findstr_len) + findstr_len = strlen(findstr); + + if (strncmp(s, findstr, findstr_len) == 0) { + return discard_const_p(char, s); + } + } + } + + if (!*s) + return NULL; + +#if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */ + /* 'make check' fails unless we do this */ + + /* With compose characters we must restart from the beginning. JRA. */ + s = src; +#endif + + /* + * Use get_iconv_handle() just as a non-NULL talloc ctx. In + * case we leak memory, this should then be more obvious in + * the talloc report. + */ + mem_ctx = talloc_new(get_iconv_handle()); + if (mem_ctx == NULL) { + return NULL; + } + + if (!push_ucs2_talloc(mem_ctx, &src_w, src, &converted_size)) { + goto done; + } + + if (!push_ucs2_talloc(mem_ctx, &find_w, findstr, &converted_size)) { + goto done; + } + + p = strstr_w(src_w, find_w); + + if (!p) { + goto done; + } + + *p = 0; + if (!pull_ucs2_talloc(mem_ctx, &s2, src_w, &converted_size)) { + goto done; + } + retp = discard_const_p(char, (s+strlen(s2))); +done: + TALLOC_FREE(mem_ctx); + return retp; +} diff --git a/lib/util/charset/util_unistr.c b/lib/util/charset/util_unistr.c new file mode 100644 index 0000000..830b480 --- /dev/null +++ b/lib/util/charset/util_unistr.c @@ -0,0 +1,644 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Simo Sorce 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/locale.h" +#include "charset.h" +#include "lib/util/byteorder.h" +#include "lib/util/fault.h" + +/** + String replace. + NOTE: oldc and newc must be 7 bit characters +**/ +_PUBLIC_ void string_replace_m(char *s, char oldc, char newc) +{ + struct smb_iconv_handle *ic = get_iconv_handle(); + while (s && *s) { + size_t size; + codepoint_t c = next_codepoint_handle(ic, s, &size); + if (c == oldc) { + *s = newc; + } + s += size; + } +} + +/** + Convert a string to lower case, allocated with talloc +**/ +_PUBLIC_ char *strlower_talloc_handle(struct smb_iconv_handle *iconv_handle, + TALLOC_CTX *ctx, const char *src) +{ + size_t size=0; + char *dest; + + if(src == NULL) { + return NULL; + } + + /* this takes advantage of the fact that upper/lower can't + change the length of a character by more than 1 byte */ + dest = talloc_array(ctx, char, 2*(strlen(src))+1); + if (dest == NULL) { + return NULL; + } + + while (*src) { + size_t c_size; + codepoint_t c = next_codepoint_handle(iconv_handle, src, &c_size); + src += c_size; + + c = tolower_m(c); + + c_size = push_codepoint_handle(iconv_handle, dest+size, c); + if (c_size == -1) { + talloc_free(dest); + return NULL; + } + size += c_size; + } + + dest[size] = 0; + + /* trim it so talloc_append_string() works */ + dest = talloc_realloc(ctx, dest, char, size+1); + + talloc_set_name_const(dest, dest); + + return dest; +} + +_PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src) +{ + struct smb_iconv_handle *iconv_handle = get_iconv_handle(); + return strlower_talloc_handle(iconv_handle, ctx, src); +} + +/** + Convert a string to UPPER case, allocated with talloc + source length limited to n bytes, iconv handle supplied +**/ +_PUBLIC_ char *strupper_talloc_n_handle(struct smb_iconv_handle *iconv_handle, + TALLOC_CTX *ctx, const char *src, size_t n) +{ + size_t size=0; + char *dest; + + if (!src) { + return NULL; + } + + /* this takes advantage of the fact that upper/lower can't + change the length of a character by more than 1 byte */ + dest = talloc_array(ctx, char, 2*(n+1)); + if (dest == NULL) { + return NULL; + } + + while (n && *src) { + size_t c_size; + codepoint_t c = next_codepoint_handle_ext(iconv_handle, src, n, + CH_UNIX, &c_size); + src += c_size; + n -= c_size; + + c = toupper_m(c); + + c_size = push_codepoint_handle(iconv_handle, dest+size, c); + if (c_size == -1) { + talloc_free(dest); + return NULL; + } + size += c_size; + } + + dest[size] = 0; + + /* trim it so talloc_append_string() works */ + dest = talloc_realloc(ctx, dest, char, size+1); + + talloc_set_name_const(dest, dest); + + return dest; +} + +/** + Convert a string to UPPER case, allocated with talloc + source length limited to n bytes +**/ +_PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n) +{ + struct smb_iconv_handle *iconv_handle = get_iconv_handle(); + return strupper_talloc_n_handle(iconv_handle, ctx, src, n); +} +/** + Convert a string to UPPER case, allocated with talloc +**/ +_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src) +{ + return strupper_talloc_n(ctx, src, src?strlen(src):0); +} + +/** + talloc_strdup() a unix string to upper case. +**/ +_PUBLIC_ char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *src) +{ + return strupper_talloc(ctx, src); +} + +/** + Find the number of 'c' chars in a string +**/ +_PUBLIC_ size_t count_chars_m(const char *s, char c) +{ + struct smb_iconv_handle *ic = get_iconv_handle(); + size_t count = 0; + + while (*s) { + size_t size; + codepoint_t c2 = next_codepoint_handle(ic, s, &size); + if (c2 == c) count++; + s += size; + } + + return count; +} + +size_t ucs2_align(const void *base_ptr, const void *p, int flags) +{ + if (flags & (STR_NOALIGN|STR_ASCII)) { + return 0; + } + return PTR_DIFF(p, base_ptr) & 1; +} + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +**/ +size_t utf16_len(const void *buf) +{ + size_t len; + + for (len = 0; PULL_LE_U16(buf,len); len += 2) ; + + return len; +} + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination +**/ +size_t utf16_null_terminated_len(const void *buf) +{ + return utf16_len(buf) + 2; +} + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +limited by 'n' bytes +**/ +size_t utf16_len_n(const void *src, size_t n) +{ + size_t len; + + for (len = 0; (len+2 <= n) && PULL_LE_U16(src, len); len += 2) ; + + return len; +} + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination +limited by 'n' bytes +**/ +size_t utf16_null_terminated_len_n(const void *src, size_t n) +{ + size_t len; + + len = utf16_len_n(src, n); + + if (len+2 <= n) { + len += 2; + } + + return len; +} + +unsigned char *talloc_utf16_strlendup(TALLOC_CTX *mem_ctx, const char *str, size_t len) +{ + unsigned char *new_str = NULL; + + /* Check for overflow. */ + if (len > SIZE_MAX - 2) { + return NULL; + } + + /* + * Allocate the new string, including space for the + * UTF‐16 null terminator. + */ + new_str = talloc_size(mem_ctx, len + 2); + if (new_str == NULL) { + return NULL; + } + + memcpy(new_str, str, len); + + /* + * Ensure that the UTF‐16 string is + * null‐terminated. + */ + new_str[len] = '\0'; + new_str[len + 1] = '\0'; + + return new_str; +} + +unsigned char *talloc_utf16_strdup(TALLOC_CTX *mem_ctx, const char *str) +{ + if (str == NULL) { + return NULL; + } + return talloc_utf16_strlendup(mem_ctx, str, utf16_len(str)); +} + +unsigned char *talloc_utf16_strndup(TALLOC_CTX *mem_ctx, const char *str, size_t n) +{ + if (str == NULL) { + return NULL; + } + return talloc_utf16_strlendup(mem_ctx, str, utf16_len_n(str, n)); +} + +/** + * Determine the length and validity of a utf-8 string. + * + * @param input the string pointer + * @param maxlen maximum size of the string + * @param byte_len receives the length of the valid section + * @param char_len receives the number of unicode characters in the valid section + * @param utf16_len receives the number of bytes the string would need in UTF16 encoding. + * + * @return true if the input is valid up to maxlen, or a '\0' byte, otherwise false. + */ +bool utf8_check(const char *input, size_t maxlen, + size_t *byte_len, + size_t *char_len, + size_t *utf16_len) +{ + const uint8_t *s = (const uint8_t *)input; + size_t i; + size_t chars = 0; + size_t long_chars = 0; + uint32_t codepoint; + uint8_t a, b, c, d; + for (i = 0; i < maxlen; i++, chars++) { + if (s[i] == 0) { + break; + } + if (s[i] < 0x80) { + continue; + } + if ((s[i] & 0xe0) == 0xc0) { + /* 110xxxxx 10xxxxxx */ + a = s[i]; + if (maxlen - i < 2) { + goto error; + } + b = s[i + 1]; + if ((b & 0xc0) != 0x80) { + goto error; + } + codepoint = (a & 31) << 6 | (b & 63); + if (codepoint < 0x80) { + goto error; + } + i++; + continue; + } + if ((s[i] & 0xf0) == 0xe0) { + /* 1110xxxx 10xxxxxx 10xxxxxx */ + if (maxlen - i < 3) { + goto error; + } + a = s[i]; + b = s[i + 1]; + c = s[i + 2]; + if ((b & 0xc0) != 0x80 || (c & 0xc0) != 0x80) { + goto error; + } + codepoint = (c & 63) | (b & 63) << 6 | (a & 15) << 12; + + if (codepoint < 0x800) { + goto error; + } + if (codepoint >= 0xd800 && codepoint <= 0xdfff) { + /* + * This is an invalid codepoint, per + * RFC3629, as it encodes part of a + * UTF-16 surrogate pair for a + * character over U+10000, which ought + * to have been encoded as a four byte + * utf-8 sequence. + */ + goto error; + } + i += 2; + continue; + } + + if ((s[i] & 0xf8) == 0xf0) { + /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (maxlen - i < 4) { + goto error; + } + a = s[i]; + b = s[i + 1]; + c = s[i + 2]; + d = s[i + 3]; + + if ((b & 0xc0) != 0x80 || + (c & 0xc0) != 0x80 || + (d & 0xc0) != 0x80) { + goto error; + } + codepoint = (d & 63) | (c & 63) << 6 | (b & 63) << 12 | (a & 7) << 18; + + if (codepoint < 0x10000 || codepoint > 0x10ffff) { + goto error; + } + /* this one will need two UTF16 characters */ + long_chars++; + i += 3; + continue; + } + /* + * If it wasn't handled yet, it's wrong. + */ + goto error; + } + *byte_len = i; + *char_len = chars; + *utf16_len = chars + long_chars; + return true; + +error: + *byte_len = i; + *char_len = chars; + *utf16_len = chars + long_chars; + return false; +} + + +/** + * Copy a string from a char* unix src to a dos codepage string destination. + * + * @converted_size the number of bytes occupied by the string in the destination. + * @return bool true if success. + * + * @param flags can include + * <dl> + * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd> + * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd> + * </dl> + * + * @param dest_len the maximum length in bytes allowed in the + * destination. If @p dest_len is -1 then no maximum is used. + **/ +static bool push_ascii_string(void *dest, const char *src, size_t dest_len, int flags, size_t *converted_size) +{ + size_t src_len; + bool ret; + + if (flags & STR_UPPER) { + char *tmpbuf = strupper_talloc(NULL, src); + if (tmpbuf == NULL) { + return false; + } + ret = push_ascii_string(dest, tmpbuf, dest_len, flags & ~STR_UPPER, converted_size); + talloc_free(tmpbuf); + return ret; + } + + src_len = strlen(src); + + if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) + src_len++; + + return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, converted_size); +} + +/** + * Copy a string from a dos codepage source to a unix char* destination. + * + * The resulting string in "dest" is always null terminated. + * + * @param flags can have: + * <dl> + * <dt>STR_TERMINATE</dt> + * <dd>STR_TERMINATE means the string in @p src + * is null terminated, and src_len is ignored.</dd> + * </dl> + * + * @param src_len is the length of the source area in bytes. + * @returns the number of bytes occupied by the string in @p src. + **/ +static ssize_t pull_ascii_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + size_t size = 0; + + if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) { + if (src_len == (size_t)-1) { + src_len = strlen((const char *)src) + 1; + } else { + size_t len = strnlen((const char *)src, src_len); + if (len < src_len) + len++; + src_len = len; + } + } + + /* We're ignoring the return here.. */ + (void)convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, &size); + + if (dest_len) + dest[MIN(size, dest_len-1)] = 0; + + return src_len; +} + +/** + * Copy a string from a char* src to a unicode destination. + * + * @returns the number of bytes occupied by the string in the destination. + * + * @param flags can have: + * + * <dl> + * <dt>STR_TERMINATE <dd>means include the null termination. + * <dt>STR_UPPER <dd>means uppercase in the destination. + * <dt>STR_NOALIGN <dd>means don't do alignment. + * </dl> + * + * @param dest_len is the maximum length allowed in the + * destination. If dest_len is -1 then no maximum is used. + **/ +static ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags) +{ + size_t len=0; + size_t src_len = strlen(src); + size_t size = 0; + bool ret; + + if (flags & STR_UPPER) { + char *tmpbuf = strupper_talloc(NULL, src); + ssize_t retval; + if (tmpbuf == NULL) { + return -1; + } + retval = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER); + talloc_free(tmpbuf); + return retval; + } + + if (flags & STR_TERMINATE) + src_len++; + + if (ucs2_align(NULL, dest, flags)) { + *(char *)dest = 0; + dest = (void *)((char *)dest + 1); + if (dest_len) dest_len--; + len++; + } + + /* ucs2 is always a multiple of 2 bytes */ + dest_len &= ~1; + + ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len, &size); + if (ret == false) { + return 0; + } + + len += size; + + return (ssize_t)len; +} + + +/** + Copy a string from a ucs2 source to a unix char* destination. + Flags can have: + STR_TERMINATE means the string in src is null terminated. + STR_NOALIGN means don't try to align. + if STR_TERMINATE is set then src_len is ignored if it is -1. + src_len is the length of the source area in bytes + Return the number of bytes occupied by the string in src. + The resulting string in "dest" is always null terminated. +**/ + +static size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + size_t size = 0; + + if (ucs2_align(NULL, src, flags)) { + src = (const void *)((const char *)src + 1); + if (src_len > 0) + src_len--; + } + + if (flags & STR_TERMINATE) { + if (src_len == (size_t)-1) { + src_len = utf16_null_terminated_len(src); + } else { + src_len = utf16_null_terminated_len_n(src, src_len); + } + } + + /* ucs2 is always a multiple of 2 bytes */ + if (src_len != (size_t)-1) + src_len &= ~1; + + /* We're ignoring the return here.. */ + (void)convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len, &size); + if (dest_len) + dest[MIN(size, dest_len-1)] = 0; + + return src_len; +} + +/** + Copy a string from a char* src to a unicode or ascii + dos codepage destination choosing unicode or ascii based on the + flags in the SMB buffer starting at base_ptr. + Return the number of bytes occupied by the string in the destination. + flags can have: + STR_TERMINATE means include the null termination. + STR_UPPER means uppercase in the destination. + STR_ASCII use ascii even with unicode packet. + STR_NOALIGN means don't do alignment. + dest_len is the maximum length allowed in the destination. If dest_len + is -1 then no maximum is used. +**/ + +_PUBLIC_ ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags) +{ + if (flags & STR_ASCII) { + size_t size = 0; + if (push_ascii_string(dest, src, dest_len, flags, &size)) { + return (ssize_t)size; + } else { + return (ssize_t)-1; + } + } else if (flags & STR_UNICODE) { + return push_ucs2(dest, src, dest_len, flags); + } else { + smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set"); + return -1; + } +} + + +/** + Copy a string from a unicode or ascii source (depending on + the packet flags) to a char* destination. + Flags can have: + STR_TERMINATE means the string in src is null terminated. + STR_UNICODE means to force as unicode. + STR_ASCII use ascii even with unicode packet. + STR_NOALIGN means don't do alignment. + if STR_TERMINATE is set then src_len is ignored is it is -1 + src_len is the length of the source area in bytes. + Return the number of bytes occupied by the string in src. + The resulting string in "dest" is always null terminated. +**/ + +_PUBLIC_ ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + if (flags & STR_ASCII) { + return pull_ascii_string(dest, src, dest_len, src_len, flags); + } else if (flags & STR_UNICODE) { + return pull_ucs2(dest, src, dest_len, src_len, flags); + } else { + smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set"); + return -1; + } +} diff --git a/lib/util/charset/util_unistr_w.c b/lib/util/charset/util_unistr_w.c new file mode 100644 index 0000000..88d5531 --- /dev/null +++ b/lib/util/charset/util_unistr_w.c @@ -0,0 +1,255 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Simo Sorce 2001 + Copyright (C) Jeremy Allison 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "charset.h" +#include "lib/util/byteorder.h" +#include "lib/util/debug.h" +#include "lib/util/fault.h" + +/* Copy into a smb_ucs2_t from a possibly unaligned buffer. Return the copied smb_ucs2_t */ +#define COPY_UCS2_CHAR(dest,src) (((unsigned char *)(dest))[0] = ((const unsigned char *)(src))[0],\ + ((unsigned char *)(dest))[1] = ((const unsigned char *)(src))[1], (dest)) + + +/* return an ascii version of a ucs2 character */ +#define UCS2_TO_CHAR(c) (((c) >> UCS2_SHIFT) & 0xff) + +static int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len); + +/******************************************************************* + Count the number of two-byte pairs in a UTF16 string. +********************************************************************/ + +size_t strlen_w(const smb_ucs2_t *src) +{ + size_t len; + smb_ucs2_t c; + + for(len = 0; *(COPY_UCS2_CHAR(&c,src)); src++, len++) { + ; + } + + return len; +} + +/******************************************************************* + Count up to max number of characters in a smb_ucs2_t string. +********************************************************************/ + +size_t strnlen_w(const smb_ucs2_t *src, size_t max) +{ + size_t len; + smb_ucs2_t c; + + for(len = 0; (len < max) && *(COPY_UCS2_CHAR(&c,src)); src++, len++) { + ; + } + + return len; +} + +/******************************************************************* + Wide strchr(). +********************************************************************/ + +smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c) +{ + smb_ucs2_t cp; + while (*(COPY_UCS2_CHAR(&cp,s))) { + if (c == cp) { + return discard_const_p(smb_ucs2_t, s); + } + s++; + } + if (c == cp) { + return discard_const_p(smb_ucs2_t, s); + } + + return NULL; +} + +smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c) +{ + return strchr_w(s, UCS2_CHAR(c)); +} + +/******************************************************************* + Wide strrchr(). +********************************************************************/ + +smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) +{ + smb_ucs2_t cp; + const smb_ucs2_t *p = s; + int len = strlen_w(s); + + if (len == 0) { + return NULL; + } + p += (len - 1); + do { + if (c == *(COPY_UCS2_CHAR(&cp,p))) { + return discard_const_p(smb_ucs2_t, p); + } + } while (p-- != s); + return NULL; +} + +/******************************************************************* + Wide version of strrchr that returns after doing strrchr 'n' times. +********************************************************************/ + +smb_ucs2_t *strnrchr_w(const smb_ucs2_t *s, smb_ucs2_t c, unsigned int n) +{ + smb_ucs2_t cp; + const smb_ucs2_t *p = s; + int len = strlen_w(s); + + if (len == 0 || !n) { + return NULL; + } + p += (len - 1); + do { + if (c == *(COPY_UCS2_CHAR(&cp,p))) { + n--; + } + + if (!n) { + return discard_const_p(smb_ucs2_t, p); + } + } while (p-- != s); + return NULL; +} + +/******************************************************************* + Wide strstr(). +********************************************************************/ + +smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins) +{ + const smb_ucs2_t *r; + size_t inslen; + + if (!s || !*s || !ins || !*ins) { + return NULL; + } + + inslen = strlen_w(ins); + r = s; + + while ((r = strchr_w(r, *ins))) { + if (strncmp_w(r, ins, inslen) == 0) { + return discard_const_p(smb_ucs2_t, r); + } + r++; + } + + return NULL; +} + +/******************************************************************* + Convert a string to lower case. + return True if any char is converted + + This is unsafe for any string involving a UTF16 character +********************************************************************/ + +bool strlower_w(smb_ucs2_t *s) +{ + smb_ucs2_t cp; + bool ret = false; + + while (*(COPY_UCS2_CHAR(&cp,s))) { + smb_ucs2_t v = tolower_m(cp); + if (v != cp) { + (void)COPY_UCS2_CHAR(s,&v); + ret = true; + } + s++; + } + return ret; +} + +/******************************************************************* + Convert a string to upper case. + return True if any char is converted + + This is unsafe for any string involving a UTF16 character +********************************************************************/ + +bool strupper_w(smb_ucs2_t *s) +{ + smb_ucs2_t cp; + bool ret = false; + while (*(COPY_UCS2_CHAR(&cp,s))) { + smb_ucs2_t v = toupper_m(cp); + if (v != cp) { + (void)COPY_UCS2_CHAR(s,&v); + ret = true; + } + s++; + } + return ret; +} + +static int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len) +{ + smb_ucs2_t cpa, cpb; + size_t n = 0; + + while ((n < len) && (*(COPY_UCS2_CHAR(&cpb,b))) && (*(COPY_UCS2_CHAR(&cpa,a)) == cpb)) { + a++; + b++; + n++; + } + return (len - n)?(*(COPY_UCS2_CHAR(&cpa,a)) - *(COPY_UCS2_CHAR(&cpb,b))):0; +} + +/* + The *_wa() functions take a combination of 7 bit ascii + and wide characters They are used so that you can use string + functions combining C string constants with ucs2 strings + + The char* arguments must NOT be multibyte - to be completely sure + of this only pass string constants */ + +int strcmp_wa(const smb_ucs2_t *a, const char *b) +{ + smb_ucs2_t cp = 0; + + while (*b && *(COPY_UCS2_CHAR(&cp,a)) == UCS2_CHAR(*b)) { + a++; + b++; + } + return (*(COPY_UCS2_CHAR(&cp,a)) - UCS2_CHAR(*b)); +} + +smb_ucs2_t toupper_w(smb_ucs2_t v) +{ + smb_ucs2_t ret; + /* LE to native. */ + codepoint_t cp = SVAL(&v,0); + cp = toupper_m(cp); + /* native to LE. */ + SSVAL(&ret,0,cp); + return ret; +} diff --git a/lib/util/charset/weird.c b/lib/util/charset/weird.c new file mode 100644 index 0000000..9752e01 --- /dev/null +++ b/lib/util/charset/weird.c @@ -0,0 +1,142 @@ +/* + Unix SMB/CIFS implementation. + Samba module with developer tools + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "charset_proto.h" + +#ifdef DEVELOPER + +static struct { + char from; + const char *to; + int len; +} weird_table[] = { + { + .from = 'q', + .to = "^q^", + .len = 3, + }, + { + .from = 'Q', + .to = "^Q^", + .len = 3, + }, + { + .len = 0, + } +}; + +size_t weird_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + int i; + int done = 0; + for (i=0;weird_table[i].from;i++) { + if (strncmp((*inbuf), + weird_table[i].to, + weird_table[i].len) == 0) { + if (*inbytesleft < weird_table[i].len) { + abort(); + } + + (*outbuf)[0] = weird_table[i].from; + (*outbuf)[1] = 0; + (*inbytesleft) -= weird_table[i].len; + (*outbytesleft) -= 2; + (*inbuf) += weird_table[i].len; + (*outbuf) += 2; + done = 1; + break; + } + } + if (done) continue; + (*outbuf)[0] = (*inbuf)[0]; + (*outbuf)[1] = 0; + (*inbytesleft) -= 1; + (*outbytesleft) -= 2; + (*inbuf) += 1; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +size_t weird_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int ir_count=0; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + int i; + int done=0; + for (i=0;weird_table[i].from;i++) { + if ((*inbuf)[0] == weird_table[i].from && + (*inbuf)[1] == 0) { + if (*outbytesleft < weird_table[i].len) { + abort(); + } + memcpy(*outbuf, + weird_table[i].to, + weird_table[i].len); + (*inbytesleft) -= 2; + (*outbytesleft) -= weird_table[i].len; + (*inbuf) += 2; + (*outbuf) += weird_table[i].len; + done = 1; + break; + } + } + if (done) continue; + + (*outbuf)[0] = (*inbuf)[0]; + if ((*inbuf)[1]) ir_count++; + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return ir_count; +} + +#else +void charset_weird_dummy(void); +void charset_weird_dummy(void) +{ + return; +} + +#endif diff --git a/lib/util/charset/wscript_build b/lib/util/charset/wscript_build new file mode 100644 index 0000000..c69a171 --- /dev/null +++ b/lib/util/charset/wscript_build @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +bld.SAMBA_SUBSYSTEM('ICONV_WRAPPER', + source=''' + iconv.c + weird.c + charset_macosxfs.c + ''', + public_deps='iconv replace talloc ' + bld.env['icu-libs']) + +bld.SAMBA_SUBSYSTEM('charset', + public_headers='charset.h', + source=''' + codepoints.c + convert_string.c + util_str.c + util_unistr_w.c + pull_push.c + util_unistr.c + ''', + deps='DYNCONFIG ICONV_WRAPPER smb-panic samba-debug', + public_deps='talloc') diff --git a/lib/util/charset/wscript_configure b/lib/util/charset/wscript_configure new file mode 100644 index 0000000..9c27fc6 --- /dev/null +++ b/lib/util/charset/wscript_configure @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +# rather strangely, we need to look for libiconv before checking libc +# as the external libiconv can use a macro to override iconv_open to libiconv_open +# and then we may find the wrong iconv.h later due to other packages looking +# in /usr/local +# We check for the lib iconv when building a shared lib has some compiler/linker +# managed to link when specifying -liconv a executable even if there is no +# libiconv.so or libiconv.a + +conf.CHECK_LIB(libs="iconv", shlib=True) + +#HP-UX can use libiconv as an add-on package, which has #define iconv_open libiconv_open +if (conf.CHECK_FUNCS_IN('iconv_open', 'iconv', checklibc=False, headers='iconv.h') or + conf.CHECK_FUNCS_IN('libiconv_open', 'iconv', checklibc=False, headers='iconv.h') or + conf.CHECK_FUNCS('iconv_open', headers='iconv.h')): + + conf.DEFINE('HAVE_NATIVE_ICONV', 1) + +conf.CHECK_CODE(''' + uint8_t inbuf[2] = { 0x30, 0xdf }; + uint8_t outbuf[4] = { 0 }; + char *ptr_in = (char *)inbuf; + char *ptr_out = (char *)outbuf; + size_t size_in = sizeof(inbuf); + size_t size_out = sizeof(outbuf); + size_t ret; + iconv_t cd; + cd = iconv_open("UTF-8", "UTF-16LE"); + if (cd == 0 || cd == (iconv_t)-1) return -1; + ret = iconv(cd, &ptr_in, &size_in, &ptr_out, &size_out); + if (ret != (size_t)-1 || errno != EILSEQ) return -1; + ''', + define='HAVE_ICONV_ERRNO_ILLEGAL_MULTIBYTE', + execute=True, + msg='Checking errno of iconv for illegal multibyte sequence', + lib='iconv', + headers='errno.h iconv.h') + +if conf.CHECK_CFG(package='icu-i18n', + args='--cflags --libs', + msg='Checking for icu-i18n', + uselib_store='ICU_I18N'): + for lib in conf.env['LIB_ICU_I18N']: + conf.CHECK_LIB(lib, shlib=True, mandatory=True) + conf.env['icu-libs'] = ' '.join(conf.env['LIB_ICU_I18N']) + if not conf.CHECK_HEADERS('unicode/ustring.h'): + conf.fatal('Found libicu, but unicode/ustring.h is missing') + conf.DEFINE('HAVE_UTF8_NORMALISATION', 1) +else: + conf.env['icu-libs'] = '' diff --git a/lib/util/charset_compat.h b/lib/util/charset_compat.h new file mode 100644 index 0000000..cb3b625 --- /dev/null +++ b/lib/util/charset_compat.h @@ -0,0 +1,9 @@ +#ifndef _SAMBA_CHARSET_COMPAT_H_ +#define _SAMBA_CHARSET_COMPAT_H_ + +#include <string.h> + +#define strchr_m(h, n) strchr(h, n) +#define strstr_m(h, n) strstr(h, n) + +#endif /* _SAMBA_CHARSET_COMPAT_H_ */ diff --git a/lib/util/close_low_fd.c b/lib/util/close_low_fd.c new file mode 100644 index 0000000..84a6906 --- /dev/null +++ b/lib/util/close_low_fd.c @@ -0,0 +1,75 @@ +/* + * Unix SMB/CIFS implementation. + * Samba utility functions + * Copyright (C) Volker Lendecke 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/filesys.h" +#include "close_low_fd.h" + +#ifdef HAVE_VALGRIND_VALGRIND_H +#include <valgrind/valgrind.h> +#elif defined(HAVE_VALGRIND_H) +#include <valgrind.h> +#else +#define RUNNING_ON_VALGRIND 0 +#endif + +_PUBLIC_ int close_low_fd(int fd) +{ + int ret, dev_null; + + if (RUNNING_ON_VALGRIND) { + return 0; + } + + dev_null = open("/dev/null", O_RDWR, 0); + + if ((dev_null == -1) && (errno == ENFILE)) { + /* + * Try to free up an fd + */ + ret = close(fd); + if (ret != 0) { + return errno; + } + } + + dev_null = open("/dev/null", O_RDWR, 0); + if (dev_null == -1) { + dev_null = open("/dev/null", O_WRONLY, 0); + } + if (dev_null == -1) { + return errno; + } + + if (dev_null == fd) { + /* + * This can happen in the ENFILE case above + */ + return 0; + } + + ret = dup2(dev_null, fd); + if (ret == -1) { + int err = errno; + close(dev_null); + return err; + } + close(dev_null); + return 0; +} diff --git a/lib/util/close_low_fd.h b/lib/util/close_low_fd.h new file mode 100644 index 0000000..954d1d2 --- /dev/null +++ b/lib/util/close_low_fd.h @@ -0,0 +1,28 @@ +/* + * Unix SMB/CIFS implementation. + * Samba utility functions + * Copyright (C) Volker Lendecke 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _CLOSE_LOW_FD_H +#define _CLOSE_LOW_FD_H + +/* + * Redirect "fd" to /dev/null + */ +int close_low_fd(int fd); + +#endif diff --git a/lib/util/data_blob.c b/lib/util/data_blob.c new file mode 100644 index 0000000..69a340c --- /dev/null +++ b/lib/util/data_blob.c @@ -0,0 +1,298 @@ +/* + Unix SMB/CIFS implementation. + Easy management of byte-length data + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Andrew Bartlett 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "attr.h" +#include "data_blob.h" +#include "lib/util/samba_util.h" + +const DATA_BLOB data_blob_null = { NULL, 0 }; + +/** + * @file + * @brief Manipulation of arbitrary data blobs + **/ + +/** + construct a data blob, must be freed with data_blob_free() + you can pass NULL for p and get a blank data blob +**/ +_PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name) +{ + return data_blob_talloc_named(NULL, p, length, name); +} + +/** + construct a data blob, using supplied TALLOC_CTX +**/ +_PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name) +{ + DATA_BLOB ret; + + if (p == NULL && length == 0) { + ZERO_STRUCT(ret); + return ret; + } + + if (p) { + ret.data = (uint8_t *)talloc_memdup(mem_ctx, p, length); + } else { + ret.data = talloc_array(mem_ctx, uint8_t, length); + } + if (ret.data == NULL) { + ret.length = 0; + return ret; + } + talloc_set_name_const(ret.data, name); + ret.length = length; + return ret; +} + +/** + construct a zero data blob, using supplied TALLOC_CTX. + use this sparingly as it initialises data - better to initialise + yourself if you want specific data in the blob +**/ +_PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length) +{ + DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length); + data_blob_clear(&blob); + return blob; +} + +/** +free a data blob +**/ +_PUBLIC_ void data_blob_free(DATA_BLOB *d) +{ + if (d) { + TALLOC_FREE(d->data); + d->length = 0; + } +} + +/** +clear a DATA_BLOB's contents +**/ +_PUBLIC_ void data_blob_clear(DATA_BLOB *d) +{ + if (d->data) { + memset_s(d->data, d->length, 0, d->length); + } +} + +/** +free a data blob and clear its contents +**/ +_PUBLIC_ void data_blob_clear_free(DATA_BLOB *d) +{ + data_blob_clear(d); + data_blob_free(d); +} + + +/** +check if two data blobs are equal +**/ +_PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2) +{ + int ret; + if (d1->data == NULL && d2->data != NULL) { + return -1; + } + if (d1->data != NULL && d2->data == NULL) { + return 1; + } + if (d1->data == d2->data) { + return d1->length - d2->length; + } + ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length)); + if (ret == 0) { + /* Note this ordering is used in conditional aces */ + return d1->length - d2->length; + } + return ret; +} + +/** +check if two data blobs are equal, where the time taken should not depend on the +contents of either blob. +**/ +_PUBLIC_ bool data_blob_equal_const_time(const DATA_BLOB *d1, const DATA_BLOB *d2) +{ + bool ret; + if (d1->data == NULL && d2->data != NULL) { + return false; + } + if (d1->data != NULL && d2->data == NULL) { + return false; + } + if (d1->length != d2->length) { + return false; + } + if (d1->data == d2->data) { + return true; + } + ret = mem_equal_const_time(d1->data, d2->data, d1->length); + return ret; +} + +/** +print the data_blob as hex string +**/ +_PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob) +{ + size_t i; + char *hex_string; + + hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1); + if (!hex_string) { + return NULL; + } + + /* this must be lowercase or w2k8 cannot join a samba domain, + as this routine is used to encode extended DNs and windows + only accepts lowercase hexadecimal numbers */ + for (i = 0; i < blob->length; i++) + slprintf(&hex_string[i*2], 3, "%02x", blob->data[i]); + + hex_string[(blob->length*2)] = '\0'; + return hex_string; +} + +_PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob) +{ + size_t i; + char *hex_string; + + hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1); + if (!hex_string) { + return NULL; + } + + for (i = 0; i < blob->length; i++) + slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]); + + hex_string[(blob->length*2)] = '\0'; + return hex_string; +} + +/** + useful for constructing data blobs in test suites, while + avoiding const warnings +**/ +_PUBLIC_ DATA_BLOB data_blob_string_const(const char *str) +{ + DATA_BLOB blob; + blob.data = discard_const_p(uint8_t, str); + blob.length = str ? strlen(str) : 0; + return blob; +} + +/** + useful for constructing data blobs in test suites, while + avoiding const warnings +**/ +_PUBLIC_ DATA_BLOB data_blob_string_const_null(const char *str) +{ + DATA_BLOB blob; + blob.data = discard_const_p(uint8_t, str); + blob.length = str ? strlen(str)+1 : 0; + return blob; +} + +/** + * Create a new data blob from const data + */ + +_PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length) +{ + DATA_BLOB blob; + blob.data = discard_const_p(uint8_t, p); + blob.length = length; + return blob; +} + + +/** + realloc a data_blob +**/ +_PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length) +{ + uint8_t *tmp = talloc_realloc(mem_ctx, blob->data, uint8_t, length); + if (tmp == NULL) { + return false; + } + blob->data = tmp; + blob->length = length; + return true; +} + + +/** + append some data to a data blob +**/ +_PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, + const void *p, size_t length) +{ + size_t old_len = blob->length; + size_t new_len = old_len + length; + + if (length == 0) { + return true; + } + + if (new_len < length || new_len < old_len) { + return false; + } + + if ((const uint8_t *)p + length < (const uint8_t *)p) { + return false; + } + + if (!data_blob_realloc(mem_ctx, blob, new_len)) { + return false; + } + + memcpy(blob->data + old_len, p, length); + return true; +} + +/** + pad the length of a data blob to a multiple of + 'pad'. 'pad' must be a power of two. +**/ +_PUBLIC_ bool data_blob_pad(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, + size_t pad) +{ + size_t old_len = blob->length; + size_t new_len = (old_len + pad - 1) & ~(pad - 1); + + if (new_len < old_len) { + return false; + } + + if (!data_blob_realloc(mem_ctx, blob, new_len)) { + return false; + } + + memset(blob->data + old_len, 0, new_len - old_len); + return true; +} diff --git a/lib/util/data_blob.h b/lib/util/data_blob.h new file mode 100644 index 0000000..6577630 --- /dev/null +++ b/lib/util/data_blob.h @@ -0,0 +1,144 @@ +/* + Unix SMB/CIFS implementation. + DATA BLOB + + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Andrew Bartlett 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* This is a public header file that is installed as part of Samba. + * If you remove any functions or change their signature, update + * the so version number. */ + +#ifndef _SAMBA_DATABLOB_H_ +#define _SAMBA_DATABLOB_H_ + +#ifndef _PUBLIC_ +#define _PUBLIC_ +#endif + +#include <talloc.h> +#include <stdbool.h> +#include <stdint.h> + +/* used to hold an arbitrary blob of data */ +typedef struct datablob { + uint8_t *data; + size_t length; +} DATA_BLOB; + +/* by making struct ldb_val and DATA_BLOB the same, we can simplify + a fair bit of code */ +#define ldb_val datablob + +#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: " __location__) +#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: " __location__) +#define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob).data, (blob).length, "DATA_BLOB: " __location__) + +/** + construct a data blob, must be freed with data_blob_free() + you can pass NULL for p and get a blank data blob +**/ +_PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name); + +/** + construct a data blob, using supplied TALLOC_CTX +**/ +_PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name); + +/** + construct a zero data blob, using supplied TALLOC_CTX. + use this sparingly as it initialises data - better to initialise + yourself if you want specific data in the blob +**/ +_PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length); + +/** +free a data blob +**/ +_PUBLIC_ void data_blob_free(DATA_BLOB *d); + +/** +clear a DATA_BLOB's contents +**/ +_PUBLIC_ void data_blob_clear(DATA_BLOB *d); + +/** +free a data blob and clear its contents +**/ +_PUBLIC_ void data_blob_clear_free(DATA_BLOB *d); + +/** +check if two data blobs are equal +**/ +_PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2); + +/** +check if two data blobs are equal, where the time taken should not depend on the +contents of either blob. +**/ +_PUBLIC_ bool data_blob_equal_const_time(const DATA_BLOB *d1, const DATA_BLOB *d2); + +/** +print the data_blob as hex string +**/ +_PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob); + +/** +print the data_blob as hex string +**/ +_PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob); + +/** + useful for constructing data blobs in test suites, while + avoiding const warnings +**/ +_PUBLIC_ DATA_BLOB data_blob_string_const(const char *str); + +/** + useful for constructing data blobs in test suites, while + avoiding const warnings + + includes the terminating null character (as opposed to data_blob_string_const) +**/ +_PUBLIC_ DATA_BLOB data_blob_string_const_null(const char *str); + +/** + * Create a new data blob from const data + */ +_PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length); + +/** + realloc a data_blob +**/ +_PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length); + +/** + append some data to a data blob +**/ +_PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, + const void *p, size_t length); + +/** + pad the length of a data blob to a multiple of + 'pad'. 'pad' must be a power of two. +**/ +_PUBLIC_ bool data_blob_pad(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, + size_t pad); + +extern const DATA_BLOB data_blob_null; + +#endif /* _SAMBA_DATABLOB_H_ */ diff --git a/lib/util/debug-classes/debug-classname-table.c b/lib/util/debug-classes/debug-classname-table.c new file mode 100644 index 0000000..9062078 --- /dev/null +++ b/lib/util/debug-classes/debug-classname-table.c @@ -0,0 +1,62 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Elrond 2002 + Copyright (C) Simo Sorce 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + + +static const char *default_classname_table[] = { + [DBGC_ALL] = "all", + [DBGC_TDB] = "tdb", + [DBGC_PRINTDRIVERS] = "printdrivers", + [DBGC_LANMAN] = "lanman", + [DBGC_SMB] = "smb", + [DBGC_RPC_PARSE] = "rpc_parse", + [DBGC_RPC_SRV] = "rpc_srv", + [DBGC_RPC_CLI] = "rpc_cli", + [DBGC_PASSDB] = "passdb", + [DBGC_SAM] = "sam", + [DBGC_AUTH] = "auth", + [DBGC_WINBIND] = "winbind", + [DBGC_VFS] = "vfs", + [DBGC_IDMAP] = "idmap", + [DBGC_QUOTA] = "quota", + [DBGC_ACLS] = "acls", + [DBGC_LOCKING] = "locking", + [DBGC_MSDFS] = "msdfs", + [DBGC_DMAPI] = "dmapi", + [DBGC_REGISTRY] = "registry", + [DBGC_SCAVENGER] = "scavenger", + [DBGC_DNS] = "dns", + [DBGC_LDB] = "ldb", + [DBGC_TEVENT] = "tevent", + [DBGC_AUTH_AUDIT] = "auth_audit", + [DBGC_AUTH_AUDIT_JSON] = "auth_json_audit", + [DBGC_KERBEROS] = "kerberos", + [DBGC_DRS_REPL] = "drs_repl", + [DBGC_SMB2] = "smb2", + [DBGC_SMB2_CREDITS] = "smb2_credits", + [DBGC_DSDB_AUDIT] = "dsdb_audit", + [DBGC_DSDB_AUDIT_JSON] = "dsdb_json_audit", + [DBGC_DSDB_PWD_AUDIT] = "dsdb_password_audit", + [DBGC_DSDB_PWD_AUDIT_JSON] = "dsdb_password_json_audit", + [DBGC_DSDB_TXN_AUDIT] = "dsdb_transaction_audit", + [DBGC_DSDB_TXN_AUDIT_JSON] = "dsdb_transaction_json_audit", + [DBGC_DSDB_GROUP_AUDIT] = "dsdb_group_audit", + [DBGC_DSDB_GROUP_AUDIT_JSON] = "dsdb_group_json_audit", +}; diff --git a/lib/util/debug.c b/lib/util/debug.c new file mode 100644 index 0000000..86f13f1 --- /dev/null +++ b/lib/util/debug.c @@ -0,0 +1,1978 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Elrond 2002 + Copyright (C) Simo Sorce 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include <talloc.h> +#include "system/filesys.h" +#include "system/syslog.h" +#include "system/locale.h" +#include "system/network.h" +#include "system/time.h" +#include "time_basic.h" +#include "close_low_fd.h" +#include "memory.h" +#include "util_strlist.h" /* LIST_SEP */ +#include "blocking.h" +#include "debug.h" +#include <assert.h> + +/* define what facility to use for syslog */ +#ifndef SYSLOG_FACILITY +#define SYSLOG_FACILITY LOG_DAEMON +#endif + +/* -------------------------------------------------------------------------- ** + * Defines... + */ + +/* + * format_bufr[FORMAT_BUFR_SIZE - 1] should always be reserved + * for a terminating null byte. + */ +#define FORMAT_BUFR_SIZE 4096 + +/* -------------------------------------------------------------------------- ** + * This module implements Samba's debugging utility. + * + * The syntax of a debugging log file is represented as: + * + * <debugfile> :== { <debugmsg> } + * + * <debugmsg> :== <debughdr> '\n' <debugtext> + * + * <debughdr> :== '[' TIME ',' LEVEL ']' [ [FILENAME ':'] [FUNCTION '()'] ] + * + * <debugtext> :== { <debugline> } + * + * <debugline> :== TEXT '\n' + * + * TEXT is a string of characters excluding the newline character. + * LEVEL is the DEBUG level of the message (an integer in the range 0..10). + * TIME is a timestamp. + * FILENAME is the name of the file from which the debug message was generated. + * FUNCTION is the function from which the debug message was generated. + * + * Basically, what that all means is: + * + * - A debugging log file is made up of debug messages. + * + * - Each debug message is made up of a header and text. The header is + * separated from the text by a newline. + * + * - The header begins with the timestamp and debug level of the message + * enclosed in brackets. The filename and function from which the + * message was generated may follow. The filename is terminated by a + * colon, and the function name is terminated by parenthesis. + * + * - The message text is made up of zero or more lines, each terminated by + * a newline. + */ + +/* state variables for the debug system */ +static struct { + bool initialized; + enum debug_logtype logtype; /* The type of logging we are doing: eg stdout, file, stderr */ + char prog_name[255]; + char hostname[HOST_NAME_MAX+1]; + bool reopening_logs; + bool schedule_reopen_logs; + int forced_log_priority; + + struct debug_settings settings; + debug_callback_fn callback; + void *callback_private; + char header_str[300]; + size_t hs_len; +} state = { + .settings = { + .timestamp_logs = true + }, +}; + +struct debug_class { + /* + * The debug loglevel of the class. + */ + int loglevel; + + /* + * An optional class specific logfile, may be NULL in which case the + * "global" logfile is used and fd is -1. + */ + char *logfile; + int fd; + /* inode number of the logfile to detect logfile rotation */ + ino_t ino; +}; + +/* + * default_classname_table[] is read in from debug-classname-table.c + * so that test_logging.c can use it too. + */ +#include "lib/util/debug-classes/debug-classname-table.c" + +/* + * This is to allow reading of dbgc_config before the debug + * system has been initialized. + */ +static struct debug_class debug_class_list_initial[ARRAY_SIZE(default_classname_table)] = { + [DBGC_ALL] = { .fd = 2 }, +}; + +static size_t debug_num_classes = 0; +static struct debug_class *dbgc_config = debug_class_list_initial; + +static int current_msg_level = 0; +static int current_msg_class = 0; + +/* + * DBG_DEV(): when and how to user it. + * + * As a developer, you sometimes want verbose logging between point A and + * point B, where the relationship between these points is not easily defined + * in terms of the call stack. + * + * For example, you might be interested in what is going on in functions in + * lib/util/util_str.c in an ldap worker process after a particular query. If + * you use gdb, something will time out and you won't get the full + * conversation. If you add fprintf() or DBG_ERR()s to util_str.c, you'll get + * a massive flood, and there's a chance one will accidentally slip into a + * release and the whole world will flood. DBG_DEV is a solution. + * + * On start-up, DBG_DEV() is switched OFF. Nothing is printed. + * + * 1. Add `DBG_DEV("formatted msg %d, etc\n", i);` where needed. + * + * 2. At each point you want to start debugging, add `debug_developer_enable()`. + * + * 3. At each point you want debugging to stop, add `debug_developer_disable()`. + * + * In DEVELOPER builds, the message will be printed at level 0, as with + * DBG_ERR(). In production builds, the macro resolves to nothing. + * + * The messages are printed with a "<function_name>:DEV:<pid>:" prefix. + */ + +static bool debug_developer_is_enabled = false; + +bool debug_developer_enabled(void) +{ + return debug_developer_is_enabled; +} + +/* + * debug_developer_disable() will turn DBG_DEV() on in the current + * process and children. + */ +void debug_developer_enable(void) +{ + debug_developer_is_enabled = true; +} + +/* + * debug_developer_disable() will make DBG_DEV() do nothing in the current + * process (and children). + */ +void debug_developer_disable(void) +{ + debug_developer_is_enabled = false; +} + +/* + * Within debug.c, DBG_DEV() always writes to stderr, because some functions + * here will attempt infinite recursion with normal DEBUG macros. + */ +#ifdef DEVELOPER +#undef DBG_DEV +#define DBG_DEV(fmt, ...) \ + (void)((debug_developer_enabled()) \ + && (fprintf(stderr, "%s:DEV:%d: " fmt "%s", \ + __func__, getpid(), ##__VA_ARGS__, "")) ) +#endif + + +#if defined(WITH_SYSLOG) || defined(HAVE_LIBSYSTEMD_JOURNAL) || defined(HAVE_LIBSYSTEMD) +static int debug_level_to_priority(int level) +{ + /* + * map debug levels to syslog() priorities + */ + static const int priority_map[] = { + LOG_ERR, /* 0 */ + LOG_WARNING, /* 1 */ + LOG_NOTICE, /* 2 */ + LOG_NOTICE, /* 3 */ + LOG_NOTICE, /* 4 */ + LOG_NOTICE, /* 5 */ + LOG_INFO, /* 6 */ + LOG_INFO, /* 7 */ + LOG_INFO, /* 8 */ + LOG_INFO, /* 9 */ + }; + int priority; + + if (state.forced_log_priority != -1) { + level = state.forced_log_priority; + } + + if (level < 0 || (size_t)level >= ARRAY_SIZE(priority_map)) + priority = LOG_DEBUG; + else + priority = priority_map[level]; + + return priority; +} +#endif + +/* -------------------------------------------------------------------------- ** + * Debug backends. When logging to DEBUG_FILE, send the log entries to + * all active backends. + */ + +static void debug_file_log(int msg_level, const char *msg, size_t msg_len) +{ + struct iovec iov[] = { + { + .iov_base = discard_const(state.header_str), + .iov_len = state.hs_len, + }, + { + .iov_base = discard_const(msg), + .iov_len = msg_len, + }, + }; + ssize_t ret; + int fd; + + check_log_size(); + + if (dbgc_config[current_msg_class].fd != -1) { + fd = dbgc_config[current_msg_class].fd; + } else { + fd = dbgc_config[DBGC_ALL].fd; + } + + do { + ret = writev(fd, iov, ARRAY_SIZE(iov)); + } while (ret == -1 && errno == EINTR); +} + +#ifdef WITH_SYSLOG +static void debug_syslog_reload(bool enabled, bool previously_enabled, + const char *prog_name, char *option) +{ + if (enabled && !previously_enabled) { + const char *ident = NULL; + if ((prog_name != NULL) && (prog_name[0] != '\0')) { + ident = prog_name; + } +#ifdef LOG_DAEMON + openlog(ident, LOG_PID, SYSLOG_FACILITY); +#else + /* for old systems that have no facility codes. */ + openlog(ident, LOG_PID); +#endif + return; + } + + if (!enabled && previously_enabled) { + closelog(); + } +} + +static void debug_syslog_log(int msg_level, const char *msg, size_t msg_len) +{ + int priority; + + priority = debug_level_to_priority(msg_level); + + /* + * Specify the facility to interoperate with other syslog + * callers (vfs_full_audit for example). + */ + priority |= SYSLOG_FACILITY; + + if (state.hs_len > 0) { + syslog(priority, "%s", state.header_str); + } + syslog(priority, "%s", msg); +} +#endif /* WITH_SYSLOG */ + +#if defined(HAVE_LIBSYSTEMD_JOURNAL) || defined(HAVE_LIBSYSTEMD) +#include <systemd/sd-journal.h> +static void debug_systemd_log(int msg_level, const char *msg, size_t msg_len) +{ + if (state.hs_len > 0) { + size_t len = state.hs_len; + + if (state.header_str[len - 1] == '\n') { + len -= 1; + } + + sd_journal_send("MESSAGE=%.*s", + (int)len, + state.header_str, + "PRIORITY=%d", + debug_level_to_priority(msg_level), + "LEVEL=%d", + msg_level, + NULL); + } + + if ((msg_len > 0) && (msg[msg_len - 1] == '\n')) { + msg_len -= 1; + } + + sd_journal_send("MESSAGE=%.*s", + (int)msg_len, + msg, + "PRIORITY=%d", + debug_level_to_priority(msg_level), + "LEVEL=%d", + msg_level, + NULL); +} +#endif + +#ifdef HAVE_LTTNG_TRACEF +#include <lttng/tracef.h> +static void debug_lttng_log(int msg_level, const char *msg, size_t msg_len) +{ + if (state.hs_len > 0) { + size_t len = state.hs_len; + + if (state.header_str[len - 1] == '\n') { + len -= 1; + } + + tracef("%.*s", (int)len, state.header_str); + } + + if ((msg_len > 0) && (msg[msg_len - 1] == '\n')) { + msg_len -= 1; + } + tracef("%.*s", (int)msg_len, msg); +} +#endif /* WITH_LTTNG_TRACEF */ + +#ifdef HAVE_GPFS +#include "gpfswrap.h" +static void debug_gpfs_reload(bool enabled, bool previously_enabled, + const char *prog_name, char *option) +{ + if (enabled) { + gpfswrap_init(); + } + + if (enabled && !previously_enabled) { + gpfswrap_init_trace(); + return; + } + + if (!enabled && previously_enabled) { + gpfswrap_fini_trace(); + return; + } + + if (enabled) { + /* + * Trigger GPFS library to adjust state if necessary. + */ + gpfswrap_query_trace(); + } +} + +static void copy_no_nl(char *out, + size_t out_size, + const char *in, + size_t in_len) +{ + size_t len; + /* + * Some backends already add an extra newline, so also provide + * a buffer without the newline character. + */ + len = MIN(in_len, out_size - 1); + if ((len > 0) && (in[len - 1] == '\n')) { + len--; + } + + memcpy(out, in, len); + out[len] = '\0'; +} + +static void debug_gpfs_log(int msg_level, const char *msg, size_t msg_len) +{ + char no_nl[FORMAT_BUFR_SIZE]; + + if (state.hs_len > 0) { + copy_no_nl(no_nl, + sizeof(no_nl), + state.header_str, + state.hs_len); + gpfswrap_add_trace(msg_level, no_nl); + } + + copy_no_nl(no_nl, sizeof(no_nl), msg, msg_len); + gpfswrap_add_trace(msg_level, no_nl); +} +#endif /* HAVE_GPFS */ + +#define DEBUG_RINGBUF_SIZE (1024 * 1024) +#define DEBUG_RINGBUF_SIZE_OPT "size=" + +static char *debug_ringbuf; +static size_t debug_ringbuf_size; +static size_t debug_ringbuf_ofs; + +/* We ensure in debug_ringbuf_log() that this is always \0 terminated */ +char *debug_get_ringbuf(void) +{ + return debug_ringbuf; +} + +/* Return the size of the ringbuf (including a \0 terminator) */ +size_t debug_get_ringbuf_size(void) +{ + return debug_ringbuf_size; +} + +static void debug_ringbuf_reload(bool enabled, bool previously_enabled, + const char *prog_name, char *option) +{ + bool cmp; + size_t optlen = strlen(DEBUG_RINGBUF_SIZE_OPT); + + debug_ringbuf_size = DEBUG_RINGBUF_SIZE; + debug_ringbuf_ofs = 0; + + SAFE_FREE(debug_ringbuf); + + if (!enabled) { + return; + } + + if (option != NULL) { + cmp = strncmp(option, DEBUG_RINGBUF_SIZE_OPT, optlen); + if (cmp == 0) { + debug_ringbuf_size = (size_t)strtoull( + option + optlen, NULL, 10); + } + } + + debug_ringbuf = calloc(debug_ringbuf_size, sizeof(char)); + if (debug_ringbuf == NULL) { + return; + } +} + +static void _debug_ringbuf_log(int msg_level, const char *msg, size_t msg_len) +{ + size_t allowed_size; + + if (debug_ringbuf == NULL) { + return; + } + + /* Ensure the buffer is always \0 terminated */ + allowed_size = debug_ringbuf_size - 1; + + if (msg_len > allowed_size) { + return; + } + + if ((debug_ringbuf_ofs + msg_len) < debug_ringbuf_ofs) { + return; + } + + if ((debug_ringbuf_ofs + msg_len) > allowed_size) { + debug_ringbuf_ofs = 0; + } + + memcpy(debug_ringbuf + debug_ringbuf_ofs, msg, msg_len); + debug_ringbuf_ofs += msg_len; +} + +static void debug_ringbuf_log(int msg_level, const char *msg, size_t msg_len) +{ + if (state.hs_len > 0) { + _debug_ringbuf_log(msg_level, state.header_str, state.hs_len); + } + _debug_ringbuf_log(msg_level, msg, msg_len); +} + +static struct debug_backend { + const char *name; + int log_level; + int new_log_level; + void (*reload)(bool enabled, bool prev_enabled, + const char *prog_name, char *option); + void (*log)(int msg_level, + const char *msg, + size_t len); + char *option; +} debug_backends[] = { + { + .name = "file", + .log = debug_file_log, + }, +#ifdef WITH_SYSLOG + { + .name = "syslog", + .reload = debug_syslog_reload, + .log = debug_syslog_log, + }, +#endif + +#if defined(HAVE_LIBSYSTEMD_JOURNAL) || defined(HAVE_LIBSYSTEMD) + { + .name = "systemd", + .log = debug_systemd_log, + }, +#endif + +#ifdef HAVE_LTTNG_TRACEF + { + .name = "lttng", + .log = debug_lttng_log, + }, +#endif + +#ifdef HAVE_GPFS + { + .name = "gpfs", + .reload = debug_gpfs_reload, + .log = debug_gpfs_log, + }, +#endif + { + .name = "ringbuf", + .log = debug_ringbuf_log, + .reload = debug_ringbuf_reload, + }, +}; + +static struct debug_backend *debug_find_backend(const char *name) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(debug_backends); i++) { + if (strcmp(name, debug_backends[i].name) == 0) { + return &debug_backends[i]; + } + } + + return NULL; +} + +/* + * parse "backend[:option][@loglevel] + */ +static void debug_backend_parse_token(char *tok) +{ + char *backend_name_option, *backend_name,*backend_level, *saveptr; + char *backend_option; + struct debug_backend *b; + + /* + * First parse into backend[:option] and loglevel + */ + backend_name_option = strtok_r(tok, "@\0", &saveptr); + if (backend_name_option == NULL) { + return; + } + + backend_level = strtok_r(NULL, "\0", &saveptr); + + /* + * Now parse backend[:option] + */ + backend_name = strtok_r(backend_name_option, ":\0", &saveptr); + if (backend_name == NULL) { + return; + } + + backend_option = strtok_r(NULL, "\0", &saveptr); + + /* + * Find and update backend + */ + b = debug_find_backend(backend_name); + if (b == NULL) { + return; + } + + if (backend_level == NULL) { + b->new_log_level = MAX_DEBUG_LEVEL; + } else { + b->new_log_level = atoi(backend_level); + } + + if (backend_option != NULL) { + b->option = strdup(backend_option); + if (b->option == NULL) { + return; + } + } +} + +/* + * parse "backend1[:option1][@loglevel1] backend2[option2][@loglevel2] ... " + * and enable/disable backends accordingly + */ +static void debug_set_backends(const char *param) +{ + size_t str_len = strlen(param); + char str[str_len+1]; + char *tok, *saveptr; + unsigned i; + + /* + * initialize new_log_level to detect backends that have been + * disabled + */ + for (i = 0; i < ARRAY_SIZE(debug_backends); i++) { + SAFE_FREE(debug_backends[i].option); + debug_backends[i].new_log_level = -1; + } + + memcpy(str, param, str_len + 1); + + tok = strtok_r(str, LIST_SEP, &saveptr); + if (tok == NULL) { + return; + } + + while (tok != NULL) { + debug_backend_parse_token(tok); + tok = strtok_r(NULL, LIST_SEP, &saveptr); + } + + /* + * Let backends react to config changes + */ + for (i = 0; i < ARRAY_SIZE(debug_backends); i++) { + struct debug_backend *b = &debug_backends[i]; + + if (b->reload) { + bool enabled = b->new_log_level > -1; + bool previously_enabled = b->log_level > -1; + + b->reload(enabled, previously_enabled, state.prog_name, + b->option); + } + b->log_level = b->new_log_level; + } +} + +static void debug_backends_log(const char *msg, size_t msg_len, int msg_level) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(debug_backends); i++) { + if (msg_level <= debug_backends[i].log_level) { + debug_backends[i].log(msg_level, msg, msg_len); + } + } + + /* Only log the header once */ + state.hs_len = 0; +} + +int debuglevel_get_class(size_t idx) +{ + return dbgc_config[idx].loglevel; +} + +void debuglevel_set_class(size_t idx, int level) +{ + dbgc_config[idx].loglevel = level; +} + + +/* -------------------------------------------------------------------------- ** + * Internal variables. + * + * debug_count - Number of debug messages that have been output. + * Used to check log size. + * + * current_msg_level - Internal copy of the message debug level. Written by + * dbghdr() and read by Debug1(). + * + * format_bufr - Used to format debug messages. The dbgtext() function + * prints debug messages to a string, and then passes the + * string to format_debug_text(), which uses format_bufr + * to build the formatted output. + * + * format_pos - Marks the first free byte of the format_bufr. + * + * + * log_overflow - When this variable is true, never attempt to check the + * size of the log. This is a hack, so that we can write + * a message using DEBUG, from open_logs() when we + * are unable to open a new log file for some reason. + */ + +static int debug_count = 0; +static char format_bufr[FORMAT_BUFR_SIZE]; +static size_t format_pos = 0; +static bool log_overflow = false; + +/* + * Define all the debug class selection names here. Names *MUST NOT* contain + * white space. There must be one name for each DBGC_<class name>, and they + * must be in the table in the order of DBGC_<class name>.. + */ + +static char **classname_table = NULL; + + +/* -------------------------------------------------------------------------- ** + * Functions... + */ + +static void debug_init(void); + +/*************************************************************************** + Free memory pointed to by global pointers. +****************************************************************************/ + +void gfree_debugsyms(void) +{ + unsigned i; + + TALLOC_FREE(classname_table); + + if ( dbgc_config != debug_class_list_initial ) { + TALLOC_FREE( dbgc_config ); + dbgc_config = discard_const_p(struct debug_class, + debug_class_list_initial); + } + + debug_num_classes = 0; + + state.initialized = false; + + for (i = 0; i < ARRAY_SIZE(debug_backends); i++) { + SAFE_FREE(debug_backends[i].option); + } +} + +/**************************************************************************** +utility lists registered debug class names's +****************************************************************************/ + +char *debug_list_class_names_and_levels(void) +{ + char *buf = talloc_strdup(NULL, ""); + size_t i; + /* prepare strings */ + for (i = 0; i < debug_num_classes; i++) { + talloc_asprintf_addbuf(&buf, + "%s:%d%s", + classname_table[i], + dbgc_config[i].loglevel, + i == (debug_num_classes - 1) ? "\n" : " "); + } + return buf; +} + +/**************************************************************************** + Utility to translate names to debug class index's (internal version). +****************************************************************************/ + +static int debug_lookup_classname_int(const char* classname) +{ + size_t i; + + if (classname == NULL) { + return -1; + } + + for (i=0; i < debug_num_classes; i++) { + char *entry = classname_table[i]; + if (entry != NULL && strcmp(classname, entry)==0) { + return i; + } + } + return -1; +} + +/**************************************************************************** + Add a new debug class to the system. +****************************************************************************/ + +int debug_add_class(const char *classname) +{ + int ndx; + struct debug_class *new_class_list = NULL; + char **new_name_list; + int default_level; + + if (classname == NULL) { + return -1; + } + + /* check the init has yet been called */ + debug_init(); + + ndx = debug_lookup_classname_int(classname); + if (ndx >= 0) { + return ndx; + } + ndx = debug_num_classes; + + if (dbgc_config == debug_class_list_initial) { + /* Initial loading... */ + new_class_list = NULL; + } else { + new_class_list = dbgc_config; + } + + default_level = dbgc_config[DBGC_ALL].loglevel; + + new_class_list = talloc_realloc(NULL, + new_class_list, + struct debug_class, + ndx + 1); + if (new_class_list == NULL) { + return -1; + } + + dbgc_config = new_class_list; + + dbgc_config[ndx] = (struct debug_class) { + .loglevel = default_level, + .fd = -1, + }; + + new_name_list = talloc_realloc(NULL, classname_table, char *, ndx + 1); + if (new_name_list == NULL) { + return -1; + } + classname_table = new_name_list; + + classname_table[ndx] = talloc_strdup(classname_table, classname); + if (classname_table[ndx] == NULL) { + return -1; + } + + debug_num_classes = ndx + 1; + + return ndx; +} + +/**************************************************************************** + Utility to translate names to debug class index's (public version). +****************************************************************************/ + +static int debug_lookup_classname(const char *classname) +{ + int ndx; + + if (classname == NULL || !*classname) + return -1; + + ndx = debug_lookup_classname_int(classname); + + if (ndx != -1) + return ndx; + + DBG_WARNING("Unknown classname[%s] -> adding it...\n", classname); + return debug_add_class(classname); +} + +/**************************************************************************** + Dump the current registered debug levels. +****************************************************************************/ + +static void debug_dump_status(int level) +{ + size_t q; + + DEBUG(level, ("INFO: Current debug levels:\n")); + for (q = 0; q < debug_num_classes; q++) { + const char *classname = classname_table[q]; + DEBUGADD(level, (" %s: %d\n", + classname, + dbgc_config[q].loglevel)); + } +} + +static bool debug_parse_param(char *param) +{ + char *class_name; + char *class_file = NULL; + char *class_level; + char *saveptr = NULL; + int ndx; + + class_name = strtok_r(param, ":", &saveptr); + if (class_name == NULL) { + return false; + } + + class_level = strtok_r(NULL, "@\0", &saveptr); + if (class_level == NULL) { + return false; + } + + class_file = strtok_r(NULL, "\0", &saveptr); + + ndx = debug_lookup_classname(class_name); + if (ndx == -1) { + return false; + } + + dbgc_config[ndx].loglevel = atoi(class_level); + + if (class_file == NULL) { + return true; + } + + TALLOC_FREE(dbgc_config[ndx].logfile); + + dbgc_config[ndx].logfile = talloc_strdup(NULL, class_file); + if (dbgc_config[ndx].logfile == NULL) { + return false; + } + return true; +} + +/**************************************************************************** + Parse the debug levels from smb.conf. Example debug level string: + 3 tdb:5 printdrivers:7 + Note: the 1st param has no "name:" preceding it. +****************************************************************************/ + +bool debug_parse_levels(const char *params_str) +{ + size_t str_len = strlen(params_str); + char str[str_len+1]; + char *tok, *saveptr; + size_t i; + + /* Just in case */ + debug_init(); + + memcpy(str, params_str, str_len+1); + + tok = strtok_r(str, LIST_SEP, &saveptr); + if (tok == NULL) { + return true; + } + + /* Allow DBGC_ALL to be specified w/o requiring its class name e.g."10" + * v.s. "all:10", this is the traditional way to set DEBUGLEVEL + */ + if (isdigit(tok[0])) { + dbgc_config[DBGC_ALL].loglevel = atoi(tok); + tok = strtok_r(NULL, LIST_SEP, &saveptr); + } else { + dbgc_config[DBGC_ALL].loglevel = 0; + } + + /* Array is debug_num_classes long */ + for (i = DBGC_ALL+1; i < debug_num_classes; i++) { + dbgc_config[i].loglevel = dbgc_config[DBGC_ALL].loglevel; + TALLOC_FREE(dbgc_config[i].logfile); + } + + while (tok != NULL) { + bool ok; + + ok = debug_parse_param(tok); + if (!ok) { + DEBUG(0,("debug_parse_params: unrecognized debug " + "class name or format [%s]\n", tok)); + return false; + } + + tok = strtok_r(NULL, LIST_SEP, &saveptr); + } + + debug_dump_status(5); + + return true; +} + +/* setup for logging of talloc warnings */ +static void talloc_log_fn(const char *msg) +{ + DEBUG(0,("%s", msg)); +} + +void debug_setup_talloc_log(void) +{ + talloc_set_log_fn(talloc_log_fn); +} + + +/**************************************************************************** +Init debugging (one time stuff) +****************************************************************************/ + +static void debug_init(void) +{ + size_t i; + + if (state.initialized) + return; + + state.initialized = true; + + debug_setup_talloc_log(); + + for (i = 0; i < ARRAY_SIZE(default_classname_table); i++) { + debug_add_class(default_classname_table[i]); + } + dbgc_config[DBGC_ALL].fd = 2; + + for (i = 0; i < ARRAY_SIZE(debug_backends); i++) { + debug_backends[i].log_level = -1; + debug_backends[i].new_log_level = -1; + } +} + +void debug_set_settings(struct debug_settings *settings, + const char *logging_param, + int syslog_level, bool syslog_only) +{ + char fake_param[256]; + size_t len = 0; + + /* + * This forces in some smb.conf derived values into the debug + * system. There are no pointers in this structure, so we can + * just structure-assign it in + */ + state.settings = *settings; + + /* + * If 'logging' is not set, create backend settings from + * deprecated 'syslog' and 'syslog only' parameters + */ + if (logging_param != NULL) { + len = strlen(logging_param); + } + if (len == 0) { + if (syslog_only) { + snprintf(fake_param, sizeof(fake_param), + "syslog@%d", syslog_level - 1); + } else { + snprintf(fake_param, sizeof(fake_param), + "syslog@%d file@%d", syslog_level -1, + MAX_DEBUG_LEVEL); + } + + logging_param = fake_param; + } + + debug_set_backends(logging_param); +} + +static void ensure_hostname(void) +{ + int ret; + + if (state.hostname[0] != '\0') { + return; + } + + ret = gethostname(state.hostname, sizeof(state.hostname)); + if (ret != 0) { + strlcpy(state.hostname, "unknown", sizeof(state.hostname)); + return; + } + + /* + * Ensure NUL termination, since POSIX isn't clear about that. + * + * Don't worry about truncating at the first '.' or similar, + * since this is usually not fully qualified. Trying to + * truncate opens up the multibyte character gates of hell. + */ + state.hostname[sizeof(state.hostname) - 1] = '\0'; +} + +void debug_set_hostname(const char *name) +{ + strlcpy(state.hostname, name, sizeof(state.hostname)); +} + +void debug_set_forced_log_priority(int forced_log_priority) +{ + state.forced_log_priority = forced_log_priority; +} + +/** + * Ensure debug logs are initialised. + * + * setup_logging() is called to direct logging to the correct outputs, whether + * those be stderr, stdout, files, or syslog, and set the program name used in + * the logs. It can be called multiple times. + * + * There is an order of precedence to the log type. Once set to DEBUG_FILE, it + * cannot be reset DEFAULT_DEBUG_STDERR, but can be set to DEBUG_STDERR, after + * which DEBUG_FILE is unavailable). This makes it possible to override for + * debug to stderr on the command line, as the smb.conf cannot reset it back + * to file-based logging. See enum debug_logtype. + * + * @param prog_name the program name. Directory path component will be + * ignored. + * + * @param new_logtype the requested destination for the debug log, + * as an enum debug_logtype. + */ +void setup_logging(const char *prog_name, enum debug_logtype new_logtype) +{ + debug_init(); + if (state.logtype < new_logtype) { + state.logtype = new_logtype; + } + if (prog_name) { + const char *p = strrchr(prog_name, '/'); + + if (p) { + prog_name = p + 1; + } + + strlcpy(state.prog_name, prog_name, sizeof(state.prog_name)); + } + reopen_logs_internal(); +} + +/*************************************************************************** + Set the logfile name. +**************************************************************************/ + +void debug_set_logfile(const char *name) +{ + if (name == NULL || *name == 0) { + /* this copes with calls when smb.conf is not loaded yet */ + return; + } + TALLOC_FREE(dbgc_config[DBGC_ALL].logfile); + dbgc_config[DBGC_ALL].logfile = talloc_strdup(NULL, name); + + reopen_logs_internal(); +} + +static void debug_close_fd(int fd) +{ + if (fd > 2) { + close(fd); + } +} + +enum debug_logtype debug_get_log_type(void) +{ + return state.logtype; +} + +bool debug_get_output_is_stderr(void) +{ + return (state.logtype == DEBUG_DEFAULT_STDERR) || (state.logtype == DEBUG_STDERR); +} + +bool debug_get_output_is_stdout(void) +{ + return (state.logtype == DEBUG_DEFAULT_STDOUT) || (state.logtype == DEBUG_STDOUT); +} + +void debug_set_callback(void *private_ptr, debug_callback_fn fn) +{ + debug_init(); + if (fn) { + state.logtype = DEBUG_CALLBACK; + state.callback_private = private_ptr; + state.callback = fn; + } else { + state.logtype = DEBUG_DEFAULT_STDERR; + state.callback_private = NULL; + state.callback = NULL; + } +} + +static void debug_callback_log(const char *msg, size_t msg_len, int msg_level) +{ + char msg_copy[msg_len]; + + if ((msg_len > 0) && (msg[msg_len-1] == '\n')) { + memcpy(msg_copy, msg, msg_len-1); + msg_copy[msg_len-1] = '\0'; + msg = msg_copy; + } + + state.callback(state.callback_private, msg_level, msg); +} + +/************************************************************************** + reopen the log files + note that we now do this unconditionally + We attempt to open the new debug fp before closing the old. This means + if we run out of fd's we just keep using the old fd rather than aborting. + Fix from dgibson@linuxcare.com. +**************************************************************************/ + +static bool reopen_one_log(struct debug_class *config) +{ + int old_fd = config->fd; + const char *logfile = config->logfile; + struct stat st; + int new_fd; + int ret; + + if (logfile == NULL) { + debug_close_fd(old_fd); + config->fd = -1; + return true; + } + + new_fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0644); + if (new_fd == -1) { + log_overflow = true; + DBG_ERR("Unable to open new log file '%s': %s\n", + logfile, strerror(errno)); + log_overflow = false; + return false; + } + + debug_close_fd(old_fd); + smb_set_close_on_exec(new_fd); + config->fd = new_fd; + + ret = fstat(new_fd, &st); + if (ret != 0) { + log_overflow = true; + DBG_ERR("Unable to fstat() new log file '%s': %s\n", + logfile, strerror(errno)); + log_overflow = false; + return false; + } + + config->ino = st.st_ino; + return true; +} + +/** + reopen the log file (usually called because the log file name might have changed) +*/ +bool reopen_logs_internal(void) +{ + struct debug_backend *b = NULL; + mode_t oldumask; + size_t i; + bool ok = true; + + if (state.reopening_logs) { + return true; + } + + /* Now clear the SIGHUP induced flag */ + state.schedule_reopen_logs = false; + + switch (state.logtype) { + case DEBUG_CALLBACK: + return true; + case DEBUG_STDOUT: + case DEBUG_DEFAULT_STDOUT: + debug_close_fd(dbgc_config[DBGC_ALL].fd); + dbgc_config[DBGC_ALL].fd = 1; + return true; + + case DEBUG_DEFAULT_STDERR: + case DEBUG_STDERR: + debug_close_fd(dbgc_config[DBGC_ALL].fd); + dbgc_config[DBGC_ALL].fd = 2; + return true; + + case DEBUG_FILE: + b = debug_find_backend("file"); + assert(b != NULL); + + b->log_level = MAX_DEBUG_LEVEL; + break; + } + + oldumask = umask( 022 ); + + for (i = DBGC_ALL; i < debug_num_classes; i++) { + if (dbgc_config[i].logfile != NULL) { + break; + } + } + if (i == debug_num_classes) { + return false; + } + + state.reopening_logs = true; + + for (i = DBGC_ALL; i < debug_num_classes; i++) { + ok = reopen_one_log(&dbgc_config[i]); + if (!ok) { + break; + } + } + + /* Fix from klausr@ITAP.Physik.Uni-Stuttgart.De + * to fix problem where smbd's that generate less + * than 100 messages keep growing the log. + */ + force_check_log_size(); + (void)umask(oldumask); + + /* + * If log file was opened or created successfully, take over stderr to + * catch output into logs. + */ + if (!state.settings.debug_no_stderr_redirect && + dbgc_config[DBGC_ALL].fd > 0) { + if (dup2(dbgc_config[DBGC_ALL].fd, 2) == -1) { + /* Close stderr too, if dup2 can't point it - + at the logfile. There really isn't much + that can be done on such a fundamental + failure... */ + close_low_fd(2); + } + } + + state.reopening_logs = false; + + return ok; +} + +/************************************************************************** + Force a check of the log size. + ***************************************************************************/ + +void force_check_log_size( void ) +{ + debug_count = 100; +} + +_PUBLIC_ void debug_schedule_reopen_logs(void) +{ + state.schedule_reopen_logs = true; +} + + +/*************************************************************************** + Check to see if there is any need to check if the logfile has grown too big. +**************************************************************************/ + +bool need_to_check_log_size(void) +{ + int maxlog; + size_t i; + + if (debug_count < 100) { + return false; + } + + maxlog = state.settings.max_log_size * 1024; + if (maxlog <= 0) { + debug_count = 0; + return false; + } + + if (dbgc_config[DBGC_ALL].fd > 2) { + return true; + } + + for (i = DBGC_ALL + 1; i < debug_num_classes; i++) { + if (dbgc_config[i].fd != -1) { + return true; + } + } + + debug_count = 0; + return false; +} + +/************************************************************************** + Check to see if the log has grown to be too big. + **************************************************************************/ + +static void do_one_check_log_size(off_t maxlog, struct debug_class *config) +{ + char name[strlen(config->logfile) + 5]; + struct stat st; + int ret; + bool reopen = false; + bool ok; + + if (maxlog == 0) { + return; + } + + ret = stat(config->logfile, &st); + if (ret != 0) { + return; + } + if (st.st_size >= maxlog ) { + reopen = true; + } + + if (st.st_ino != config->ino) { + reopen = true; + } + + if (!reopen) { + return; + } + + /* reopen_logs_internal() modifies *_fd */ + (void)reopen_logs_internal(); + + if (config->fd <= 2) { + return; + } + ret = fstat(config->fd, &st); + if (ret != 0) { + config->ino = (ino_t)0; + return; + } + + config->ino = st.st_ino; + + if (st.st_size < maxlog) { + return; + } + + snprintf(name, sizeof(name), "%s.old", config->logfile); + + (void)rename(config->logfile, name); + + ok = reopen_logs_internal(); + if (ok) { + return; + } + /* We failed to reopen a log - continue using the old name. */ + (void)rename(name, config->logfile); +} + +static void do_check_log_size(off_t maxlog) +{ + size_t i; + + for (i = DBGC_ALL; i < debug_num_classes; i++) { + if (dbgc_config[i].fd == -1) { + continue; + } + if (dbgc_config[i].logfile == NULL) { + continue; + } + do_one_check_log_size(maxlog, &dbgc_config[i]); + } +} + +void check_log_size( void ) +{ + off_t maxlog; + + if (geteuid() != 0) { + /* + * We need to be root to change the log file (tests use a fake + * geteuid() from third_party/uid_wrapper). Otherwise we skip + * this and let the main smbd loop or some other process do + * the work. + */ + return; + } + + if(log_overflow || (!state.schedule_reopen_logs && !need_to_check_log_size())) { + return; + } + + maxlog = state.settings.max_log_size * 1024; + + if (state.schedule_reopen_logs) { + (void)reopen_logs_internal(); + } + + do_check_log_size(maxlog); + + /* + * Here's where we need to panic if dbgc_config[DBGC_ALL].fd == 0 or -1 + * (invalid values) + */ + + if (dbgc_config[DBGC_ALL].fd <= 0) { + /* This code should only be reached in very strange + * circumstances. If we merely fail to open the new log we + * should stick with the old one. ergo this should only be + * reached when opening the logs for the first time: at + * startup or when the log level is increased from zero. + * -dwg 6 June 2000 + */ + int fd = open( "/dev/console", O_WRONLY, 0); + if (fd != -1) { + smb_set_close_on_exec(fd); + dbgc_config[DBGC_ALL].fd = fd; + DBG_ERR("check_log_size: open of debug file %s failed " + "- using console.\n", + dbgc_config[DBGC_ALL].logfile); + } else { + /* + * We cannot continue without a debug file handle. + */ + abort(); + } + } + debug_count = 0; +} + +/************************************************************************* + Write an debug message on the debugfile. + This is called by format_debug_text(). +************************************************************************/ + +static void Debug1(const char *msg, size_t msg_len) +{ + int old_errno = errno; + + debug_count++; + + switch(state.logtype) { + case DEBUG_CALLBACK: + debug_callback_log(msg, msg_len, current_msg_level); + break; + case DEBUG_STDOUT: + case DEBUG_STDERR: + case DEBUG_DEFAULT_STDOUT: + case DEBUG_DEFAULT_STDERR: + if (state.settings.debug_syslog_format == + DEBUG_SYSLOG_FORMAT_ALWAYS) { + debug_file_log(current_msg_level, msg, msg_len); + } else { + if (dbgc_config[DBGC_ALL].fd > 0) { + ssize_t ret; + do { + ret = write(dbgc_config[DBGC_ALL].fd, + msg, + msg_len); + } while (ret == -1 && errno == EINTR); + } + } + break; + case DEBUG_FILE: + debug_backends_log(msg, msg_len, current_msg_level); + break; + }; + + errno = old_errno; +} + +/************************************************************************** + Print the buffer content via Debug1(), then reset the buffer. + Input: none + Output: none +****************************************************************************/ + +static void bufr_print( void ) +{ + format_bufr[format_pos] = '\0'; + (void)Debug1(format_bufr, format_pos); + format_pos = 0; +} + +/* + * If set (by tevent_thread_call_depth_set()) to value > 0, debug code will use + * it for the trace indentation. + */ +static size_t debug_call_depth = 0; + +size_t *debug_call_depth_addr(void) +{ + return &debug_call_depth; +} + +/*************************************************************************** + Format the debug message text. + + Input: msg - Text to be added to the "current" debug message text. + + Output: none. + + Notes: The purpose of this is two-fold. First, each call to syslog() + (used by Debug1(), see above) generates a new line of syslog + output. This is fixed by storing the partial lines until the + newline character is encountered. Second, printing the debug + message lines when a newline is encountered allows us to add + spaces, thus indenting the body of the message and making it + more readable. +**************************************************************************/ + +static void format_debug_text( const char *msg ) +{ + size_t i; + bool timestamp = (state.logtype == DEBUG_FILE && (state.settings.timestamp_logs)); + + debug_init(); + + for( i = 0; msg[i]; i++ ) { + /* Indent two spaces at each new line. */ + if(timestamp && 0 == format_pos) { + /* Limit the maximum indentation to 20 levels */ + size_t depth = MIN(20, debug_call_depth); + format_bufr[0] = format_bufr[1] = ' '; + format_pos = 2; + /* + * Indent by four spaces for each depth level, + * but only if the current debug level is >= 8. + */ + if (depth > 0 && debuglevel_get() >= 8 && + format_pos + 4 * depth < FORMAT_BUFR_SIZE) { + memset(&format_bufr[format_pos], + ' ', + 4 * depth); + format_pos += 4 * depth; + } + } + + /* If there's room, copy the character to the format buffer. */ + if (format_pos < FORMAT_BUFR_SIZE - 1) + format_bufr[format_pos++] = msg[i]; + + /* If a newline is encountered, print & restart. */ + if( '\n' == msg[i] ) + bufr_print(); + + /* If the buffer is full dump it out, reset it, and put out a line + * continuation indicator. + */ + if (format_pos >= FORMAT_BUFR_SIZE - 1) { + const char cont[] = " +>\n"; + bufr_print(); + (void)Debug1(cont , sizeof(cont) - 1); + } + } + + /* Just to be safe... */ + format_bufr[format_pos] = '\0'; +} + +/*************************************************************************** + Flush debug output, including the format buffer content. + + Input: none + Output: none +***************************************************************************/ + +void dbgflush( void ) +{ + bufr_print(); +} + +bool dbgsetclass(int level, int cls) +{ + /* Set current_msg_level. */ + current_msg_level = level; + + /* Set current message class */ + current_msg_class = cls; + + return true; +} + +/*************************************************************************** + Put a Debug Header into header_str. + + Input: level - Debug level of the message (not the system-wide debug + level. ) + cls - Debuglevel class of the calling module. + location - Pointer to a string containing the name of the file + from which this function was called, or an empty string + if the __FILE__ macro is not implemented. + func - Pointer to a string containing the name of the function + from which this function was called, or an empty string + if the __FUNCTION__ macro is not implemented. + + Output: Always true. This makes it easy to fudge a call to dbghdr() + in a macro, since the function can be called as part of a test. + Eg: ( (level <= DEBUGLEVEL) && (dbghdr(level,"",line)) ) + + Notes: This function takes care of setting current_msg_level. + +****************************************************************************/ + +bool dbghdrclass(int level, int cls, const char *location, const char *func) +{ + /* Ensure we don't lose any real errno value. */ + int old_errno = errno; + bool verbose = false; + struct timeval tv; + struct timeval_buf tvbuf; + + /* + * This might be overkill, but if another early return is + * added later then initialising these avoids potential + * problems + */ + state.hs_len = 0; + state.header_str[0] = '\0'; + + if( format_pos ) { + /* This is a fudge. If there is stuff sitting in the format_bufr, then + * the *right* thing to do is to call + * format_debug_text( "\n" ); + * to write the remainder, and then proceed with the new header. + * Unfortunately, there are several places in the code at which + * the DEBUG() macro is used to build partial lines. That in mind, + * we'll work under the assumption that an incomplete line indicates + * that a new header is *not* desired. + */ + return( true ); + } + + dbgsetclass(level, cls); + + /* + * Don't print a header if we're logging to stdout, + * unless 'debug syslog format = always' + */ + if (state.logtype != DEBUG_FILE && + state.settings.debug_syslog_format != DEBUG_SYSLOG_FORMAT_ALWAYS) + { + return true; + } + + /* + * Print the header if timestamps (or debug syslog format) is + * turned on. If parameters are not yet loaded, then default + * to timestamps on. + */ + if (!(state.settings.timestamp_logs || + state.settings.debug_prefix_timestamp || + state.settings.debug_syslog_format != DEBUG_SYSLOG_FORMAT_NO)) + { + return true; + } + + GetTimeOfDay(&tv); + + if (state.settings.debug_syslog_format != DEBUG_SYSLOG_FORMAT_NO) { + if (state.settings.debug_hires_timestamp) { + timeval_str_buf(&tv, true, true, &tvbuf); + } else { + time_t t; + struct tm *tm; + + t = (time_t)tv.tv_sec; + tm = localtime(&t); + if (tm != NULL) { + size_t len; + len = strftime(tvbuf.buf, + sizeof(tvbuf.buf), + "%b %e %T", + tm); + if (len == 0) { + /* Trigger default time format below */ + tm = NULL; + } + } + if (tm == NULL) { + snprintf(tvbuf.buf, + sizeof(tvbuf.buf), + "%ld seconds since the Epoch", (long)t); + } + } + + ensure_hostname(); + state.hs_len = snprintf(state.header_str, + sizeof(state.header_str), + "%s %.*s %s[%u]: ", + tvbuf.buf, + (int)(sizeof(state.hostname) - 1), + state.hostname, + state.prog_name, + (unsigned int) getpid()); + + goto full; + } + + timeval_str_buf(&tv, false, state.settings.debug_hires_timestamp, + &tvbuf); + + state.hs_len = snprintf(state.header_str, + sizeof(state.header_str), + "[%s, %2d", + tvbuf.buf, + level); + if (state.hs_len >= sizeof(state.header_str) - 1) { + goto full; + } + + if (unlikely(dbgc_config[cls].loglevel >= 10)) { + verbose = true; + } + + if (verbose || state.settings.debug_pid) { + state.hs_len += snprintf(state.header_str + state.hs_len, + sizeof(state.header_str) - state.hs_len, + ", pid=%u", + (unsigned int)getpid()); + if (state.hs_len >= sizeof(state.header_str) - 1) { + goto full; + } + } + + if (verbose || state.settings.debug_uid) { + state.hs_len += snprintf(state.header_str + state.hs_len, + sizeof(state.header_str) - state.hs_len, + ", effective(%u, %u), real(%u, %u)", + (unsigned int)geteuid(), + (unsigned int)getegid(), + (unsigned int)getuid(), + (unsigned int)getgid()); + if (state.hs_len >= sizeof(state.header_str) - 1) { + goto full; + } + } + + if ((verbose || state.settings.debug_class) + && (cls != DBGC_ALL)) { + state.hs_len += snprintf(state.header_str + state.hs_len, + sizeof(state.header_str) - state.hs_len, + ", class=%s", + classname_table[cls]); + if (state.hs_len >= sizeof(state.header_str) - 1) { + goto full; + } + } + + if (debug_traceid_get() != 0) { + state.hs_len += snprintf(state.header_str + state.hs_len, + sizeof(state.header_str) - state.hs_len, + ", traceid=%" PRIu64, + debug_traceid_get()); + if (state.hs_len >= sizeof(state.header_str) - 1) { + goto full; + } + } + + if (debug_call_depth > 0) { + state.hs_len += snprintf(state.header_str + state.hs_len, + sizeof(state.header_str) - state.hs_len, + ", depth=%zu", + debug_call_depth); + if (state.hs_len >= sizeof(state.header_str) - 1) { + goto full; + } + } + + state.header_str[state.hs_len] = ']'; + state.hs_len++; + if (state.hs_len < sizeof(state.header_str) - 1) { + state.header_str[state.hs_len] = ' '; + state.hs_len++; + } + state.header_str[state.hs_len] = '\0'; + + if (!state.settings.debug_prefix_timestamp) { + state.hs_len += snprintf(state.header_str + state.hs_len, + sizeof(state.header_str) - state.hs_len, + "%s(%s)\n", + location, + func); + if (state.hs_len >= sizeof(state.header_str)) { + goto full; + } + } + +full: + /* + * Above code never overflows state.header_str and always + * NUL-terminates correctly. However, state.hs_len can point + * past the end of the buffer to indicate that truncation + * occurred, so fix it if necessary, since state.hs_len is + * expected to be used after return. + */ + if (state.hs_len >= sizeof(state.header_str)) { + state.hs_len = sizeof(state.header_str) - 1; + } + + errno = old_errno; + return( true ); +} + +/*************************************************************************** + Add text to the body of the "current" debug message via the format buffer. + + Input: format_str - Format string, as used in printf(), et. al. + ... - Variable argument list. + + ..or.. va_alist - Old style variable parameter list starting point. + + Output: Always true. See dbghdr() for more info, though this is not + likely to be used in the same way. + +***************************************************************************/ + +static inline bool __dbgtext_va(const char *format_str, va_list ap) PRINTF_ATTRIBUTE(1,0); +static inline bool __dbgtext_va(const char *format_str, va_list ap) +{ + char *msgbuf = NULL; + bool ret = true; + int res; + + res = vasprintf(&msgbuf, format_str, ap); + if (res != -1) { + format_debug_text(msgbuf); + } else { + ret = false; + } + SAFE_FREE(msgbuf); + return ret; +} + +bool dbgtext_va(const char *format_str, va_list ap) +{ + return __dbgtext_va(format_str, ap); +} + +bool dbgtext(const char *format_str, ... ) +{ + va_list ap; + bool ret; + + va_start(ap, format_str); + ret = __dbgtext_va(format_str, ap); + va_end(ap); + + return ret; +} + +static uint64_t debug_traceid = 0; + +uint64_t debug_traceid_set(uint64_t id) +{ + uint64_t old_id = debug_traceid; + debug_traceid = id; + return old_id; +} + +uint64_t debug_traceid_get(void) +{ + return debug_traceid; +} diff --git a/lib/util/debug.h b/lib/util/debug.h new file mode 100644 index 0000000..4687ac0 --- /dev/null +++ b/lib/util/debug.h @@ -0,0 +1,396 @@ +/* + Unix SMB/CIFS implementation. + SMB debug stuff + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) John H Terpstra 1996-1998 + Copyright (C) Luke Kenneth Casson Leighton 1996-1998 + Copyright (C) Paul Ashton 1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_DEBUG_H +#define _SAMBA_DEBUG_H + +#include <stdint.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdarg.h> +#include "attr.h" + + +/* -------------------------------------------------------------------------- ** + * Debugging code. See also debug.c + */ + +/* the maximum debug level to compile into the code. This assumes a good + optimising compiler that can remove unused code + for embedded or low-memory systems set this to a value like 2 to get + only important messages. This gives *much* smaller binaries +*/ +#ifndef MAX_DEBUG_LEVEL +#define MAX_DEBUG_LEVEL 1000 +#endif + +bool dbgtext_va(const char *, va_list ap) PRINTF_ATTRIBUTE(1,0); +bool dbgtext( const char *, ... ) PRINTF_ATTRIBUTE(1,2); +bool dbghdrclass( int level, int cls, const char *location, const char *func); +bool dbgsetclass(int level, int cls); + +/* + * Define all new debug classes here. A class is represented by an entry in + * the DEBUGLEVEL_CLASS array. Index zero of this array is equivalent to the + * old DEBUGLEVEL. Any source file that does NOT add the following lines: + * + * #undef DBGC_CLASS + * #define DBGC_CLASS DBGC_<your class name here> + * + * at the start of the file (after #include "includes.h") will default to + * using index zero, so it will behave just like it always has. + */ +#define DBGC_ALL 0 /* index equivalent to DEBUGLEVEL */ + +#define DBGC_TDB 1 +#define DBGC_PRINTDRIVERS 2 +#define DBGC_LANMAN 3 +#define DBGC_SMB 4 +#define DBGC_RPC_PARSE 5 +#define DBGC_RPC_SRV 6 +#define DBGC_RPC_CLI 7 +#define DBGC_PASSDB 8 +#define DBGC_SAM 9 +#define DBGC_AUTH 10 +#define DBGC_WINBIND 11 +#define DBGC_VFS 12 +#define DBGC_IDMAP 13 +#define DBGC_QUOTA 14 +#define DBGC_ACLS 15 +#define DBGC_LOCKING 16 +#define DBGC_MSDFS 17 +#define DBGC_DMAPI 18 +#define DBGC_REGISTRY 19 +#define DBGC_SCAVENGER 20 +#define DBGC_DNS 21 +#define DBGC_LDB 22 +#define DBGC_TEVENT 23 +#define DBGC_AUTH_AUDIT 24 +#define DBGC_AUTH_AUDIT_JSON 25 +#define DBGC_KERBEROS 26 +#define DBGC_DRS_REPL 27 +#define DBGC_SMB2 28 +#define DBGC_SMB2_CREDITS 29 +#define DBGC_DSDB_AUDIT 30 +#define DBGC_DSDB_AUDIT_JSON 31 +#define DBGC_DSDB_PWD_AUDIT 32 +#define DBGC_DSDB_PWD_AUDIT_JSON 33 +#define DBGC_DSDB_TXN_AUDIT 34 +#define DBGC_DSDB_TXN_AUDIT_JSON 35 +#define DBGC_DSDB_GROUP_AUDIT 36 +#define DBGC_DSDB_GROUP_AUDIT_JSON 37 + +/* So you can define DBGC_CLASS before including debug.h */ +#ifndef DBGC_CLASS +#define DBGC_CLASS 0 /* override as shown above */ +#endif + +#define DEBUGLEVEL debuglevel_get() + +#define debuglevel_get() debuglevel_get_class(DBGC_ALL) +#define debuglevel_set(lvl) debuglevel_set_class(DBGC_ALL, (lvl)) + +/* Debugging macros + * + * DEBUGLVL() + * If the 'file specific' debug class level >= level OR the system-wide + * DEBUGLEVEL (synonym for DEBUGLEVEL_CLASS[ DBGC_ALL ]) >= level then + * generate a header using the default macros for file, line, and + * function name. Returns True if the debug level was <= DEBUGLEVEL. + * + * Example: if( DEBUGLVL( 2 ) ) dbgtext( "Some text.\n" ); + * + * DEBUG() + * If the 'file specific' debug class level >= level OR the system-wide + * DEBUGLEVEL (synonym for DEBUGLEVEL_CLASS[ DBGC_ALL ]) >= level then + * generate a header using the default macros for file, line, and + * function name. Each call to DEBUG() generates a new header *unless* the + * previous debug output was unterminated (i.e. no '\n'). + * See debug.c:dbghdr() for more info. + * + * Example: DEBUG( 2, ("Some text and a value %d.\n", value) ); + * + * DEBUGC() + * If the 'macro specified' debug class level >= level OR the system-wide + * DEBUGLEVEL (synonym for DEBUGLEVEL_CLASS[ DBGC_ALL ]) >= level then + * generate a header using the default macros for file, line, and + * function name. Each call to DEBUG() generates a new header *unless* the + * previous debug output was unterminated (i.e. no '\n'). + * See debug.c:dbghdr() for more info. + * + * Example: DEBUGC( DBGC_TDB, 2, ("Some text and a value %d.\n", value) ); + * + * DEBUGADD(), DEBUGADDC() + * Same as DEBUG() and DEBUGC() except the text is appended to the previous + * DEBUG(), DEBUGC(), DEBUGADD(), DEBUGADDC() with out another interviening + * header. + * + * Example: DEBUGADD( 2, ("Some text and a value %d.\n", value) ); + * DEBUGADDC( DBGC_TDB, 2, ("Some text and a value %d.\n", value) ); + * + * Note: If the debug class has not be redefined (see above) then the optimizer + * will remove the extra conditional test. + */ + +/* + * From talloc.c: + */ + +/* these macros gain us a few percent of speed on gcc */ +#if (__GNUC__ >= 3) +/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1 + as its first argument */ +#ifndef likely +#define likely(x) __builtin_expect(!!(x), 1) +#endif +#ifndef unlikely +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#else +#ifndef likely +#define likely(x) (x) +#endif +#ifndef unlikely +#define unlikely(x) (x) +#endif +#endif + +int debuglevel_get_class(size_t idx); +void debuglevel_set_class(size_t idx, int level); + +#define CHECK_DEBUGLVL( level ) \ + ( ((level) <= MAX_DEBUG_LEVEL) && \ + unlikely(debuglevel_get_class(DBGC_CLASS) >= (level))) + +#define CHECK_DEBUGLVLC( dbgc_class, level ) \ + ( ((level) <= MAX_DEBUG_LEVEL) && \ + unlikely(debuglevel_get_class(dbgc_class) >= (level))) + +#define DEBUGLVL( level ) \ + ( CHECK_DEBUGLVL(level) \ + && dbghdrclass( level, DBGC_CLASS, __location__, __FUNCTION__ ) ) + +#define DEBUGLVLC( dbgc_class, level ) \ + ( CHECK_DEBUGLVLC( dbgc_class, level ) \ + && dbghdrclass( level, dbgc_class, __location__, __FUNCTION__ ) ) + +#define DEBUG( level, body ) \ + (void)( ((level) <= MAX_DEBUG_LEVEL) && \ + unlikely(debuglevel_get_class(DBGC_CLASS) >= (level)) \ + && (dbghdrclass( level, DBGC_CLASS, __location__, __FUNCTION__ )) \ + && (dbgtext body) ) + +/** + * @brief DEBUGLF is same as DEBUG with explicit location and function arguments + * + * To be used when passing location and function of a caller appearing earlier in + * the call stack instead of some helper function. + * + * @code + * DEBUGLF( 2, ("Some text.\n"), "foo.c:1", "foo" ); + * DEBUGLF( 5, ("Some text.\n"), location, function ); + * @endcode + * + * @return void. + */ +#define DEBUGLF( level, body, location, function ) \ + (void)( ((level) <= MAX_DEBUG_LEVEL) && \ + unlikely(debuglevel_get_class(DBGC_CLASS) >= (level)) \ + && (dbghdrclass( level, DBGC_CLASS, location, function )) \ + && (dbgtext body) ) + +#define DEBUGC( dbgc_class, level, body ) \ + (void)( ((level) <= MAX_DEBUG_LEVEL) && \ + unlikely(debuglevel_get_class(dbgc_class) >= (level)) \ + && (dbghdrclass( level, dbgc_class, __location__, __FUNCTION__ )) \ + && (dbgtext body) ) + +#define DEBUGADD( level, body ) \ + (void)( ((level) <= MAX_DEBUG_LEVEL) && \ + unlikely(debuglevel_get_class(DBGC_CLASS) >= (level)) \ + && (dbgsetclass(level, DBGC_CLASS)) \ + && (dbgtext body) ) + +#define DEBUGADDC( dbgc_class, level, body ) \ + (void)( ((level) <= MAX_DEBUG_LEVEL) && \ + unlikely((debuglevel_get_class(dbgc_class) >= (level))) \ + && (dbgsetclass(level, dbgc_class)) \ + && (dbgtext body) ) + +/* Print a separator to the debug log. */ +#define DEBUGSEP(level)\ + DEBUG((level),("===============================================================\n")) + +/* Prefix messages with the function name */ +#define DBG_PREFIX(level, body ) \ + (void)( ((level) <= MAX_DEBUG_LEVEL) && \ + unlikely(debuglevel_get_class(DBGC_CLASS) >= (level)) \ + && (dbghdrclass(level, DBGC_CLASS, __location__, __func__ )) \ + && (dbgtext("%s: ", __func__)) \ + && (dbgtext body) ) + +/* Prefix messages with the function name - class specific */ +#define DBGC_PREFIX(dbgc_class, level, body ) \ + (void)( ((level) <= MAX_DEBUG_LEVEL) && \ + unlikely(debuglevel_get_class(dbgc_class) >= (level)) \ + && (dbghdrclass(level, dbgc_class, __location__, __func__ )) \ + && (dbgtext("%s: ", __func__)) \ + && (dbgtext body) ) + + +#ifdef DEVELOPER +#define DBG_DEV(...) \ + (void)( (debug_developer_enabled()) \ + && (dbgtext("%s:DEV:%d: ", __func__, getpid())) \ + && (dbgtext(__VA_ARGS__)) ) +#else +#define DBG_DEV(...) /* DBG_DEV was here */ +#endif + +/* + * Debug levels matching RFC 3164 + */ +#define DBGLVL_ERR 0 /* error conditions */ +#define DBGLVL_WARNING 1 /* warning conditions */ +#define DBGLVL_NOTICE 3 /* normal, but significant, condition */ +#define DBGLVL_INFO 5 /* informational message */ +#define DBGLVL_DEBUG 10 /* debug-level message */ + +#define DBG_STARTUP_NOTICE(...) do { \ + debug_set_forced_log_priority(DBGLVL_NOTICE); \ + D_ERR(__VA_ARGS__); \ + debug_set_forced_log_priority(-1); \ +} while(0) + +#define DBG_ERR(...) DBG_PREFIX(DBGLVL_ERR, (__VA_ARGS__)) +#define DBG_WARNING(...) DBG_PREFIX(DBGLVL_WARNING, (__VA_ARGS__)) +#define DBG_NOTICE(...) DBG_PREFIX(DBGLVL_NOTICE, (__VA_ARGS__)) +#define DBG_INFO(...) DBG_PREFIX(DBGLVL_INFO, (__VA_ARGS__)) +#define DBG_DEBUG(...) DBG_PREFIX(DBGLVL_DEBUG, (__VA_ARGS__)) + +#define DBGC_ERR(dbgc_class, ...) DBGC_PREFIX(dbgc_class, \ + DBGLVL_ERR, (__VA_ARGS__)) +#define DBGC_WARNING(dbgc_class, ...) DBGC_PREFIX(dbgc_class, \ + DBGLVL_WARNING, (__VA_ARGS__)) +#define DBGC_NOTICE(dbgc_class, ...) DBGC_PREFIX(dbgc_class, \ + DBGLVL_NOTICE, (__VA_ARGS__)) +#define DBGC_INFO(dbgc_class, ...) DBGC_PREFIX(dbgc_class, \ + DBGLVL_INFO, (__VA_ARGS__)) +#define DBGC_DEBUG(dbgc_class, ...) DBGC_PREFIX(dbgc_class, \ + DBGLVL_DEBUG, (__VA_ARGS__)) + +#define D_ERR(...) DEBUG(DBGLVL_ERR, (__VA_ARGS__)) +#define D_WARNING(...) DEBUG(DBGLVL_WARNING, (__VA_ARGS__)) +#define D_NOTICE(...) DEBUG(DBGLVL_NOTICE, (__VA_ARGS__)) +#define D_INFO(...) DEBUG(DBGLVL_INFO, (__VA_ARGS__)) +#define D_DEBUG(...) DEBUG(DBGLVL_DEBUG, (__VA_ARGS__)) + +#define DC_ERR(...) DEBUGC(dbgc_class, \ + DBGLVL_ERR, (__VA_ARGS__)) +#define DC_WARNING(...) DEBUGC(dbgc_class, \ + DBGLVL_WARNING, (__VA_ARGS__)) +#define DC_NOTICE(...) DEBUGC(dbgc_class, \ + DBGLVL_NOTICE, (__VA_ARGS__)) +#define DC_INFO(...) DEBUGC(dbgc_class, \ + DBGLVL_INFO, (__VA_ARGS__)) +#define DC_DEBUG(...) DEBUGC(dbgc_class, \ + DBGLVL_DEBUG, (__VA_ARGS__)) + +/* The following definitions come from lib/debug.c */ + +/** + * Possible destinations for the debug log. + * + * Set via setup_logging(); higher values have precedence. + */ +enum debug_logtype { + DEBUG_DEFAULT_STDERR = 0, + DEBUG_DEFAULT_STDOUT = 1, + DEBUG_FILE = 2, + DEBUG_STDOUT = 3, + DEBUG_STDERR = 4, + DEBUG_CALLBACK = 5 +}; + +enum debug_syslog_format { + DEBUG_SYSLOG_FORMAT_NO = 0, + DEBUG_SYSLOG_FORMAT_IN_LOGS = 1, + DEBUG_SYSLOG_FORMAT_ALWAYS = 2, +}; + +struct debug_settings { + size_t max_log_size; + bool timestamp_logs; + bool debug_prefix_timestamp; + bool debug_hires_timestamp; + enum debug_syslog_format debug_syslog_format; + bool debug_pid; + bool debug_uid; + bool debug_class; + bool debug_no_stderr_redirect; +}; + +void setup_logging(const char *prog_name, enum debug_logtype new_logtype); + +void gfree_debugsyms(void); +int debug_add_class(const char *classname); +bool debug_parse_levels(const char *params_str); +void debug_setup_talloc_log(void); +void debug_set_logfile(const char *name); +void debug_set_settings(struct debug_settings *settings, + const char *logging_param, + int syslog_level, bool syslog_only); +void debug_set_hostname(const char *name); +void debug_set_forced_log_priority(int forced_log_priority); +bool reopen_logs_internal( void ); +void force_check_log_size( void ); +bool need_to_check_log_size( void ); +void check_log_size( void ); +void dbgflush( void ); +enum debug_logtype debug_get_log_type(void); +bool debug_get_output_is_stderr(void); +bool debug_get_output_is_stdout(void); +void debug_schedule_reopen_logs(void); +char *debug_list_class_names_and_levels(void); +bool debug_developer_enabled(void); +void debug_developer_enable(void); +void debug_developer_disable(void); + +typedef void (*debug_callback_fn)(void *private_ptr, int level, const char *msg); + +/** + Set a callback for all debug messages. Use in dlz_bind9 to push output to the bind logs + */ +void debug_set_callback(void *private_ptr, debug_callback_fn fn); + +char *debug_get_ringbuf(void); +size_t debug_get_ringbuf_size(void); + +/* Explicitly set new traceid. The old id is returned. */ +uint64_t debug_traceid_set(uint64_t id); + +/* Get the current traceid. */ +uint64_t debug_traceid_get(void); + +size_t *debug_call_depth_addr(void); + +#endif /* _SAMBA_DEBUG_H */ diff --git a/lib/util/debug_s3.c b/lib/util/debug_s3.c new file mode 100644 index 0000000..1fd8637 --- /dev/null +++ b/lib/util/debug_s3.c @@ -0,0 +1,155 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Bartlett 2011 + Copyright (C) Andrew Tridgell 1992-2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "lib/util/server_id.h" +#include "librpc/gen_ndr/messaging.h" +#include "messages.h" +#include "lib/util/memory.h" + +/* This is the Samba3-specific implementation of reopen_logs(), which + * calls out to the s3 loadparm code, and means that we don't depend + * on loadparm directly. */ + +bool reopen_logs(void) +{ + if (lp_loaded()) { + struct debug_settings settings = { + .max_log_size = lp_max_log_size(), + .timestamp_logs = lp_timestamp_logs(), + .debug_prefix_timestamp = lp_debug_prefix_timestamp(), + .debug_hires_timestamp = lp_debug_hires_timestamp(), + .debug_syslog_format = lp_debug_syslog_format(), + .debug_pid = lp_debug_pid(), + .debug_uid = lp_debug_uid(), + .debug_class = lp_debug_class(), + }; + const struct loadparm_substitution *lp_sub = + loadparm_s3_global_substitution(); + + debug_set_logfile(lp_logfile(talloc_tos(), lp_sub)); + debug_parse_levels(lp_log_level(talloc_tos(), lp_sub)); + debug_set_settings(&settings, + lp_logging(talloc_tos(), lp_sub), + lp_syslog(), + lp_syslog_only()); + } else { + /* + * Parameters are not yet loaded - configure debugging with + * reasonable defaults to enable logging for early + * startup failures. + */ + struct debug_settings settings = { + .max_log_size = 5000, + .timestamp_logs = true, + .debug_prefix_timestamp = false, + .debug_hires_timestamp = true, + .debug_syslog_format = false, + .debug_pid = false, + .debug_uid = false, + .debug_class = false, + }; + debug_set_settings(&settings, + "file", + 1, + false); + } + return reopen_logs_internal(); +} + +/**************************************************************************** + Receive a "set debug level" message. +****************************************************************************/ + +void debug_message(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id src, + DATA_BLOB *data) +{ + const char *params_str = (const char *)data->data; + + /* Check, it's a proper string! */ + if (params_str[(data->length)-1] != '\0') { + DEBUG(1, ("Invalid debug message from pid %u to pid %u\n", + (unsigned int)procid_to_pid(&src), + (unsigned int)getpid())); + return; + } + + DEBUG(3, ("INFO: Remote set of debug to `%s' (pid %u from pid %u)\n", + params_str, (unsigned int)getpid(), + (unsigned int)procid_to_pid(&src))); + + debug_parse_levels(params_str); +} + +/**************************************************************************** + Return current debug level. +****************************************************************************/ + +static void debuglevel_message(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id src, + DATA_BLOB *data) +{ + char *message = debug_list_class_names_and_levels(); + struct server_id_buf tmp; + + if (!message) { + DEBUG(0,("debuglevel_message - debug_list_class_names_and_levels returned NULL\n")); + return; + } + + DEBUG(1, ("INFO: Received REQ_DEBUGLEVEL message from PID %s\n", + server_id_str_buf(src, &tmp))); + messaging_send_buf(msg_ctx, src, MSG_DEBUGLEVEL, + (uint8_t *)message, strlen(message) + 1); + + TALLOC_FREE(message); +} + +static void debug_ringbuf_log(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id src, + DATA_BLOB *data) +{ + char *log = debug_get_ringbuf(); + size_t logsize = debug_get_ringbuf_size(); + + if (log == NULL) { + log = discard_const_p(char, "*disabled*\n"); + logsize = strlen(log) + 1; + } + + messaging_send_buf(msg_ctx, src, MSG_RINGBUF_LOG, (uint8_t *)log, + logsize); +} + +void debug_register_msgs(struct messaging_context *msg_ctx) +{ + messaging_register(msg_ctx, NULL, MSG_DEBUG, debug_message); + messaging_register(msg_ctx, NULL, MSG_REQ_DEBUGLEVEL, + debuglevel_message); + messaging_register(msg_ctx, NULL, MSG_REQ_RINGBUF_LOG, + debug_ringbuf_log); +} diff --git a/lib/util/debug_s3.h b/lib/util/debug_s3.h new file mode 100644 index 0000000..9e5211b --- /dev/null +++ b/lib/util/debug_s3.h @@ -0,0 +1,26 @@ +/* + Unix SMB/CIFS implementation. + SMB debug stuff + Copyright (C) Andrew Tridgell 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "librpc/gen_ndr/server_id.h" + +struct messaging_context; +struct server_id; +void debug_message(struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, struct server_id src, DATA_BLOB *data); +void debug_register_msgs(struct messaging_context *msg_ctx); +bool reopen_logs( void ); diff --git a/lib/util/discard.h b/lib/util/discard.h new file mode 100644 index 0000000..d2b74ac --- /dev/null +++ b/lib/util/discard.h @@ -0,0 +1,51 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1999 + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_DISCARD_H_ +#define _SAMBA_DISCARD_H_ + +/** + this is a warning hack. The idea is to use this everywhere that we + get the "discarding const" warning from gcc. That doesn't actually + fix the problem of course, but it means that when we do get to + cleaning them up we can do it by searching the code for + discard_const. + + It also means that other error types aren't as swamped by the noise + of hundreds of const warnings, so we are more likely to notice when + we get new errors. + + Please only add more uses of this macro when you find it + _really_ hard to fix const warnings. Our aim is to eventually use + this function in only a very few places. + + Also, please call this via the discard_const_p() macro interface, as that + makes the return type safe. +*/ +#ifndef discard_const +#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) +#endif + +/** Type-safe version of discard_const */ +#ifndef discard_const_p +#define discard_const_p(type, ptr) ((type *)discard_const(ptr)) +#endif + +#endif /* _SAMBA_DISCARD_H_ */ diff --git a/lib/util/dlinklist.h b/lib/util/dlinklist.h new file mode 100644 index 0000000..49a135a --- /dev/null +++ b/lib/util/dlinklist.h @@ -0,0 +1,198 @@ +/* + Unix SMB/CIFS implementation. + some simple double linked list macros + + Copyright (C) Andrew Tridgell 1998-2010 + + ** NOTE! The following LGPL license applies to this file (*dlinklist.h). + ** This does NOT imply that all of Samba is released under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +/* To use these macros you must have a structure containing a next and + prev pointer */ + +#ifndef _DLINKLIST_H +#define _DLINKLIST_H + +/* + February 2010 - changed list format to have a prev pointer from the + list head. This makes DLIST_ADD_END() O(1) even though we only have + one list pointer. + + The scheme is as follows: + + 1) with no entries in the list: + list_head == NULL + + 2) with 1 entry in the list: + list_head->next == NULL + list_head->prev == list_head + + 3) with 2 entries in the list: + list_head->next == element2 + list_head->prev == element2 + element2->prev == list_head + element2->next == NULL + + 4) with N entries in the list: + list_head->next == element2 + list_head->prev == elementN + elementN->prev == element{N-1} + elementN->next == NULL + + This allows us to find the tail of the list by using + list_head->prev, which means we can add to the end of the list in + O(1) time + */ + + +/* + add an element at the front of a list +*/ +#define DLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (p)->prev = (list) = (p); \ + (p)->next = NULL; \ + } else { \ + (p)->prev = (list)->prev; \ + (list)->prev = (p); \ + (p)->next = (list); \ + (list) = (p); \ + } \ +} while (0) + +/* + remove an element from a list + Note that the element doesn't have to be in the list. If it + isn't then this is a no-op +*/ +#define DLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + (list) = (p)->next; \ + } else if ((p)->prev && (list) && (p) == (list)->prev) { \ + (p)->prev->next = NULL; \ + (list)->prev = (p)->prev; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) != (list)) (p)->next = (p)->prev = NULL; \ +} while (0) + +/* + find the head of the list given any element in it. + Note that this costs O(N), so you should avoid this macro + if at all possible! +*/ +#define DLIST_HEAD(p, result_head) \ +do { \ + (result_head) = (p); \ + while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \ +} while(0) + +/* return the last element in the list */ +#define DLIST_TAIL(list) ((list)?(list)->prev:NULL) + +/* return the previous element in the list. */ +#define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL) + +/* insert 'p' after the given element 'el' in a list. If el is NULL then + this is the same as a DLIST_ADD() */ +#define DLIST_ADD_AFTER(list, p, el) \ +do { \ + if (!(list) || !(el)) { \ + DLIST_ADD(list, p); \ + } else { \ + (p)->prev = (el); \ + (p)->next = (el)->next; \ + (el)->next = (p); \ + if ((p)->next) (p)->next->prev = (p); \ + if ((list)->prev == (el)) (list)->prev = (p); \ + }\ +} while (0) + + +/* + add to the end of a list. +*/ +#define DLIST_ADD_END(list, p) \ +do { \ + if (!(list)) { \ + DLIST_ADD(list, p); \ + } else { \ + DLIST_ADD_AFTER(list, p, (list)->prev); \ + } \ +} while (0) + +/* promote an element to the front of a list */ +#define DLIST_PROMOTE(list, p) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD(list, p); \ +} while (0) + +/* + demote an element to the end of a list. +*/ +#define DLIST_DEMOTE(list, p) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD_END(list, p); \ +} while (0) + +/* + * like DLIST_DEMOTE(), but optimized + * for short lists with 0, 1 or 2 elements + */ +#define DLIST_DEMOTE_SHORT(list, p) \ +do { \ + if ((list) == NULL) { \ + /* no reason to demote, just add */ \ + DLIST_ADD(list, p); \ + } else if ((list)->prev == (p)) { \ + /* optimize if p is last */ \ + } else if ((list) == (p)) { \ + /* optimize if p is first */ \ + (list)->prev->next = (p); \ + (list) = (p)->next; \ + (p)->next = NULL; \ + } else { \ + DLIST_DEMOTE(list, p); \ + } \ +} while (0) + +/* + concatenate two lists - putting all elements of the 2nd list at the + end of the first list. +*/ +#define DLIST_CONCATENATE(list1, list2) \ +do { \ + if (!(list1)) { \ + (list1) = (list2); \ + } else { \ + (list1)->prev->next = (list2); \ + if (list2) { \ + void *_tmplist = (void *)(list1)->prev; \ + (list1)->prev = (list2)->prev; \ + (list2)->prev = _tmplist; \ + } \ + } \ +} while (0) + +#endif /* _DLINKLIST_H */ diff --git a/lib/util/dprintf.c b/lib/util/dprintf.c new file mode 100644 index 0000000..9d1573f --- /dev/null +++ b/lib/util/dprintf.c @@ -0,0 +1,80 @@ +/* + Unix SMB/CIFS implementation. + display print functions + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + + +/* + this module provides functions for printing internal strings in the + "display charset". + + This charset may be quite different from the chosen unix charset. + + Eventually these functions will need to take care of column count constraints + + The d_ prefix on print functions in Samba refers to the display character set + conversion +*/ + +#include "replace.h" +#include "system/locale.h" +#include "lib/util/samba_util.h" + +static int d_vfprintf(FILE *f, const char *format, va_list ap) + PRINTF_ATTRIBUTE(2,0); + +static int d_vfprintf(FILE *f, const char *format, va_list ap) +{ + return vfprintf(f, format, ap); +} + + +_PUBLIC_ int d_fprintf(FILE *f, const char *format, ...) +{ + int ret; + va_list ap; + + va_start(ap, format); + ret = d_vfprintf(f, format, ap); + va_end(ap); + + return ret; +} + +static FILE *outfile; + +_PUBLIC_ int d_printf(const char *format, ...) +{ + int ret; + va_list ap; + + if (!outfile) outfile = stdout; + + va_start(ap, format); + ret = d_vfprintf(outfile, format, ap); + va_end(ap); + + return ret; +} + +/* interactive programs need a way of tell d_*() to write to stderr instead + of stdout */ +void display_set_stderr(void) +{ + outfile = stderr; +} diff --git a/lib/util/fault.c b/lib/util/fault.c new file mode 100644 index 0000000..10c3720 --- /dev/null +++ b/lib/util/fault.c @@ -0,0 +1,318 @@ +/* + Unix SMB/CIFS implementation. + Critical Fault handling + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Tim Prouty 2009 + Copyright (C) James Peach 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/wait.h" +#include "version.h" + +#ifdef HAVE_SYS_SYSCTL_H +#include <sys/sysctl.h> +#endif + + +#ifdef HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif + +#include "debug.h" +#include "lib/util/signal.h" /* Avoid /usr/include/signal.h */ +#include "fault.h" +#include "util_process.h" + +static struct { + bool disabled; + smb_panic_handler_t panic_handler; +} fault_state; + + +/******************************************************************* +setup variables used for fault handling +********************************************************************/ +void fault_configure(smb_panic_handler_t panic_handler) +{ + fault_state.panic_handler = panic_handler; +} + + +/** + disable setting up fault handlers + This is used for the bind9 dlz module, as we + don't want a Samba module in bind9 to override the bind + fault handling +**/ +_PUBLIC_ void fault_setup_disable(void) +{ + fault_state.disabled = true; +} + + +#if !defined(HAVE_DISABLE_FAULT_HANDLING) +/******************************************************************* +report a fault +********************************************************************/ +static void fault_report(int sig) +{ + static int counter; + char signal_string[128]; + + if (counter) _exit(1); + + counter++; + + snprintf(signal_string, sizeof(signal_string), + "Signal %d: %s", sig, strsignal(sig)); + smb_panic(signal_string); + + /* smb_panic() never returns, so this is really redundant */ + exit(1); +} + +/**************************************************************************** +catch serious errors +****************************************************************************/ +static void sig_fault(int sig) +{ + fault_report(sig); +} +#endif +/******************************************************************* +setup our fault handlers +********************************************************************/ +void fault_setup(void) +{ + if (fault_state.disabled) { + return; + } +#if !defined(HAVE_DISABLE_FAULT_HANDLING) +#ifdef SIGSEGV + CatchSignal(SIGSEGV, sig_fault); +#endif +#ifdef SIGBUS + CatchSignal(SIGBUS, sig_fault); +#endif +#ifdef SIGABRT + CatchSignal(SIGABRT, sig_fault); +#endif +#endif +} + +_PUBLIC_ const char *panic_action = NULL; + +/* + default smb_panic() implementation +*/ +static void smb_panic_default(const char *why) _NORETURN_; +static void smb_panic_default(const char *why) +{ +#if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER) + /* + * Make sure all children can attach a debugger. + */ + prctl(PR_SET_PTRACER, getpid(), 0, 0, 0); +#endif + + if (panic_action && *panic_action) { + char cmdstring[200]; + if (strlcpy(cmdstring, panic_action, sizeof(cmdstring)) < sizeof(cmdstring)) { + int result; + char pidstr[20]; + char subst[200]; + char *p = NULL; + snprintf(pidstr, sizeof(pidstr), "%d", (int) getpid()); + + p = strstr(cmdstring, "%d"); + if (p != NULL) { + snprintf(subst, + sizeof(subst), + "%.*s%s%s", + (int)(p-cmdstring), + cmdstring, + pidstr, + p+2); + strlcpy(cmdstring, subst, sizeof(cmdstring)); + } + + DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmdstring)); + result = system(cmdstring); + + if (result == -1) + DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n", + strerror(errno))); + else + DEBUG(0, ("smb_panic(): action returned status %d\n", + WEXITSTATUS(result))); + } + } + +#ifdef SIGABRT + CatchSignal(SIGABRT, SIG_DFL); +#endif + abort(); +} + +_PUBLIC_ void smb_panic_log(const char *why) +{ + const char *binary_name = process_get_saved_binary_name(); + const char *short_title = process_get_short_title(); + const char *long_title = process_get_long_title(); + + DEBUGSEP(0); + DEBUG(0,("INTERNAL ERROR: %s in %s (%s) (%s) pid %lld (%s)\n", + why, + binary_name, + short_title, + long_title, + (unsigned long long)getpid(), + SAMBA_VERSION_STRING)); + DEBUG(0,("If you are running a recent Samba version, and " + "if you think this problem is not yet fixed in the " + "latest versions, please consider reporting this " + "bug, see " + "https://wiki.samba.org/index.php/Bug_Reporting\n")); + DEBUGSEP(0); + DEBUG(0,("PANIC (pid %llu): %s in " SAMBA_VERSION_STRING "\n", + (unsigned long long)getpid(), why)); + + log_stack_trace(); +} + +/** + Something really nasty happened - panic ! + + This function is in this file to allow sharing the last set process + title into the logs before the backtrace +**/ +_PUBLIC_ void smb_panic(const char *why) +{ + smb_panic_log(why); + + if (fault_state.panic_handler) { + fault_state.panic_handler(why); + _exit(1); + } + smb_panic_default(why); +} + +/******************************************************************* + Print a backtrace of the stack to the debug log. This function + DELIBERATELY LEAKS MEMORY. The expectation is that you should + exit shortly after calling it. +********************************************************************/ + +/* Buffer size to use when printing backtraces */ +#define BACKTRACE_STACK_SIZE 64 + + +#ifdef HAVE_LIBUNWIND_H +#include <libunwind.h> +#endif + +#ifdef HAVE_EXECINFO_H +#include <execinfo.h> +#endif + +void log_stack_trace(void) +{ +#ifdef HAVE_LIBUNWIND + /* + * --with-libunwind is required to use libunwind, the + * backtrace_symbols() code below is the default. + * + * This code is available because a previous version of this + * comment asserted that on ia64 libunwind correctly walks the + * stack in more circumstances than backtrace. + */ + unw_cursor_t cursor; + unw_context_t uc; + unsigned i = 0; + + char procname[256]; + unw_word_t ip, sp, off; + + procname[sizeof(procname) - 1] = '\0'; + + if (unw_getcontext(&uc) != 0) { + goto libunwind_failed; + } + + if (unw_init_local(&cursor, &uc) != 0) { + goto libunwind_failed; + } + + DEBUG(0, ("BACKTRACE:\n")); + + do { + ip = sp = 0; + unw_get_reg(&cursor, UNW_REG_IP, &ip); + unw_get_reg(&cursor, UNW_REG_SP, &sp); + + switch (unw_get_proc_name(&cursor, + procname, sizeof(procname) - 1, &off) ) { + case 0: + /* Name found. */ + case -UNW_ENOMEM: + /* Name truncated. */ + DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n", + i, procname, (long long)off, + (long long)ip, (long long) sp)); + break; + default: + /* case -UNW_ENOINFO: */ + /* case -UNW_EUNSPEC: */ + /* No symbol name found. */ + DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n", + i, "<unknown symbol>", + (long long)ip, (long long) sp)); + } + ++i; + } while (unw_step(&cursor) > 0); + + return; + +libunwind_failed: + DEBUG(0, ("unable to produce a stack trace with libunwind\n")); + +#elif defined(HAVE_BACKTRACE_SYMBOLS) + void *backtrace_stack[BACKTRACE_STACK_SIZE]; + size_t backtrace_size; + char **backtrace_strings; + + /* get the backtrace (stack frames) */ + backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE); + backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size); + + DEBUG(0, ("BACKTRACE: %lu stack frames:\n", + (unsigned long)backtrace_size)); + + if (backtrace_strings) { + size_t i; + + for (i = 0; i < backtrace_size; i++) + DEBUGADD(0, (" #%zu %s\n", i, backtrace_strings[i])); + + /* Leak the backtrace_strings, rather than risk what free() might do */ + } + +#else + DEBUG(0, ("unable to produce a stack trace on this platform\n")); +#endif +} diff --git a/lib/util/fault.h b/lib/util/fault.h new file mode 100644 index 0000000..6aceaf6 --- /dev/null +++ b/lib/util/fault.h @@ -0,0 +1,59 @@ +/* + Unix SMB/CIFS implementation. + Critical Fault handling + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Tim Prouty 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_FAULT_H_ +#define _SAMBA_FAULT_H_ + +#include <sys/types.h> + +#include "attr.h" + +/* Please include header file debug.h if you want to use macro SMB_ASSERT */ + +/** + * assert macros + */ +#ifdef _SAMBA_DEBUG_H +#define SMB_ASSERT(b) \ +do { \ + if (unlikely(!(b))) { \ + DEBUG(0,("PANIC: assert failed at %s(%d): %s\n", \ + __FILE__, __LINE__, #b)); \ + smb_panic("assert failed: " #b); \ + } \ +} while(0) +#endif /* _SAMBA_DEBUG_H */ + +extern const char *panic_action; + +/** + Something really nasty happened - panic ! +**/ +typedef void (*smb_panic_handler_t)(const char *why); + +void fault_configure(smb_panic_handler_t panic_handler); +void fault_setup(void); +void fault_setup_disable(void); +_NORETURN_ void smb_panic(const char *reason); +void smb_panic_log(const char *reason); + +void log_stack_trace(void); + +#endif /* _SAMBA_FAULT_H_ */ diff --git a/lib/util/fsusage.c b/lib/util/fsusage.c new file mode 100644 index 0000000..d769b45 --- /dev/null +++ b/lib/util/fsusage.c @@ -0,0 +1,160 @@ +/* + Unix SMB/CIFS implementation. + functions to calculate the free disk space + Copyright (C) Andrew Tridgell 1998-2000 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "lib/util/samba_util.h" +#include "system/filesys.h" + +/** + * @file + * @brief Utility functions for getting the amount of free disk space + */ + +/* Return the number of TOSIZE-byte blocks used by + BLOCKS FROMSIZE-byte blocks, rounding away from zero. +*/ +static uint64_t adjust_blocks(uint64_t blocks, uint64_t fromsize, uint64_t tosize) +{ + if (fromsize == tosize) { /* e.g., from 512 to 512 */ + return blocks; + } else if (fromsize > tosize) { /* e.g., from 2048 to 512 */ + return blocks * (fromsize / tosize); + } else { /* e.g., from 256 to 512 */ + /* Protect against broken filesystems... */ + if (fromsize == 0) { + fromsize = tosize; + } + return (blocks + 1) / (tosize / fromsize); + } +} + +/** + * Retrieve amount of free disk space. + * this does all of the system specific guff to get the free disk space. + * It is derived from code in the GNU fileutils package, but has been + * considerably mangled for use here + * + * results are returned in *dfree and *dsize, in 512 byte units +*/ +_PUBLIC_ int sys_fsusage(const char *path, uint64_t *dfree, uint64_t *dsize) +{ +#ifdef STAT_STATFS3_OSF1 +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512) + struct statfs fsd; + + if (statfs (path, &fsd, sizeof (struct statfs)) != 0) + return -1; +#endif /* STAT_STATFS3_OSF1 */ + +#ifdef STAT_STATFS2_FS_DATA /* Ultrix */ +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)1024, (uint64_t)512) + struct fs_data fsd; + + if (statfs (path, &fsd) != 1) + return -1; + + (*dsize) = CONVERT_BLOCKS (fsd.fd_req.btot); + (*dfree) = CONVERT_BLOCKS (fsd.fd_req.bfreen); +#endif /* STAT_STATFS2_FS_DATA */ + +#ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */ +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512) + struct statfs fsd; + + if (statfs (path, &fsd) < 0) + return -1; + +#ifdef STATFS_TRUNCATES_BLOCK_COUNTS + /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the + struct statfs are truncated to 2GB. These conditions detect that + truncation, presumably without botching the 4.1.1 case, in which + the values are not truncated. The correct counts are stored in + undocumented spare fields. */ + if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0) { + fsd.f_blocks = fsd.f_spare[0]; + fsd.f_bfree = fsd.f_spare[1]; + fsd.f_bavail = fsd.f_spare[2]; + } +#endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ +#endif /* STAT_STATFS2_BSIZE */ + + +#ifdef STAT_STATFS2_FSIZE /* 4.4BSD */ +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512) + + struct statfs fsd; + + if (statfs (path, &fsd) < 0) + return -1; +#endif /* STAT_STATFS2_FSIZE */ + +#ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */ +# if _AIX || defined(_CRAY) +# define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512) +# ifdef _CRAY +# define f_bavail f_bfree +# endif +# else +# define CONVERT_BLOCKS(B) ((uint64_t)B) +# ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx */ +# ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */ +# define f_bavail f_bfree +# endif +# endif +# endif + + struct statfs fsd; + + if (statfs (path, &fsd, sizeof fsd, 0) < 0) + return -1; + /* Empirically, the block counts on most SVR3 and SVR3-derived + systems seem to always be in terms of 512-byte blocks, + no matter what value f_bsize has. */ + +#endif /* STAT_STATFS4 */ + +#if defined(STAT_STATVFS) /* SVR4 */ +#ifdef HAVE_FRSIZE +# define CONVERT_BLOCKS(B) \ + adjust_blocks ((uint64_t)(B), fsd.f_frsize ? (uint64_t)fsd.f_frsize : (uint64_t)fsd.f_bsize, (uint64_t)512) +#else +# define CONVERT_BLOCKS(B) \ + adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512) +#endif + + struct statvfs fsd; + if (statvfs(path, &fsd) < 0) return -1; + + /* f_frsize isn't guaranteed to be supported. */ + +#endif /* STAT_STATVFS */ + +#ifndef CONVERT_BLOCKS + /* we don't have any dfree code! */ + return -1; +#else +#if !defined(STAT_STATFS2_FS_DATA) + /* !Ultrix */ + (*dsize) = CONVERT_BLOCKS (fsd.f_blocks); + (*dfree) = CONVERT_BLOCKS (fsd.f_bavail); +#endif /* not STAT_STATFS2_FS_DATA */ +#endif + + return 0; +} diff --git a/lib/util/genrand.c b/lib/util/genrand.c new file mode 100644 index 0000000..d0b49db --- /dev/null +++ b/lib/util/genrand.c @@ -0,0 +1,87 @@ +/* + Unix SMB/CIFS implementation. + + Functions to create reasonable random numbers for crypto use. + + Copyright (C) Jeremy Allison 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "lib/util/fault.h" +#include "lib/util/genrand.h" + +#include <gnutls/gnutls.h> +#include <gnutls/crypto.h> + +/* + * Details about the GnuTLS CSPRNG: + * + * https://nikmav.blogspot.com/2017/03/improving-by-simplifying-gnutls-prng.html + */ + + +_NORETURN_ static void genrand_panic(int err, + const char *location, + const char *func) +{ + char buf[200]; + snprintf(buf, sizeof(buf), + "%s:%s: GnuTLS could not generate a random buffer: %s [%d]\n", + location, func, gnutls_strerror_name(err), err); + smb_panic(buf); +} + + +_PUBLIC_ void generate_random_buffer(uint8_t *out, size_t len) +{ + /* Random number generator for temporary keys. */ + int ret = gnutls_rnd(GNUTLS_RND_RANDOM, out, len); + if (ret != 0) { + genrand_panic(ret, __location__, __func__); + } +} + +_PUBLIC_ void generate_secret_buffer(uint8_t *out, size_t len) +{ + /* + * Random number generator for long term keys. + * + * The key generator, will re-seed after a fixed amount of bytes is + * generated (typically less than the nonce), and will also re-seed + * based on time, i.e., after few hours of operation without reaching + * the limit for a re-seed. For its re-seed it mixes data obtained + * from the OS random device with the previous key. + */ + int ret = gnutls_rnd(GNUTLS_RND_KEY, out, len); + if (ret != 0) { + genrand_panic(ret, __location__, __func__); + } +} + +_PUBLIC_ void generate_nonce_buffer(uint8_t *out, size_t len) +{ + /* + * Random number generator for nonce and initialization vectors. + * + * The nonce generator will reseed after outputting a fixed amount of + * bytes (typically few megabytes), or after few hours of operation + * without reaching the limit has passed. + */ + int ret = gnutls_rnd(GNUTLS_RND_NONCE, out, len); + if (ret != 0) { + genrand_panic(ret, __location__, __func__); + } +} diff --git a/lib/util/genrand.h b/lib/util/genrand.h new file mode 100644 index 0000000..76e9b98 --- /dev/null +++ b/lib/util/genrand.h @@ -0,0 +1,49 @@ +/* + Unix SMB/CIFS implementation. + + Functions to create reasonable random numbers for crypto use. + + Copyright (C) Jeremy Allison 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + * @brief Generate random values for session and temporary keys. + * + * @param[in] out A pointer to the buffer to fill with random data. + * + * @param[in] len The size of the buffer to fill. + */ +void generate_random_buffer(uint8_t *out, size_t len); + +/** + * @brief Generate random values for long term keys and passwords. + * + * @param[in] out A pointer to the buffer to fill with random data. + * + * @param[in] len The size of the buffer to fill. + */ +void generate_secret_buffer(uint8_t *out, size_t len); + +/** + * @brief Generate random values for a nonce buffer. + * + * This is also known as initialization vector. + * + * @param[in] out A pointer to the buffer to fill with random data. + * + * @param[in] len The size of the buffer to fill. + */ +void generate_nonce_buffer(uint8_t *out, size_t len); diff --git a/lib/util/genrand_util.c b/lib/util/genrand_util.c new file mode 100644 index 0000000..43005c5 --- /dev/null +++ b/lib/util/genrand_util.c @@ -0,0 +1,531 @@ +/* + Unix SMB/CIFS implementation. + + Functions to create reasonable random numbers for crypto use. + + Copyright (C) Jeremy Allison 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/locale.h" +#include <tevent.h> +#include "lib/util/samba_util.h" +#include "lib/util/debug.h" + +/** + * @file + * @brief Random number generation + */ + +/** + generate a single random uint32_t +**/ +_PUBLIC_ uint32_t generate_random(void) +{ + uint8_t v[4]; + generate_random_buffer(v, 4); + return IVAL(v, 0); +} + +/** + @brief generate a random uint64 +**/ +_PUBLIC_ uint64_t generate_random_u64(void) +{ + uint8_t v[8]; + generate_random_buffer(v, 8); + return BVAL(v, 0); +} + +/** + * @brief Generate a random number in the given range. + * + * @param lower The lower value of the range + + * @param upper The upper value of the range + * + * @return A random number bigger than than lower and smaller than upper. + */ +_PUBLIC_ uint64_t generate_random_u64_range(uint64_t lower, uint64_t upper) +{ + return generate_random_u64() % (upper - lower) + lower; +} + +_PUBLIC_ uint64_t generate_unique_u64(uint64_t veto_value) +{ + static struct generate_unique_u64_state { + uint64_t next_value; + int pid; + } generate_unique_u64_state; + + int pid = tevent_cached_getpid(); + + if (unlikely(pid != generate_unique_u64_state.pid)) { + generate_unique_u64_state = (struct generate_unique_u64_state) { + .pid = pid, + .next_value = veto_value, + }; + } + + while (unlikely(generate_unique_u64_state.next_value == veto_value)) { + generate_nonce_buffer( + (void *)&generate_unique_u64_state.next_value, + sizeof(generate_unique_u64_state.next_value)); + } + + return generate_unique_u64_state.next_value++; +} + +/** + Microsoft composed the following rules (among others) for quality + checks. This is an abridgment from + http://msdn.microsoft.com/en-us/subscriptions/cc786468%28v=ws.10%29.aspx: + + Passwords must contain characters from three of the following five + categories: + + - Uppercase characters of European languages (A through Z, with + diacritic marks, Greek and Cyrillic characters) + - Lowercase characters of European languages (a through z, sharp-s, + with diacritic marks, Greek and Cyrillic characters) + - Base 10 digits (0 through 9) + - Nonalphanumeric characters: ~!@#$%^&*_-+=`|\(){}[]:;"'<>,.?/ + - Any Unicode character that is categorized as an alphabetic character + but is not uppercase or lowercase. This includes Unicode characters + from Asian languages. + + Note: for now do not check if the unicode category is + alphabetic character +**/ +_PUBLIC_ bool check_password_quality(const char *pwd) +{ + size_t ofs = 0; + size_t num_digits = 0; + size_t num_upper = 0; + size_t num_lower = 0; + size_t num_nonalpha = 0; + size_t num_unicode = 0; + size_t num_categories = 0; + + if (pwd == NULL) { + return false; + } + + while (true) { + const char *s = &pwd[ofs]; + size_t len = 0; + codepoint_t c; + + c = next_codepoint(s, &len); + if (c == INVALID_CODEPOINT) { + return false; + } else if (c == 0) { + break; + } + ofs += len; + + if (len == 1) { + const char *na = "~!@#$%^&*_-+=`|\\(){}[]:;\"'<>,.?/"; + + if (isdigit(c)) { + num_digits += 1; + continue; + } + + if (isupper(c)) { + num_upper += 1; + continue; + } + + if (islower(c)) { + num_lower += 1; + continue; + } + + if (strchr(na, c)) { + num_nonalpha += 1; + continue; + } + + /* + * the rest does not belong to + * a category. + */ + continue; + } + + if (isupper_m(c)) { + num_upper += 1; + continue; + } + + if (islower_m(c)) { + num_lower += 1; + continue; + } + + /* + * Note: for now do not check if the unicode category is + * alphabetic character + * + * We would have to import the details from + * ftp://ftp.unicode.org/Public/6.3.0/ucd/UnicodeData-6.3.0d1.txt + */ + num_unicode += 1; + continue; + } + + if (num_digits > 0) { + num_categories += 1; + } + if (num_upper > 0) { + num_categories += 1; + } + if (num_lower > 0) { + num_categories += 1; + } + if (num_nonalpha > 0) { + num_categories += 1; + } + if (num_unicode > 0) { + num_categories += 1; + } + + if (num_categories >= 3) { + return true; + } + + return false; +} + +/** + Use the random number generator to generate a random string. +**/ + +_PUBLIC_ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list) +{ + size_t i; + size_t list_len = strlen(list); + + char *retstr = talloc_array(mem_ctx, char, len + 1); + if (!retstr) return NULL; + + generate_secret_buffer((uint8_t *)retstr, len); + for (i = 0; i < len; i++) { + retstr[i] = list[retstr[i] % list_len]; + } + retstr[i] = '\0'; + + return retstr; +} + +/** + * Generate a random text string consisting of the specified length. + * The returned string will be allocated. + * + * Characters used are: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#., + */ + +_PUBLIC_ char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len) +{ + char *retstr; + const char *c_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,"; + +again: + retstr = generate_random_str_list(mem_ctx, len, c_list); + if (!retstr) return NULL; + + /* we need to make sure the random string passes basic quality tests + or it might be rejected by windows as a password */ + if (len >= 7 && !check_password_quality(retstr)) { + talloc_free(retstr); + goto again; + } + + return retstr; +} + +/** + * Generate a random text password (based on printable ascii characters). + */ + +_PUBLIC_ char *generate_random_password(TALLOC_CTX *mem_ctx, size_t min, size_t max) +{ + char *retstr; + /* This list does not include { or } because they cause + * problems for our provision (it can create a substring + * ${...}, and for Fedora DS (which treats {...} at the start + * of a stored password as special + * -- Andrew Bartlett 2010-03-11 + */ + const char *c_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,@$%&!?:;<=>()[]~"; + size_t len = max; + size_t diff; + + if (min > max) { + errno = EINVAL; + return NULL; + } + + diff = max - min; + + if (diff > 0 ) { + size_t tmp; + + generate_secret_buffer((uint8_t *)&tmp, sizeof(tmp)); + + tmp %= diff; + + len = min + tmp; + } + +again: + retstr = generate_random_str_list(mem_ctx, len, c_list); + if (!retstr) return NULL; + + /* we need to make sure the random string passes basic quality tests + or it might be rejected by windows as a password */ + if (len >= 7 && !check_password_quality(retstr)) { + talloc_free(retstr); + goto again; + } + + return retstr; +} + +/** + * Generate a random machine password (based on random utf16 characters, + * converted to utf8). min must be at least 14, max must be at most 255. + * + * If 'unix charset' is not utf8, the password consist of random ascii + * values! + * + * The return value is a talloc string with destructor talloc_keep_secret() set. + * The content will be overwritten by zeros when the mem_ctx is destroyed. + */ + +_PUBLIC_ char *generate_random_machine_password(TALLOC_CTX *mem_ctx, size_t min, size_t max) +{ + TALLOC_CTX *frame = NULL; + struct generate_random_machine_password_state { + uint8_t password_buffer[256 * 2]; + uint8_t tmp; + } *state; + char *new_pw = NULL; + size_t len = max; + char *utf8_pw = NULL; + size_t utf8_len = 0; + char *unix_pw = NULL; + size_t unix_len = 0; + size_t diff; + size_t i; + bool ok; + int cmp; + + if (max > 255) { + errno = EINVAL; + return NULL; + } + + if (min < 14) { + errno = EINVAL; + return NULL; + } + + if (min > max) { + errno = EINVAL; + return NULL; + } + + frame = talloc_stackframe_pool(2048); + state = talloc_zero(frame, struct generate_random_machine_password_state); + talloc_keep_secret(state); + + diff = max - min; + + if (diff > 0) { + size_t tmp; + + generate_secret_buffer((uint8_t *)&tmp, sizeof(tmp)); + + tmp %= diff; + + len = min + tmp; + } + + /* + * Create a random machine account password + * We create a random buffer and convert that to utf8. + * This is similar to what windows is doing. + * + * In future we may store the raw random buffer, + * but for now we need to pass the password as + * char pointer through some layers. + * + * As most kerberos keys are derived from the + * utf8 password we need to fallback to + * ASCII passwords if "unix charset" is not utf8. + */ + generate_secret_buffer(state->password_buffer, len * 2); + for (i = 0; i < len; i++) { + size_t idx = i*2; + uint16_t c; + + /* + * both MIT krb5 and HEIMDAL only + * handle codepoints up to 0xffff. + * + * It means we need to avoid + * 0xD800 - 0xDBFF (high surrogate) + * and + * 0xDC00 - 0xDFFF (low surrogate) + * in the random utf16 data. + * + * 55296 0xD800 0154000 0b1101100000000000 + * 57343 0xDFFF 0157777 0b1101111111111111 + * 8192 0x2000 020000 0b10000000000000 + * + * The above values show that we can check + * for 0xD800 and just add 0x2000 to avoid + * the surrogate ranges. + * + * The rest will be handled by CH_UTF16MUNGED + * see utf16_munged_pull(). + */ + c = SVAL(state->password_buffer, idx); + if (c & 0xD800) { + c |= 0x2000; + } + SSVAL(state->password_buffer, idx, c); + } + ok = convert_string_talloc(frame, + CH_UTF16MUNGED, CH_UTF8, + state->password_buffer, len * 2, + (void *)&utf8_pw, &utf8_len); + if (!ok) { + DEBUG(0, ("%s: convert_string_talloc() failed\n", + __func__)); + TALLOC_FREE(frame); + return NULL; + } + talloc_keep_secret(utf8_pw); + + ok = convert_string_talloc(frame, + CH_UTF16MUNGED, CH_UNIX, + state->password_buffer, len * 2, + (void *)&unix_pw, &unix_len); + if (!ok) { + goto ascii_fallback; + } + talloc_keep_secret(unix_pw); + + if (utf8_len != unix_len) { + goto ascii_fallback; + } + + cmp = memcmp((const uint8_t *)utf8_pw, + (const uint8_t *)unix_pw, + utf8_len); + if (cmp != 0) { + goto ascii_fallback; + } + + new_pw = talloc_strdup(mem_ctx, utf8_pw); + if (new_pw == NULL) { + TALLOC_FREE(frame); + return NULL; + } + talloc_keep_secret(new_pw); + talloc_set_name_const(new_pw, __func__); + TALLOC_FREE(frame); + return new_pw; + +ascii_fallback: + for (i = 0; i < len; i++) { + /* + * truncate to ascii + */ + state->tmp = state->password_buffer[i] & 0x7f; + if (state->tmp == 0) { + state->tmp = state->password_buffer[i] >> 1; + } + if (state->tmp == 0) { + state->tmp = 0x01; + } + state->password_buffer[i] = state->tmp; + } + state->password_buffer[i] = '\0'; + + new_pw = talloc_strdup(mem_ctx, (const char *)state->password_buffer); + if (new_pw == NULL) { + TALLOC_FREE(frame); + return NULL; + } + talloc_keep_secret(new_pw); + talloc_set_name_const(new_pw, __func__); + TALLOC_FREE(frame); + return new_pw; +} + +/** + * Generate an array of unique text strings all of the same length. + * The returned string will be allocated. + * Returns NULL if the number of unique combinations cannot be created. + * + * Characters used are: abcdefghijklmnopqrstuvwxyz0123456789+_-#., + */ +_PUBLIC_ char** generate_unique_strs(TALLOC_CTX *mem_ctx, size_t len, + uint32_t num) +{ + const char *c_list = "abcdefghijklmnopqrstuvwxyz0123456789+_-#.,"; + const unsigned c_size = 42; + size_t i, j; + unsigned rem; + char ** strs = NULL; + + if (num == 0 || len == 0) + return NULL; + + strs = talloc_array(mem_ctx, char *, num); + if (strs == NULL) return NULL; + + for (i = 0; i < num; i++) { + char *retstr = (char *)talloc_size(strs, len + 1); + if (retstr == NULL) { + talloc_free(strs); + return NULL; + } + rem = i; + for (j = 0; j < len; j++) { + retstr[j] = c_list[rem % c_size]; + rem = rem / c_size; + } + retstr[j] = 0; + strs[i] = retstr; + if (rem != 0) { + /* we were not able to fit the number of + * combinations asked for in the length + * specified */ + DEBUG(0,(__location__ ": Too many combinations %u for length %u\n", + num, (unsigned)len)); + + talloc_free(strs); + return NULL; + } + } + + return strs; +} diff --git a/lib/util/getpass.c b/lib/util/getpass.c new file mode 100644 index 0000000..0cbc7dd --- /dev/null +++ b/lib/util/getpass.c @@ -0,0 +1,230 @@ +/* + * Unix SMB/CIFS implementation. + * + * getpass.c - platform independent getpass function. + * + * Copyright (c) 2010-2012 Andreas Schneider <asn@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" + +#include "system/filesys.h" +#include "system/terminal.h" + +#if !defined(SMB_MALLOC) +#undef malloc +#define SMB_MALLOC(s) malloc((s)) +#endif + +/** + * @internal + * + * @brief Get the password from the console. + * + * @param[in] prompt The prompt to display. + * + * @param[in] buf The buffer to fill. + * + * @param[in] len The length of the buffer. + * + * @param[in] verify Should the password be verified? + * + * @return 1 on success, 0 on error. + */ +static int samba_gets(const char *prompt, char *buf, size_t len, bool verify) +{ + char *tmp; + char *ptr = NULL; + int ok = 0; + + tmp = SMB_MALLOC(len); + if (tmp == NULL) { + return 0; + } + memset(tmp,'\0',len); + + /* read the password */ + while (!ok) { + if (buf[0] != '\0') { + fprintf(stdout, "%s[%s] ", prompt, buf); + } else { + fprintf(stdout, "%s", prompt); + } + fflush(stdout); + if (fgets(tmp, len, stdin) == NULL) { + free(tmp); + return 0; + } + + if ((ptr = strchr(tmp, '\n'))) { + *ptr = '\0'; + } + fprintf(stdout, "\n"); + + if (*tmp) { + strncpy(buf, tmp, len); + } + + if (verify) { + char *key_string; + + key_string = SMB_MALLOC(len); + if (key_string == NULL) { + break; + } + memset(key_string, '\0', len); + + fprintf(stdout, "\nVerifying, please re-enter. %s", prompt); + fflush(stdout); + if (! fgets(key_string, len, stdin)) { + memset(key_string, '\0', len); + SAFE_FREE(key_string); + clearerr(stdin); + continue; + } + if ((ptr = strchr(key_string, '\n'))) { + *ptr = '\0'; + } + fprintf(stdout, "\n"); + if (strcmp(buf, key_string)) { + printf("\n\07\07Mismatch - try again\n"); + memset(key_string, '\0', len); + SAFE_FREE(key_string); + fflush(stdout); + continue; + } + memset(key_string, '\0', len); + SAFE_FREE(key_string); + } + ok = 1; + } + memset(tmp, '\0', len); + free(tmp); + + return ok; +} + +/** + * @brief Get a password from the console. + * + * You should make sure that the buffer is an empty string! + * + * You can also use this function to ask for a username. Then you can fill the + * buffer with the username and it is shows to the users. If the users just + * presses enter the buffer will be untouched. + * + * @code + * char username[128]; + * + * snprintf(username, sizeof(username), "john"); + * + * samba_getpass("Username:", username, sizeof(username), 1, 0); + * @endcode + * + * The prompt will look like this: + * + * Username: [john] + * + * If you press enter then john is used as the username, or you can type it in + * to change it. + * + * @param[in] prompt The prompt to show to ask for the password. + * + * @param[out] buf The buffer the password should be stored. It NEEDS to be + * empty or filled out. + * + * @param[in] len The length of the buffer. + * + * @param[in] echo Should we echo what you type. + * + * @param[in] verify Should we ask for the password twice. + * + * @return 0 on success, -1 on error. + */ +int samba_getpass(const char *prompt, + char *buf, + size_t len, + bool echo, + bool verify) +{ + struct termios attr; + struct termios old_attr; + int ok = 0; + int fd = -1; + + /* fgets needs at least len - 1 */ + if (prompt == NULL || buf == NULL || len < 2) { + return -1; + } + + if (isatty (STDIN_FILENO)) { + + ZERO_STRUCT(attr); + ZERO_STRUCT(old_attr); + + /* get local terminal attributes */ + if (tcgetattr(STDIN_FILENO, &attr) < 0) { + perror("tcgetattr"); + return -1; + } + + /* save terminal attributes */ + memcpy(&old_attr, &attr, sizeof(attr)); + if((fd = fcntl(0, F_GETFL, 0)) < 0) { + perror("fcntl"); + return -1; + } + + /* disable echo */ + if (!echo) { + attr.c_lflag &= ~(ECHO); + } + + /* write attributes to terminal */ + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) < 0) { + perror("tcsetattr"); + return -1; + } + } + + /* disable nonblocking I/O */ + if (fd & O_NDELAY) { + fcntl(0, F_SETFL, fd & ~O_NDELAY); + } + + ok = samba_gets(prompt, buf, len, verify); + + if (isatty (STDIN_FILENO)) { + + /* reset terminal */ + tcsetattr(STDIN_FILENO, TCSANOW, &old_attr); + } + + /* close fd */ + if (fd & O_NDELAY) { + fcntl(0, F_SETFL, fd); + } + + if (!ok) { + memset (buf, '\0', len); + return -1; + } + + /* force termination */ + buf[len - 1] = '\0'; + + return 0; +} diff --git a/lib/util/gpfswrap.c b/lib/util/gpfswrap.c new file mode 100644 index 0000000..2f15bf4 --- /dev/null +++ b/lib/util/gpfswrap.c @@ -0,0 +1,296 @@ +/* + * Unix SMB/CIFS implementation. + * Wrapper for GPFS library + * Copyright (C) Volker Lendecke 2005 + * Copyright (C) Christof Schmitt 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "gpfswrap.h" + +static int (*gpfs_set_share_fn)(int fd, unsigned int allow, unsigned int deny); +static int (*gpfs_set_lease_fn)(int fd, unsigned int type); +static int (*gpfs_fgetacl_fn)(int fd, int flags, void *acl); +static int (*gpfs_putacl_fn)(const char *pathname, int flags, void *acl); +static int (*gpfs_get_realfilename_path_fn)(const char *pathname, + char *filenamep, + int *len); +static int (*gpfs_register_cifs_export_fn)(void); +static int (*gpfs_set_winattrs_path_fn)(const char *pathname, + int flags, + struct gpfs_winattr *attrs); +static int (*gpfs_set_winattrs_fn)(int fd, int flags, + struct gpfs_winattr *attrs); +static int (*gpfs_get_winattrs_fn)(int fd, struct gpfs_winattr *attrs); +static int (*gpfs_ftruncate_fn)(int fd, gpfs_off64_t length); +static int (*gpfs_lib_init_fn)(int flags); +static int (*gpfs_set_times_fn)(int fd, int flags, gpfs_timestruc_t times[4]); +static int (*gpfs_set_times_path_fn)(char *path, + int flags, + gpfs_timestruc_t times[4]); +static int (*gpfs_quotactl_fn)(const char *pathname, + int cmd, + int id, + void *bufp); +static int (*gpfs_init_trace_fn)(void); +static int (*gpfs_query_trace_fn)(void); +static void (*gpfs_add_trace_fn)(int level, const char *msg); +static void (*gpfs_fini_trace_fn)(void); +static int (*gpfs_fstat_x_fn)(int fd, unsigned int *litemask, + struct gpfs_iattr64 *iattr, size_t len); +static int (*gpfs_stat_x_fn)(const char *pathname, unsigned int *litemask, + struct gpfs_iattr64 *iattr, size_t len); + +int gpfswrap_init(void) +{ + static void *l; + + if (l != NULL) { + return 0; + } + + l = dlopen("libgpfs.so", RTLD_LAZY); + if (l == NULL) { + return -1; + } + + gpfs_set_share_fn = dlsym(l, "gpfs_set_share"); + gpfs_set_lease_fn = dlsym(l, "gpfs_set_lease"); + gpfs_fgetacl_fn = dlsym(l, "gpfs_getacl_fd"); + gpfs_putacl_fn = dlsym(l, "gpfs_putacl"); + gpfs_get_realfilename_path_fn = dlsym(l, "gpfs_get_realfilename_path"); + gpfs_register_cifs_export_fn = dlsym(l, "gpfs_register_cifs_export"); + gpfs_set_winattrs_path_fn = dlsym(l, "gpfs_set_winattrs_path"); + gpfs_set_winattrs_fn = dlsym(l, "gpfs_set_winattrs"); + gpfs_get_winattrs_fn = dlsym(l, "gpfs_get_winattrs"); + gpfs_ftruncate_fn = dlsym(l, "gpfs_ftruncate"); + gpfs_lib_init_fn = dlsym(l, "gpfs_lib_init"); + gpfs_set_times_fn = dlsym(l, "gpfs_set_times"); + gpfs_set_times_path_fn = dlsym(l, "gpfs_set_times_path"); + gpfs_quotactl_fn = dlsym(l, "gpfs_quotactl"); + gpfs_init_trace_fn = dlsym(l, "gpfs_init_trace"); + gpfs_query_trace_fn = dlsym(l, "gpfs_query_trace"); + gpfs_add_trace_fn = dlsym(l, "gpfs_add_trace"); + gpfs_fini_trace_fn = dlsym(l, "gpfs_fini_trace"); + gpfs_fstat_x_fn = dlsym(l, "gpfs_fstat_x"); + gpfs_stat_x_fn = dlsym(l, "gpfs_stat_x"); + + return 0; +} + +int gpfswrap_set_share(int fd, unsigned int allow, unsigned int deny) +{ + if (gpfs_set_share_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_set_share_fn(fd, allow, deny); +} + +int gpfswrap_set_lease(int fd, unsigned int type) +{ + if (gpfs_set_lease_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_set_lease_fn(fd, type); +} + +int gpfswrap_fgetacl(int fd, int flags, void *acl) +{ + if (gpfs_fgetacl_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_fgetacl_fn(fd, flags, acl); +} + +int gpfswrap_putacl(const char *pathname, int flags, void *acl) +{ + if (gpfs_putacl_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_putacl_fn(pathname, flags, acl); +} + +int gpfswrap_get_realfilename_path(const char *pathname, + char *filenamep, + int *len) +{ + if (gpfs_get_realfilename_path_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_get_realfilename_path_fn(pathname, filenamep, len); +} + +int gpfswrap_register_cifs_export(void) +{ + if (gpfs_register_cifs_export_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_register_cifs_export_fn(); +} + +int gpfswrap_set_winattrs_path(const char *pathname, + int flags, + struct gpfs_winattr *attrs) +{ + if (gpfs_set_winattrs_path_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_set_winattrs_path_fn(pathname, flags, attrs); +} + +int gpfswrap_set_winattrs(int fd, int flags, struct gpfs_winattr *attrs) +{ + if (gpfs_set_winattrs_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_set_winattrs_fn(fd, flags, attrs); +} + +int gpfswrap_get_winattrs(int fd, struct gpfs_winattr *attrs) +{ + if (gpfs_get_winattrs_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_get_winattrs_fn(fd, attrs); +} + +int gpfswrap_ftruncate(int fd, gpfs_off64_t length) +{ + if (gpfs_ftruncate_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_ftruncate_fn(fd, length); +} + +int gpfswrap_lib_init(int flags) +{ + if (gpfs_lib_init_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_lib_init_fn(flags); +} + +int gpfswrap_set_times(int fd, int flags, gpfs_timestruc_t times[4]) +{ + if (gpfs_set_times_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_set_times_fn(fd, flags, times); +} + +int gpfswrap_set_times_path(char *path, int flags, gpfs_timestruc_t times[4]) +{ + if (gpfs_set_times_path_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_set_times_path_fn(path, flags, times); +} + +int gpfswrap_quotactl(const char *pathname, int cmd, int id, void *bufp) +{ + if (gpfs_quotactl_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_quotactl_fn(pathname, cmd, id, bufp); +} + +int gpfswrap_init_trace(void) +{ + if (gpfs_init_trace_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_init_trace_fn(); +} + +int gpfswrap_query_trace(void) +{ + if (gpfs_query_trace_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_query_trace_fn(); +} + +void gpfswrap_add_trace(int level, const char *msg) +{ + if (gpfs_add_trace_fn == NULL) { + return; + } + + gpfs_add_trace_fn(level, msg); +} + +void gpfswrap_fini_trace(void) +{ + if (gpfs_fini_trace_fn == NULL) { + return; + } + + gpfs_fini_trace_fn(); +} + +int gpfswrap_fstat_x(int fd, unsigned int *litemask, + struct gpfs_iattr64 *iattr, size_t len) +{ + if (gpfs_fstat_x_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_fstat_x_fn(fd, litemask, iattr, len); +} + +int gpfswrap_stat_x(const char *pathname, unsigned int *litemask, + struct gpfs_iattr64 *iattr, size_t len) +{ + if (gpfs_stat_x_fn == NULL) { + errno = ENOSYS; + return -1; + } + + return gpfs_stat_x_fn(pathname, litemask, iattr, len); +} diff --git a/lib/util/gpfswrap.h b/lib/util/gpfswrap.h new file mode 100644 index 0000000..e387a56 --- /dev/null +++ b/lib/util/gpfswrap.h @@ -0,0 +1,57 @@ +/* + * Unix SMB/CIFS implementation. + * Wrapper for GPFS library + * Copyright (C) Christian Ambach <cambach1@de.ibm.com> 2006 + * Copyright (C) Christof Schmitt 2015 + * + * Major code contributions by Chetan Shringarpure <chetan.sh@in.ibm.com> + * and Gomati Mohanan <gomati.mohanan@in.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GPFSWRAP_H__ +#define __GPFSWRAP_H__ + +#include <gpfs.h> + +int gpfswrap_init(void); +int gpfswrap_set_share(int fd, unsigned int allow, unsigned int deny); +int gpfswrap_set_lease(int fd, unsigned int type); +int gpfswrap_fgetacl(int fd, int flags, void *acl); +int gpfswrap_putacl(const char *pathname, int flags, void *acl); +int gpfswrap_get_realfilename_path(const char *pathname, + char *filenamep, + int *len); +int gpfswrap_register_cifs_export(void); +int gpfswrap_set_winattrs_path(const char *pathname, + int flags, + struct gpfs_winattr *attrs); +int gpfswrap_set_winattrs(int fd, int flags, struct gpfs_winattr *attrs); +int gpfswrap_get_winattrs(int fd, struct gpfs_winattr *attrs); +int gpfswrap_ftruncate(int fd, gpfs_off64_t length); +int gpfswrap_lib_init(int flags); +int gpfswrap_set_times(int fd, int flags, gpfs_timestruc_t times[4]); +int gpfswrap_set_times_path(char *path, int flags, gpfs_timestruc_t times[4]); +int gpfswrap_quotactl(const char *pathname, int cmd, int id, void *bufp); +int gpfswrap_init_trace(void); +int gpfswrap_query_trace(void); +void gpfswrap_add_trace(int level, const char *msg); +void gpfswrap_fini_trace(void); +int gpfswrap_fstat_x(int fd, unsigned int *litemask, + struct gpfs_iattr64 *iattr, size_t len); +int gpfswrap_stat_x(const char *pathname, unsigned int *litemask, + struct gpfs_iattr64 *iattr, size_t len); + +#endif diff --git a/lib/util/idtree.c b/lib/util/idtree.c new file mode 100644 index 0000000..7f08b42 --- /dev/null +++ b/lib/util/idtree.c @@ -0,0 +1,395 @@ +/* + Unix SMB/CIFS implementation. + + very efficient functions to manage mapping a id (such as a fnum) to + a pointer. This is used for fnum and search id allocation. + + Copyright (C) Andrew Tridgell 2004 + + This code is derived from lib/idr.c in the 2.6 Linux kernel, which was + written by Jim Houston jim.houston@ccur.com, and is + Copyright (C) 2002 by Concurrent Computer Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + see the section marked "public interface" below for documentation +*/ + +/** + * @file + */ + +#include "replace.h" +#include <talloc.h> +#include "debug.h" +#include "idtree.h" + +#define IDR_BITS 5 +#define IDR_FULL 0xfffffffful +#if 0 /* unused */ +#define TOP_LEVEL_FULL (IDR_FULL >> 30) +#endif +#define IDR_SIZE (1 << IDR_BITS) +#define IDR_MASK ((1 << IDR_BITS)-1) +#define MAX_ID_SHIFT (sizeof(int)*8 - 1) +#define MAX_ID_BIT (1U << MAX_ID_SHIFT) +#define MAX_ID_MASK (MAX_ID_BIT - 1) +#define MAX_LEVEL (MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS +#define IDR_FREE_MAX MAX_LEVEL + MAX_LEVEL + +#define set_bit(bit, v) (v) |= (1U<<(bit)) +#define clear_bit(bit, v) (v) &= ~(1U<<(bit)) +#define test_bit(bit, v) ((v) & (1U<<(bit))) + +struct idr_layer { + uint32_t bitmap; + struct idr_layer *ary[IDR_SIZE]; + int count; +}; + +struct idr_context { + struct idr_layer *top; + struct idr_layer *id_free; + int layers; + int id_free_cnt; +}; + +static struct idr_layer *alloc_layer(struct idr_context *idp) +{ + struct idr_layer *p; + + if (!(p = idp->id_free)) + return NULL; + idp->id_free = p->ary[0]; + idp->id_free_cnt--; + p->ary[0] = NULL; + return p; +} + +static int find_next_bit(uint32_t bm, int maxid, int n) +{ + while (n<maxid && !test_bit(n, bm)) n++; + return n; +} + +static void free_layer(struct idr_context *idp, struct idr_layer *p) +{ + p->ary[0] = idp->id_free; + idp->id_free = p; + idp->id_free_cnt++; +} + +static int idr_pre_get(struct idr_context *idp) +{ + while (idp->id_free_cnt < IDR_FREE_MAX) { + struct idr_layer *pn = talloc_zero(idp, struct idr_layer); + if(pn == NULL) + return (0); + free_layer(idp, pn); + } + return 1; +} + +static int sub_alloc(struct idr_context *idp, void *ptr, int *starting_id) +{ + int n, m, sh; + struct idr_layer *p, *pn; + struct idr_layer *pa[MAX_LEVEL+1]; + unsigned int l, id, oid; + uint32_t bm; + + memset(pa, 0, sizeof(pa)); + + id = *starting_id; +restart: + p = idp->top; + l = idp->layers; + pa[l--] = NULL; + while (1) { + /* + * We run around this while until we reach the leaf node... + */ + n = (id >> (IDR_BITS*l)) & IDR_MASK; + bm = ~p->bitmap; + m = find_next_bit(bm, IDR_SIZE, n); + if (m == IDR_SIZE) { + /* no space available go back to previous layer. */ + l++; + oid = id; + id = (id | ((1 << (IDR_BITS*l))-1)) + 1; + + /* if already at the top layer, we need to grow */ + if (!(p = pa[l])) { + *starting_id = id; + return -2; + } + + /* If we need to go up one layer, continue the + * loop; otherwise, restart from the top. + */ + sh = IDR_BITS * (l + 1); + if (oid >> sh == id >> sh) + continue; + else + goto restart; + } + if (m != n) { + sh = IDR_BITS*l; + id = ((id >> sh) ^ n ^ m) << sh; + } + if (id >= MAX_ID_BIT) + return -1; + if (l == 0) + break; + /* + * Create the layer below if it is missing. + */ + if (!p->ary[m]) { + if (!(pn = alloc_layer(idp))) + return -1; + p->ary[m] = pn; + p->count++; + } + pa[l--] = p; + p = p->ary[m]; + } + /* + * We have reached the leaf node, plant the + * users pointer and return the raw id. + */ + p->ary[m] = (struct idr_layer *)ptr; + set_bit(m, p->bitmap); + p->count++; + /* + * If this layer is full mark the bit in the layer above + * to show that this part of the radix tree is full. + * This may complete the layer above and require walking + * up the radix tree. + */ + n = id; + while (p->bitmap == IDR_FULL) { + if (l >= MAX_LEVEL) { + break; + } + p = pa[++l]; + if (p == NULL) { + break; + } + n = n >> IDR_BITS; + set_bit((n & IDR_MASK), p->bitmap); + } + return(id); +} + +static int idr_get_new_above_int(struct idr_context *idp, void *ptr, int starting_id) +{ + struct idr_layer *p, *pn; + int layers, v, id; + + idr_pre_get(idp); + + id = starting_id; +build_up: + p = idp->top; + layers = idp->layers; + if (!p) { + if (!(p = alloc_layer(idp))) + return -1; + layers = 1; + } + /* + * Add a new layer to the top of the tree if the requested + * id is larger than the currently allocated space. + */ + while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) { + layers++; + if (!p->count) + continue; + if (!(pn = alloc_layer(idp))) { + /* + * The allocation failed. If we built part of + * the structure tear it down. + */ + for (pn = p; p && p != idp->top; pn = p) { + p = p->ary[0]; + pn->ary[0] = NULL; + pn->bitmap = pn->count = 0; + free_layer(idp, pn); + } + return -1; + } + pn->ary[0] = p; + pn->count = 1; + if (p->bitmap == IDR_FULL) + set_bit(0, pn->bitmap); + p = pn; + } + idp->top = p; + idp->layers = layers; + v = sub_alloc(idp, ptr, &id); + if (v == -2) + goto build_up; + return(v); +} + +static int sub_remove(struct idr_context *idp, int shift, int id) +{ + struct idr_layer *p = idp->top; + struct idr_layer **pa[1+MAX_LEVEL]; + struct idr_layer ***paa = &pa[0]; + int n; + + *paa = NULL; + *++paa = &idp->top; + + while ((shift > 0) && p) { + n = (id >> shift) & IDR_MASK; + clear_bit(n, p->bitmap); + *++paa = &p->ary[n]; + p = p->ary[n]; + shift -= IDR_BITS; + } + n = id & IDR_MASK; + if (p != NULL && test_bit(n, p->bitmap)) { + clear_bit(n, p->bitmap); + p->ary[n] = NULL; + while(*paa && ! --((**paa)->count)){ + free_layer(idp, **paa); + **paa-- = NULL; + } + if ( ! *paa ) + idp->layers = 0; + return 0; + } + return -1; +} + +static void *_idr_find(struct idr_context *idp, int id) +{ + int n; + struct idr_layer *p; + + n = idp->layers * IDR_BITS; + p = idp->top; + /* + * This tests to see if bits outside the current tree are + * present. If so, tain't one of ours! + */ + if (n + IDR_BITS < 31 && + ((id & ~(~0U << MAX_ID_SHIFT)) >> (n + IDR_BITS))) { + return NULL; + } + + /* Mask off upper bits we don't use for the search. */ + id &= MAX_ID_MASK; + + while (n >= IDR_BITS && p) { + n -= IDR_BITS; + p = p->ary[(id >> n) & IDR_MASK]; + } + return((void *)p); +} + +static int _idr_remove(struct idr_context *idp, int id) +{ + struct idr_layer *p; + + /* Mask off upper bits we don't use for the search. */ + id &= MAX_ID_MASK; + + if (sub_remove(idp, (idp->layers - 1) * IDR_BITS, id) == -1) { + return -1; + } + + if ( idp->top && idp->top->count == 1 && + (idp->layers > 1) && + idp->top->ary[0]) { + /* We can drop a layer */ + p = idp->top->ary[0]; + idp->top->bitmap = idp->top->count = 0; + free_layer(idp, idp->top); + idp->top = p; + --idp->layers; + } + while (idp->id_free_cnt >= IDR_FREE_MAX) { + p = alloc_layer(idp); + talloc_free(p); + } + return 0; +} + +/************************************************************************ + this is the public interface +**************************************************************************/ + +/** + initialise a idr tree. The context return value must be passed to + all subsequent idr calls. To destroy the idr tree use talloc_free() + on this context + */ +_PUBLIC_ struct idr_context *idr_init(TALLOC_CTX *mem_ctx) +{ + return talloc_zero(mem_ctx, struct idr_context); +} + +/** + allocate the next available id, and assign 'ptr' into its slot. + you can retrieve later this pointer using idr_find() +*/ +_PUBLIC_ int idr_get_new(struct idr_context *idp, void *ptr, int limit) +{ + int ret = idr_get_new_above_int(idp, ptr, 0); + if (ret > limit) { + idr_remove(idp, ret); + return -1; + } + return ret; +} + +/** + allocate a new id, giving the first available value greater than or + equal to the given starting id +*/ +_PUBLIC_ int idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id, int limit) +{ + int ret = idr_get_new_above_int(idp, ptr, starting_id); + if (ret > limit) { + idr_remove(idp, ret); + return -1; + } + return ret; +} + +/** + find a pointer value previously set with idr_get_new given an id +*/ +_PUBLIC_ void *idr_find(struct idr_context *idp, int id) +{ + return _idr_find(idp, id); +} + +/** + remove an id from the idr tree +*/ +_PUBLIC_ int idr_remove(struct idr_context *idp, int id) +{ + int ret; + ret = _idr_remove((struct idr_context *)idp, id); + if (ret != 0) { + DEBUG(0,("WARNING: attempt to remove unset id %d in idtree\n", id)); + } + return ret; +} diff --git a/lib/util/idtree.h b/lib/util/idtree.h new file mode 100644 index 0000000..79d2d8c --- /dev/null +++ b/lib/util/idtree.h @@ -0,0 +1,63 @@ +/* + Unix SMB/CIFS implementation. + + very efficient functions to manage mapping a id (such as a fnum) to + a pointer. This is used for fnum and search id allocation. + + Copyright (C) Andrew Tridgell 2004 + + This code is derived from lib/idr.c in the 2.6 Linux kernel, which was + written by Jim Houston jim.houston@ccur.com, and is + Copyright (C) 2002 by Concurrent Computer Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_IDTREE_H_ +#define _SAMBA_IDTREE_H_ + +#include <talloc.h> + +struct idr_context; + +/** + initialise a idr tree. The context return value must be passed to + all subsequent idr calls. To destroy the idr tree use talloc_free() + on this context + */ +struct idr_context *idr_init(TALLOC_CTX *mem_ctx); + +/** + allocate the next available id, and assign 'ptr' into its slot. + you can retrieve later this pointer using idr_find() +*/ +int idr_get_new(struct idr_context *idp, void *ptr, int limit); + +/** + allocate a new id, giving the first available value greater than or + equal to the given starting id +*/ +int idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id, int limit); + +/** + find a pointer value previously set with idr_get_new given an id +*/ +void *idr_find(struct idr_context *idp, int id); + +/** + remove an id from the idr tree +*/ +int idr_remove(struct idr_context *idp, int id); + +#endif /* _SAMBA_IDTREE_H_ */ diff --git a/lib/util/idtree_random.c b/lib/util/idtree_random.c new file mode 100644 index 0000000..d22245a --- /dev/null +++ b/lib/util/idtree_random.c @@ -0,0 +1,68 @@ +/* + Unix SMB/CIFS implementation. + + very efficient functions to manage mapping a id (such as a fnum) to + a pointer. This is used for fnum and search id allocation. + + Copyright (C) Andrew Tridgell 2004 + + This code is derived from lib/idr.c in the 2.6 Linux kernel, which was + written by Jim Houston jim.houston@ccur.com, and is + Copyright (C) 2002 by Concurrent Computer Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + see the section marked "public interface" below for documentation +*/ + +/** + * @file + */ + +#include "replace.h" +#include "samba_util.h" /* generate_random() */ +#include "idtree.h" +#include "idtree_random.h" + +/** + allocate a new id randomly in the given range +*/ +_PUBLIC_ int idr_get_new_random(struct idr_context *idp, + void *ptr, + int starting_id, + int limit) +{ + int id; + + /* first try a random starting point in the whole range, and if that fails, + then start randomly in the bottom half of the range. This can only + fail if the range is over half full, and finally fallback to any + free id */ + id = idr_get_new_above( + idp, ptr, starting_id+(generate_random() % limit), limit); + if (id == -1) { + id = idr_get_new_above( + idp, + ptr, + starting_id+(generate_random()%(limit/2)), + limit); + } + if (id == -1) { + id = idr_get_new_above(idp, ptr, starting_id, limit); + } + + return id; +} diff --git a/lib/util/idtree_random.h b/lib/util/idtree_random.h new file mode 100644 index 0000000..623147c --- /dev/null +++ b/lib/util/idtree_random.h @@ -0,0 +1,41 @@ +/* + Unix SMB/CIFS implementation. + + very efficient functions to manage mapping a id (such as a fnum) to + a pointer. This is used for fnum and search id allocation. + + Copyright (C) Andrew Tridgell 2004 + + This code is derived from lib/idr.c in the 2.6 Linux kernel, which was + written by Jim Houston jim.houston@ccur.com, and is + Copyright (C) 2002 by Concurrent Computer Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_IDTREE_RANDOM_H_ +#define _SAMBA_IDTREE_RANDOM_H_ + +#include <talloc.h> +#include "idtree.h" + +/** + allocate a new id randomly in the given range +*/ +int idr_get_new_random(struct idr_context *idp, + void *ptr, + int starting_id, + int limit); + +#endif /* _SAMBA_IDTREE_RANDOM_H_ */ diff --git a/lib/util/iov_buf.c b/lib/util/iov_buf.c new file mode 100644 index 0000000..0c18466 --- /dev/null +++ b/lib/util/iov_buf.c @@ -0,0 +1,43 @@ +/* + * Unix SMB/CIFS implementation. + * Samba system utilities + * Copyright (C) Volker Lendecke 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/filesys.h" +#include "iov_buf.h" +#include <talloc.h> + +uint8_t *iov_concat(TALLOC_CTX *mem_ctx, const struct iovec *iov, int count) +{ + ssize_t buflen; + uint8_t *buf; + + buflen = iov_buflen(iov, count); + if (buflen == -1) { + return NULL; + } + + buf = talloc_array(mem_ctx, uint8_t, buflen); + if (buf == NULL) { + return NULL; + } + + iov_buf(iov, count, buf, buflen); + + return buf; +} diff --git a/lib/util/iov_buf.h b/lib/util/iov_buf.h new file mode 100644 index 0000000..cb330de --- /dev/null +++ b/lib/util/iov_buf.h @@ -0,0 +1,102 @@ +/* + * Unix SMB/CIFS implementation. + * Samba system utilities + * Copyright (C) Volker Lendecke 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LIB_IOV_BUF_H__ +#define __LIB_IOV_BUF_H__ + +#include "replace.h" +#include <talloc.h> +#include "system/filesys.h" + +static inline +ssize_t iov_buf(const struct iovec *iov, int iovcnt, + uint8_t *buf, size_t buflen) +{ + size_t needed = 0; + uint8_t *p = buf; + int i; + + for (i=0; i<iovcnt; i++) { + size_t thislen = iov[i].iov_len; + size_t tmp; + + tmp = needed + thislen; + + if (tmp < needed) { + /* wrap */ + return -1; + } + needed = tmp; + + if ((p != NULL) && needed <= buflen && thislen > 0) { + memcpy(p, iov[i].iov_base, thislen); + p += thislen; + } + } + + return needed; +} + +static inline +ssize_t iov_buflen(const struct iovec *iov, int iovcnt) +{ + return iov_buf(iov, iovcnt, NULL, 0); +} + +static inline +bool iov_advance(struct iovec **iov, int *iovcnt, size_t n) +{ + struct iovec *v = *iov; + int cnt = *iovcnt; + + while (n > 0) { + if (cnt == 0) { + return false; + } + if (n < v->iov_len) { + v->iov_base = (char *)v->iov_base + n; + v->iov_len -= n; + break; + } + n -= v->iov_len; + v += 1; + cnt -= 1; + } + + /* + * Skip 0-length iovec's + * + * There might be empty buffers at the end of iov. Next time we do a + * readv/writev based on this iov would give 0 transferred bytes, also + * known as EPIPE. So we need to be careful discarding them. + */ + + while ((cnt > 0) && (v->iov_len == 0)) { + v += 1; + cnt -= 1; + } + + *iov = v; + *iovcnt = cnt; + return true; +} + +uint8_t *iov_concat(TALLOC_CTX *mem_ctx, const struct iovec *iov, int count); + +#endif diff --git a/lib/util/mainpage.dox b/lib/util/mainpage.dox new file mode 100644 index 0000000..464151e --- /dev/null +++ b/lib/util/mainpage.dox @@ -0,0 +1,11 @@ +/** + +\mainpage util + +\section Introduction + +This library contains convenience functions that are used heavily +throughout Samba. None of these functions are SMB or Samba-specific. +It's a bit to Samba what GLib is to the GNOME folks. + +*/ diff --git a/lib/util/memcache.c b/lib/util/memcache.c new file mode 100644 index 0000000..98e317c --- /dev/null +++ b/lib/util/memcache.c @@ -0,0 +1,467 @@ +/* + Unix SMB/CIFS implementation. + In-memory cache + Copyright (C) Volker Lendecke 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include <talloc.h> +#include "../lib/util/debug.h" +#include "../lib/util/samba_util.h" +#include "../lib/util/dlinklist.h" +#include "../lib/util/rbtree.h" +#include "memcache.h" + +static struct memcache *global_cache; + +struct memcache_talloc_value { + void *ptr; + size_t len; +}; + +struct memcache_element { + struct rb_node rb_node; + struct memcache_element *prev, *next; + size_t keylength, valuelength; + uint8_t n; /* This is really an enum, but save memory */ + char data[1]; /* placeholder for offsetof */ +}; + +struct memcache { + struct memcache_element *mru; + struct rb_root tree; + size_t size; + size_t max_size; +}; + +static void memcache_element_parse(struct memcache_element *e, + DATA_BLOB *key, DATA_BLOB *value); + +static bool memcache_is_talloc(enum memcache_number n) +{ + bool result; + + switch (n) { + case GETPWNAM_CACHE: + case PDB_GETPWSID_CACHE: + case SINGLETON_CACHE_TALLOC: + case SHARE_MODE_LOCK_CACHE: + case GETWD_CACHE: + case VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC: + result = true; + break; + default: + result = false; + break; + } + + return result; +} + +static int memcache_destructor(struct memcache *cache) { + struct memcache_element *e, *next; + + for (e = cache->mru; e != NULL; e = next) { + next = e->next; + TALLOC_FREE(e); + } + return 0; +} + +struct memcache *memcache_init(TALLOC_CTX *mem_ctx, size_t max_size) +{ + struct memcache *result; + + result = talloc_zero(mem_ctx, struct memcache); + if (result == NULL) { + return NULL; + } + result->max_size = max_size; + talloc_set_destructor(result, memcache_destructor); + return result; +} + +void memcache_set_global(struct memcache *cache) +{ + TALLOC_FREE(global_cache); + global_cache = cache; +} + +static struct memcache_element *memcache_node2elem(struct rb_node *node) +{ + return (struct memcache_element *) + ((char *)node - offsetof(struct memcache_element, rb_node)); +} + +static void memcache_element_parse(struct memcache_element *e, + DATA_BLOB *key, DATA_BLOB *value) +{ + key->data = ((uint8_t *)e) + offsetof(struct memcache_element, data); + key->length = e->keylength; + value->data = key->data + e->keylength; + value->length = e->valuelength; +} + +static size_t memcache_element_size(size_t key_length, size_t value_length) +{ + return sizeof(struct memcache_element) - 1 + key_length + value_length; +} + +static int memcache_compare(struct memcache_element *e, enum memcache_number n, + DATA_BLOB key) +{ + DATA_BLOB this_key, this_value; + + if ((int)e->n < (int)n) return 1; + if ((int)e->n > (int)n) return -1; + + if (e->keylength < key.length) return 1; + if (e->keylength > key.length) return -1; + + memcache_element_parse(e, &this_key, &this_value); + return memcmp(this_key.data, key.data, key.length); +} + +static struct memcache_element *memcache_find( + struct memcache *cache, enum memcache_number n, DATA_BLOB key) +{ + struct rb_node *node; + + node = cache->tree.rb_node; + + while (node != NULL) { + struct memcache_element *elem = memcache_node2elem(node); + int cmp; + + cmp = memcache_compare(elem, n, key); + if (cmp == 0) { + return elem; + } + node = (cmp < 0) ? node->rb_left : node->rb_right; + } + + return NULL; +} + +bool memcache_lookup(struct memcache *cache, enum memcache_number n, + DATA_BLOB key, DATA_BLOB *value) +{ + struct memcache_element *e; + + if (cache == NULL) { + cache = global_cache; + } + if (cache == NULL) { + return false; + } + + e = memcache_find(cache, n, key); + if (e == NULL) { + return false; + } + + if (cache->size != 0) { + DLIST_PROMOTE(cache->mru, e); + } + + memcache_element_parse(e, &key, value); + return true; +} + +void *memcache_lookup_talloc(struct memcache *cache, enum memcache_number n, + DATA_BLOB key) +{ + DATA_BLOB value; + struct memcache_talloc_value mtv; + + if (!memcache_lookup(cache, n, key, &value)) { + return NULL; + } + + if (value.length != sizeof(mtv)) { + return NULL; + } + + memcpy(&mtv, value.data, sizeof(mtv)); + + return mtv.ptr; +} + +static void memcache_delete_element(struct memcache *cache, + struct memcache_element *e) +{ + rb_erase(&e->rb_node, &cache->tree); + + DLIST_REMOVE(cache->mru, e); + + if (memcache_is_talloc(e->n)) { + DATA_BLOB cache_key, cache_value; + struct memcache_talloc_value mtv; + + memcache_element_parse(e, &cache_key, &cache_value); + SMB_ASSERT(cache_value.length == sizeof(mtv)); + memcpy(&mtv, cache_value.data, sizeof(mtv)); + cache->size -= mtv.len; + TALLOC_FREE(mtv.ptr); + } + + cache->size -= memcache_element_size(e->keylength, e->valuelength); + + TALLOC_FREE(e); +} + +static void memcache_trim(struct memcache *cache, struct memcache_element *e) +{ + struct memcache_element *tail = NULL; + + if (cache->max_size == 0) { + return; + } + + for (tail = DLIST_TAIL(cache->mru); + (cache->size > cache->max_size) && (tail != NULL); + tail = DLIST_TAIL(cache->mru)) + { + if (tail == e) { + tail = DLIST_PREV(tail); + if (tail == NULL) { + break; + } + } + memcache_delete_element(cache, tail); + } +} + +void memcache_delete(struct memcache *cache, enum memcache_number n, + DATA_BLOB key) +{ + struct memcache_element *e; + + if (cache == NULL) { + cache = global_cache; + } + if (cache == NULL) { + return; + } + + e = memcache_find(cache, n, key); + if (e == NULL) { + return; + } + + memcache_delete_element(cache, e); +} + +bool memcache_add(struct memcache *cache, enum memcache_number n, + DATA_BLOB key, DATA_BLOB value) +{ + struct memcache_element *e; + struct rb_node **p; + struct rb_node *parent; + DATA_BLOB cache_key, cache_value; + size_t element_size; + + if (cache == NULL) { + cache = global_cache; + } + if (cache == NULL) { + return false; + } + + if (key.length == 0) { + return false; + } + + e = memcache_find(cache, n, key); + + if (e != NULL) { + memcache_element_parse(e, &cache_key, &cache_value); + + if (value.length <= cache_value.length) { + if (memcache_is_talloc(e->n)) { + struct memcache_talloc_value mtv; + + SMB_ASSERT(cache_value.length == sizeof(mtv)); + memcpy(&mtv, cache_value.data, sizeof(mtv)); + cache->size -= mtv.len; + TALLOC_FREE(mtv.ptr); + } + /* + * We can reuse the existing record + */ + memcpy(cache_value.data, value.data, value.length); + e->valuelength = value.length; + + if (memcache_is_talloc(e->n)) { + struct memcache_talloc_value mtv; + + SMB_ASSERT(cache_value.length == sizeof(mtv)); + memcpy(&mtv, cache_value.data, sizeof(mtv)); + cache->size += mtv.len; + } + return true; + } + + memcache_delete_element(cache, e); + } + + element_size = memcache_element_size(key.length, value.length); + + e = talloc_size(cache, element_size); + if (e == NULL) { + DEBUG(0, ("talloc failed\n")); + return false; + } + talloc_set_type(e, struct memcache_element); + + e->n = n; + e->keylength = key.length; + e->valuelength = value.length; + + memcache_element_parse(e, &cache_key, &cache_value); + memcpy(cache_key.data, key.data, key.length); + memcpy(cache_value.data, value.data, value.length); + + parent = NULL; + p = &cache->tree.rb_node; + + while (*p) { + struct memcache_element *elem = memcache_node2elem(*p); + int cmp; + + parent = (*p); + + cmp = memcache_compare(elem, n, key); + + p = (cmp < 0) ? &(*p)->rb_left : &(*p)->rb_right; + } + + rb_link_node(&e->rb_node, parent, p); + rb_insert_color(&e->rb_node, &cache->tree); + + DLIST_ADD(cache->mru, e); + + cache->size += element_size; + if (memcache_is_talloc(e->n)) { + struct memcache_talloc_value mtv; + + SMB_ASSERT(cache_value.length == sizeof(mtv)); + memcpy(&mtv, cache_value.data, sizeof(mtv)); + cache->size += mtv.len; + } + memcache_trim(cache, e); + + return true; +} + +bool memcache_add_talloc(struct memcache *cache, enum memcache_number n, + DATA_BLOB key, void *pptr) +{ + struct memcache_talloc_value mtv; + void **ptr = (void **)pptr; + + if (cache == NULL) { + cache = global_cache; + } + if (cache == NULL) { + return false; + } + + mtv.len = talloc_total_size(*ptr); + mtv.ptr = talloc_move(cache, ptr); + + return memcache_add(cache, n, key, data_blob_const(&mtv, sizeof(mtv))); +} + +void memcache_flush(struct memcache *cache, enum memcache_number n) +{ + struct rb_node *node; + + if (cache == NULL) { + cache = global_cache; + } + if (cache == NULL) { + return; + } + + /* + * Find the smallest element of number n + */ + + node = cache->tree.rb_node; + if (node == NULL) { + return; + } + + /* + * First, find *any* element of number n + */ + + while (true) { + struct memcache_element *elem = memcache_node2elem(node); + struct rb_node *next; + + if ((int)elem->n == (int)n) { + break; + } + + if ((int)elem->n < (int)n) { + next = node->rb_right; + } + else { + next = node->rb_left; + } + if (next == NULL) { + break; + } + node = next; + } + + /* + * Then, find the leftmost element with number n + */ + + while (true) { + struct rb_node *prev = rb_prev(node); + struct memcache_element *elem; + + if (prev == NULL) { + break; + } + elem = memcache_node2elem(prev); + if ((int)elem->n != (int)n) { + break; + } + node = prev; + } + + while (node != NULL) { + struct memcache_element *e = memcache_node2elem(node); + struct rb_node *next = rb_next(node); + + if (e->n != n) { + break; + } + + memcache_delete_element(cache, e); + node = next; + } +} + +void gfree_memcache(void) +{ + TALLOC_FREE(global_cache); +} diff --git a/lib/util/memcache.h b/lib/util/memcache.h new file mode 100644 index 0000000..6986760 --- /dev/null +++ b/lib/util/memcache.h @@ -0,0 +1,119 @@ +/* + Unix SMB/CIFS implementation. + In-memory cache + Copyright (C) Volker Lendecke 2007-2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __MEMCACHE_H__ +#define __MEMCACHE_H__ + +#include <talloc.h> +#include "lib/util/data_blob.h" + +struct memcache; + +/* + * A memcache can store different subkeys with overlapping keys, the + * memcache_number becomes part of the key. Feel free to add caches of your + * own here. + * + * If you add talloc type caches, also note this in the switch statement in + * memcache_is_talloc(). + */ + +enum memcache_number { + STAT_CACHE, + GETREALFILENAME_CACHE, + GETWD_CACHE, + GETPWNAM_CACHE, /* talloc */ + MANGLE_HASH2_CACHE, + PDB_GETPWSID_CACHE, /* talloc */ + SINGLETON_CACHE_TALLOC, /* talloc */ + SINGLETON_CACHE, + SMB1_SEARCH_OFFSET_MAP, + SHARE_MODE_LOCK_CACHE, /* talloc */ + VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC, /* talloc */ + DFREE_CACHE, +}; + +/* + * Create a memcache structure. max_size is in bytes, if you set it 0 it will + * not forget anything. + */ + +struct memcache *memcache_init(TALLOC_CTX *mem_ctx, size_t max_size); + +/* + * If you set this global memcache, use it as the default cache when NULL is + * passed to the memcache functions below. This is a workaround for many + * situations where passing the cache everywhere would be a big hassle. + */ + +void memcache_set_global(struct memcache *cache); + +/* + * Add a data blob to the cache + */ + +bool memcache_add(struct memcache *cache, enum memcache_number n, + DATA_BLOB key, DATA_BLOB value); + +/* + * Add a talloc object to the cache. The difference to memcache_add() is that + * when the objects is to be discarded, talloc_free is called for it. Also + * talloc_move() ownership of the object to the cache. + * + * Please note that the current implementation has a fixed relationship + * between what cache subtypes store talloc objects and which ones store plain + * blobs. We can fix this, but for now we don't have a mixed use of blobs vs + * talloc objects in the cache types. + */ + +bool memcache_add_talloc(struct memcache *cache, enum memcache_number n, + DATA_BLOB key, void *ptr); + +/* + * Delete an object from the cache + */ + +void memcache_delete(struct memcache *cache, enum memcache_number n, + DATA_BLOB key); + +/* + * Look up an object from the cache. Memory still belongs to the cache, so + * make a copy of it if needed. + */ + +bool memcache_lookup(struct memcache *cache, enum memcache_number n, + DATA_BLOB key, DATA_BLOB *value); + +/* + * Look up an object from the cache. Memory still belongs to the cache, so + * make a copy of it if needed. + */ + +void *memcache_lookup_talloc(struct memcache *cache, enum memcache_number n, + DATA_BLOB key); + +/* + * Flush a complete cache subset. + */ + +void memcache_flush(struct memcache *cache, enum memcache_number n); + +void gfree_memcache(void); + +#endif diff --git a/lib/util/memory.h b/lib/util/memory.h new file mode 100644 index 0000000..40c66d8 --- /dev/null +++ b/lib/util/memory.h @@ -0,0 +1,129 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1999 + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_MEMORY_H_ +#define _SAMBA_MEMORY_H_ + +#ifndef SAFE_FREE /* Oh no this is also defined in tdb.h */ +/** + * Free memory if the pointer and zero the pointer. + * + * @note You are explicitly allowed to pass NULL pointers -- they will + * always be ignored. + **/ +#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) +#endif + +/** + * Zero string and free memory if the pointer and zero the pointer. + * + * @note You are explicitly allowed to pass NULL pointers -- they will + * always be ignored. + **/ +#define BURN_FREE_STR(x) do { \ + if ((x) != NULL) { \ + size_t s = strlen(x); \ + memset_s((x), s, 0, s); \ + free(x); (x) = NULL; \ + } \ + } while(0) + +/** + * Zero and free memory if the pointer and zero the pointer. + * + * @note You are explicitly allowed to pass NULL pointers -- they will + * always be ignored. + **/ +#define BURN_FREE(x, s) do { \ + if ((x) != NULL) { \ + memset_s((x), (s), 0, (s)); \ + free(x); (x) = NULL; \ + } \ + } while(0) + +/** + * Type-safe version of malloc. Allocated one copy of the + * specified data type. + */ +#define malloc_p(type) (type *)malloc(sizeof(type)) + +/** + * Allocate an array of elements of one data type. Does type-checking. + */ +#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count, false) + +/** + * Resize an array of elements of one data type. Does type-checking. + */ +#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count, false) + +/** + * Zero a structure. + */ +#ifndef ZERO_STRUCT +#define ZERO_STRUCT(x) memset_s((char *)&(x), sizeof(x), 0, sizeof(x)) +#endif + +/** + * Zero a structure given a pointer to the structure. + */ +#ifndef ZERO_STRUCTP +#define ZERO_STRUCTP(x) do { \ + if ((x) != NULL) { \ + memset_s((char *)(x), sizeof(*(x)), 0, sizeof(*(x))); \ + } \ +} while(0) +#endif + +/** + * Zero a structure given a pointer to the structure - no zero check. + */ +#ifndef ZERO_STRUCTPN +#define ZERO_STRUCTPN(x) memset_s((char *)(x), sizeof(*(x)), 0, sizeof(*(x))) +#endif + +/** + * Zero an array - note that sizeof(array) must work - ie. it must not be a + * pointer. + */ +#ifndef ZERO_ARRAY +#define ZERO_ARRAY(x) memset_s((char *)(x), sizeof(x), 0, sizeof(x)) +#endif + +/** + * Zero a given len of an array + */ +#define ZERO_ARRAY_LEN(x, l) memset_s((char *)(x), (l), 0, (l)) + +/** + * Work out how many elements there are in a static array + */ +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) +#endif + +/** + * Pointer difference macro. + */ +#ifndef PTR_DIFF +#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2))) +#endif + +#endif /* _SAMBA_MEMORY_H_ */ diff --git a/lib/util/mkdir_p.c b/lib/util/mkdir_p.c new file mode 100644 index 0000000..87a3f79 --- /dev/null +++ b/lib/util/mkdir_p.c @@ -0,0 +1,70 @@ +/* + mkdir -p + + Copyright (C) Amitay Isaacs 2014 + Copyright (C) Martin Schwenke 2014 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ +#include "replace.h" +#include <sys/stat.h> +#include <libgen.h> +#include "mkdir_p.h" + +int mkdir_p(const char *dir, int mode) +{ + char t[PATH_MAX]; + ssize_t len; + int ret; + + if (strcmp(dir, "/") == 0) { + return 0; + } + + if (strcmp(dir, ".") == 0) { + return 0; + } + + /* Try to create directory */ + ret = mkdir(dir, mode); + /* Succeed if that worked or if it already existed */ + if (ret == 0 || errno == EEXIST) { + return 0; + } + /* Fail on anything else except ENOENT */ + if (errno != ENOENT) { + return ret; + } + + /* Create ancestors */ + len = strlen(dir); + ret = snprintf(t, sizeof(t), "%s", dir); + if (ret != len) { + errno = ENAMETOOLONG; + return -1; + } + + ret = mkdir_p(dirname(t), mode); + if (ret != 0) { + return ret; + } + + /* Create directory */ + ret = mkdir(dir, mode); + if ((ret == -1) && (errno == EEXIST)) { + ret = 0; + } + + return ret; +} diff --git a/lib/util/mkdir_p.h b/lib/util/mkdir_p.h new file mode 100644 index 0000000..9281de8 --- /dev/null +++ b/lib/util/mkdir_p.h @@ -0,0 +1,21 @@ +/* + mkdir -p + + Copyright (C) Amitay Isaacs 2014 + Copyright (C) Martin Schwenke 2014 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +int mkdir_p(const char *dir, int mode); diff --git a/lib/util/modules.c b/lib/util/modules.c new file mode 100644 index 0000000..4260234 --- /dev/null +++ b/lib/util/modules.c @@ -0,0 +1,320 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jelmer Vernooij 2002-2003,2005-2007 + Copyright (C) Stefan (metze) Metzmacher 2003 + Copyright (C) Andrew Bartlett 2011 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "dynconfig/dynconfig.h" +#include "lib/util/samba_modules.h" +#include "lib/util/util_paths.h" +#include "system/filesys.h" +#include "system/dir.h" + +/** + * Obtain the init function from a shared library file + */ +init_module_fn load_module(const char *path, bool is_probe, void **handle_out) +{ + void *handle; + void *init_fn; + char *error; + + /* This should be a WAF build, where modules should be built + * with no undefined symbols and are already linked against + * the libraries that they are loaded by */ + handle = dlopen(path, RTLD_NOW); + + /* This call should reset any possible non-fatal errors that + occurred since last call to dl* functions */ + error = dlerror(); + + if (handle == NULL) { + int level = is_probe ? 5 : 0; + DEBUG(level, ("Error loading module '%s': %s\n", path, error ? error : "")); + return NULL; + } + + init_fn = (init_module_fn)dlsym(handle, SAMBA_INIT_MODULE); + + /* we could check dlerror() to determine if it worked, because + dlsym() can validly return NULL, but what would we do with + a NULL pointer as a module init function? */ + + if (init_fn == NULL) { + DEBUG(0, ("Unable to find %s() in %s: %s\n", + SAMBA_INIT_MODULE, path, dlerror())); + DEBUG(1, ("Loading module '%s' failed\n", path)); + dlclose(handle); + return NULL; + } + + if (handle_out) { + *handle_out = handle; + } + + return (init_module_fn)init_fn; +} + +/** + * Obtain list of init functions from the modules in the specified + * directory + */ +static init_module_fn *load_modules(TALLOC_CTX *mem_ctx, const char *path) +{ + DIR *dir; + struct dirent *entry; + char *filename; + int success = 0; + init_module_fn *ret = talloc_array(mem_ctx, init_module_fn, 2); + + ret[0] = NULL; + + dir = opendir(path); + if (dir == NULL) { + talloc_free(ret); + return NULL; + } + + while((entry = readdir(dir))) { + if (ISDOT(entry->d_name) || ISDOTDOT(entry->d_name)) + continue; + + filename = talloc_asprintf(mem_ctx, "%s/%s", path, entry->d_name); + + ret[success] = load_module(filename, true, NULL); + if (ret[success]) { + ret = talloc_realloc(mem_ctx, ret, init_module_fn, success+2); + success++; + ret[success] = NULL; + } + + talloc_free(filename); + } + + closedir(dir); + + return ret; +} + +/** + * Run the specified init functions. + * + * @return true if all functions ran successfully, false otherwise + */ +bool run_init_functions(TALLOC_CTX *ctx, init_module_fn *fns) +{ + int i; + bool ret = true; + + if (fns == NULL) + return true; + + for (i = 0; fns[i]; i++) { ret &= (bool)NT_STATUS_IS_OK(fns[i](ctx)); } + + return ret; +} + +/** + * Load the initialization functions from DSO files for a specific subsystem. + * + * Will return an array of function pointers to initialization functions + */ + +init_module_fn *load_samba_modules(TALLOC_CTX *mem_ctx, const char *subsystem) +{ + char *path = modules_path(mem_ctx, subsystem); + init_module_fn *ret; + + ret = load_modules(mem_ctx, path); + + talloc_free(path); + + return ret; +} + +static NTSTATUS load_module_absolute_path(const char *module_path, + bool is_probe) +{ + void *handle; + init_module_fn init; + NTSTATUS status; + + DBG_INFO("%s module '%s'\n", + is_probe ? "Probing" : "Loading", + module_path); + + init = load_module(module_path, is_probe, &handle); + if (init == NULL) { + return NT_STATUS_UNSUCCESSFUL; + } + + DBG_NOTICE("Module '%s' loaded\n", module_path); + + status = init(NULL); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("Module '%s' initialization failed: %s\n", + module_path, + get_friendly_nt_error_msg(status)); + dlclose(handle); + return status; + } + + return NT_STATUS_OK; +} + +/* Load all modules in list and return number of + * modules that has been successfully loaded */ +int smb_load_all_modules_absoute_path(const char **modules) +{ + int i; + int success = 0; + + for(i = 0; modules[i] != NULL; i++) { + const char *module = modules[i]; + NTSTATUS status; + + if (module[0] != '/') { + continue; + } + + status = load_module_absolute_path(module, false); + if (NT_STATUS_IS_OK(status)) { + success++; + } + } + + DEBUG(2, ("%d modules successfully loaded\n", success)); + + return success; +} + +/** + * @brief Check if a module exist and load it. + * + * @param[in] subsystem The name of the subsystem the module belongs too. + * + * @param[in] module The name of the module + * + * @return A NTSTATUS code + */ +NTSTATUS smb_probe_module(const char *subsystem, const char *module) +{ + NTSTATUS status; + char *module_path = NULL; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + + if (subsystem == NULL) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + if (module == NULL) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + if (strchr(module, '/')) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + module_path = talloc_asprintf(tmp_ctx, + "%s/%s.%s", + modules_path(tmp_ctx, subsystem), + module, + shlib_ext()); + if (module_path == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + status = load_module_absolute_path(module_path, true); + +done: + TALLOC_FREE(tmp_ctx); + return status; +} + +/** + * @brief Check if a module exist and load it. + * + * Warning: Using this function can have security implecations! + * + * @param[in] subsystem The name of the subsystem the module belongs too. + * + * @param[in] module Load a module using an absolute path. + * + * @return A NTSTATUS code + */ +NTSTATUS smb_probe_module_absolute_path(const char *module) +{ + if (module == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + if (module[0] != '/') { + return NT_STATUS_INVALID_PARAMETER; + } + + return load_module_absolute_path(module, true); +} + +/** + * @brief Load a module. + * + * @param[in] subsystem The name of the subsystem the module belongs too. + * + * @param[in] module Check if a module exists and load it. + * + * @return A NTSTATUS code + */ +NTSTATUS smb_load_module(const char *subsystem, const char *module) +{ + NTSTATUS status; + char *module_path = NULL; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + + if (subsystem == NULL) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + if (module == NULL) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + if (strchr(module, '/')) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + module_path = talloc_asprintf(tmp_ctx, + "%s/%s.%s", + modules_path(tmp_ctx, subsystem), + module, + shlib_ext()); + if (module_path == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + status = load_module_absolute_path(module_path, false); + +done: + TALLOC_FREE(tmp_ctx); + return status; +} diff --git a/lib/util/ms_fnmatch.c b/lib/util/ms_fnmatch.c new file mode 100644 index 0000000..48454a8 --- /dev/null +++ b/lib/util/ms_fnmatch.c @@ -0,0 +1,249 @@ +/* + Unix SMB/CIFS implementation. + filename matching routine + Copyright (C) Andrew Tridgell 1992-2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + This module was originally based on fnmatch.c copyright by the Free + Software Foundation. It bears little (if any) resemblance to that + code now +*/ + +/** + * @file + * @brief MS-style Filename matching + */ + +#include "replace.h" +#include "lib/util/samba_util.h" +#include "libcli/smb/smb_constants.h" + +static int null_match(const char *p) +{ + for (;*p;p++) { + if (*p != '*' && + *p != '<' && + *p != '"' && + *p != '>') return -1; + } + return 0; +} + +/* + the max_n structure is purely for efficiency, it doesn't contribute + to the matching algorithm except by ensuring that the algorithm does + not grow exponentially +*/ +struct max_n { + const char *predot; + const char *postdot; +}; + + +/* + p and n are the pattern and string being matched. The max_n array is + an optimisation only. The ldot pointer is NULL if the string does + not contain a '.', otherwise it points at the last dot in 'n'. +*/ +static int ms_fnmatch_core(const char *p, const char *n, + struct max_n *max_n, const char *ldot, + bool is_case_sensitive) +{ + codepoint_t c, c2; + int i; + size_t size, size_n; + + while ((c = next_codepoint(p, &size))) { + p += size; + + switch (c) { + case '*': + /* a '*' matches zero or more characters of any type */ + if (max_n != NULL && max_n->predot && + max_n->predot <= n) { + return null_match(p); + } + for (i=0; n[i]; i += size_n) { + next_codepoint(n+i, &size_n); + if (ms_fnmatch_core(p, n+i, max_n+1, ldot, is_case_sensitive) == 0) { + return 0; + } + } + if (max_n != NULL && (!max_n->predot || + max_n->predot > n)) { + max_n->predot = n; + } + return null_match(p); + + case '<': + /* a '<' matches zero or more characters of + any type, but stops matching at the last + '.' in the string. */ + if (max_n != NULL && max_n->predot && + max_n->predot <= n) { + return null_match(p); + } + if (max_n != NULL && max_n->postdot && + max_n->postdot <= n && n <= ldot) { + return -1; + } + for (i=0; n[i]; i += size_n) { + next_codepoint(n+i, &size_n); + if (ms_fnmatch_core(p, n+i, max_n+1, ldot, is_case_sensitive) == 0) return 0; + if (n+i == ldot) { + if (ms_fnmatch_core(p, n+i+size_n, max_n+1, ldot, is_case_sensitive) == 0) return 0; + if (max_n != NULL) { + if (!max_n->postdot || + max_n->postdot > n) { + max_n->postdot = n; + } + } + return -1; + } + } + if (max_n != NULL && (!max_n->predot || + max_n->predot > n)) { + max_n->predot = n; + } + return null_match(p); + + case '?': + /* a '?' matches any single character */ + if (! *n) { + return -1; + } + next_codepoint(n, &size_n); + n += size_n; + break; + + case '>': + /* a '?' matches any single character, but + treats '.' specially */ + if (n[0] == '.') { + if (! n[1] && null_match(p) == 0) { + return 0; + } + break; + } + if (! *n) return null_match(p); + next_codepoint(n, &size_n); + n += size_n; + break; + + case '"': + /* a bit like a soft '.' */ + if (*n == 0 && null_match(p) == 0) { + return 0; + } + if (*n != '.') return -1; + next_codepoint(n, &size_n); + n += size_n; + break; + + default: + c2 = next_codepoint(n, &size_n); + if (c != c2) { + if (is_case_sensitive) { + return -1; + } + if (codepoint_cmpi(c, c2) != 0) { + return -1; + } + } + n += size_n; + break; + } + } + + if (! *n) { + return 0; + } + + return -1; +} + +int ms_fnmatch_protocol(const char *pattern, const char *string, int protocol, + bool is_case_sensitive) +{ + int ret = -1; + size_t count, i; + + if (strcmp(string, "..") == 0) { + string = "."; + } + + if (strpbrk(pattern, "<>*?\"") == NULL) { + /* this is not just an optimisation - it is essential + for LANMAN1 correctness */ + return strcasecmp_m(pattern, string); + } + + if (protocol <= PROTOCOL_LANMAN2) { + char *p = talloc_strdup(NULL, pattern); + if (p == NULL) { + return -1; + } + /* + for older negotiated protocols it is possible to + translate the pattern to produce a "new style" + pattern that exactly matches w2k behaviour + */ + for (i=0;p[i];i++) { + if (p[i] == '?') { + p[i] = '>'; + } else if (p[i] == '.' && + (p[i+1] == '?' || + p[i+1] == '*' || + p[i+1] == 0)) { + p[i] = '"'; + } else if (p[i] == '*' && + p[i+1] == '.') { + p[i] = '<'; + } + } + ret = ms_fnmatch_protocol(p, string, PROTOCOL_NT1, + is_case_sensitive); + talloc_free(p); + return ret; + } + + for (count=i=0;pattern[i];i++) { + if (pattern[i] == '*' || pattern[i] == '<') count++; + } + + /* If the pattern includes '*' or '<' */ + if (count >= 1) { + struct max_n max_n[count]; + + memset(max_n, 0, sizeof(struct max_n) * count); + + ret = ms_fnmatch_core(pattern, string, max_n, strrchr(string, '.'), + is_case_sensitive); + } else { + ret = ms_fnmatch_core(pattern, string, NULL, strrchr(string, '.'), + is_case_sensitive); + } + + return ret; +} + + +/** a generic fnmatch function - uses for non-CIFS pattern matching */ +int gen_fnmatch(const char *pattern, const char *string) +{ + return ms_fnmatch_protocol(pattern, string, PROTOCOL_NT1, false); +} diff --git a/lib/util/msghdr.c b/lib/util/msghdr.c new file mode 100644 index 0000000..3a1d6f5 --- /dev/null +++ b/lib/util/msghdr.c @@ -0,0 +1,273 @@ +/* + * Unix SMB/CIFS implementation. + * Copyright (C) Volker Lendecke 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "lib/util/msghdr.h" +#include "lib/util/iov_buf.h" +#include <sys/socket.h> + +#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) + +ssize_t msghdr_prep_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize, + const int *fds, size_t num_fds) +{ + size_t fds_size = sizeof(int) * MIN(num_fds, INT8_MAX); + size_t cmsg_len = CMSG_LEN(fds_size); + size_t cmsg_space = CMSG_SPACE(fds_size); + struct cmsghdr *cmsg; + void *fdptr; + + if (num_fds == 0) { + if (msg != NULL) { + msg->msg_control = NULL; + msg->msg_controllen = 0; + } + /* + * C99 doesn't allow 0-length arrays + */ + return 1; + } + if (num_fds > INT8_MAX) { + return -1; + } + if ((msg == NULL) || (cmsg_space > bufsize)) { + /* + * C99 doesn't allow 0-length arrays + */ + return MAX(cmsg_space, 1); + } + + msg->msg_control = buf; + msg->msg_controllen = cmsg_space; + + cmsg = CMSG_FIRSTHDR(msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = cmsg_len; + fdptr = CMSG_DATA(cmsg); + memcpy(fdptr, fds, fds_size); + msg->msg_controllen = cmsg->cmsg_len; + + return cmsg_space; +} + +size_t msghdr_prep_recv_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize, + size_t num_fds) +{ + size_t ret = CMSG_SPACE(sizeof(int) * num_fds); + + if (bufsize < ret) { + return ret; + } + if (msg != NULL) { + if (num_fds != 0) { + msg->msg_control = buf; + msg->msg_controllen = ret; + } else { + msg->msg_control = NULL; + msg->msg_controllen = 0; + } + } + return ret; +} + +size_t msghdr_extract_fds(struct msghdr *msg, int *fds, size_t fds_size) +{ + struct cmsghdr *cmsg; + size_t num_fds; + + for(cmsg = CMSG_FIRSTHDR(msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(msg, cmsg)) + { + if ((cmsg->cmsg_type == SCM_RIGHTS) && + (cmsg->cmsg_level == SOL_SOCKET)) { + break; + } + } + + if (cmsg == NULL) { + return 0; + } + + num_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); + + if ((num_fds != 0) && (fds != NULL) && (fds_size >= num_fds)) { + memcpy(fds, CMSG_DATA(cmsg), num_fds * sizeof(int)); + } + + return num_fds; +} + +#elif defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS) + +ssize_t msghdr_prep_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize, + const int *fds, size_t num_fds) +{ + size_t needed; + + if (num_fds > INT8_MAX) { + return -1; + } + + needed = sizeof(int) * num_fds; + + if ((msg == NULL) || (needed > bufsize)) { + return needed; + } + + memcpy(buf, fds, needed); + + msg->msg_accrights = (caddr_t) buf; + msg->msg_accrightslen = needed; + + return needed; +} + +size_t msghdr_prep_recv_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize, + size_t num_fds) +{ + size_t ret = num_fds * sizeof(int); + + if (bufsize < ret) { + return ret; + } + + if (msg != NULL) { + if (num_fds != 0) { + msg->msg_accrights = (caddr_t) buf; + msg->msg_accrightslen = ret; + } else { + msg->msg_accrights = NULL; + msg->msg_accrightslen = 0; + } + } + return ret; +} + +size_t msghdr_extract_fds(struct msghdr *msg, int *fds, size_t fds_size) +{ + size_t num_fds = msg->msg_accrightslen / sizeof(int); + + if ((fds != 0) && (num_fds <= fds_size)) { + memcpy(fds, msg->msg_accrights, msg->msg_accrightslen); + } + + return num_fds; +} + +#else + +ssize_t msghdr_prep_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize, + const int *fds, size_t num_fds) +{ + return -1; +} + +size_t msghdr_prep_recv_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize, + size_t num_fds) +{ + return 0; +} + +size_t msghdr_extract_fds(struct msghdr *msg, int *fds, size_t fds_size) +{ + return 0; +} + +#endif + +struct msghdr_buf { + struct msghdr msg; + struct sockaddr_storage addr; + struct iovec iov; + uint8_t buf[]; +}; + +ssize_t msghdr_copy(struct msghdr_buf *msg, size_t msgsize, + const void *addr, socklen_t addrlen, + const struct iovec *iov, int iovcnt, + const int *fds, size_t num_fds) +{ + ssize_t fd_len; + size_t iov_len, needed, bufsize; + + bufsize = (msgsize > offsetof(struct msghdr_buf, buf)) ? + msgsize - offsetof(struct msghdr_buf, buf) : 0; + + if (msg != NULL) { + msg->msg = (struct msghdr) { 0 }; + + fd_len = msghdr_prep_fds(&msg->msg, msg->buf, bufsize, + fds, num_fds); + } else { + fd_len = msghdr_prep_fds(NULL, NULL, bufsize, fds, num_fds); + } + + if (fd_len == -1) { + return -1; + } + + if (bufsize >= (size_t)fd_len) { + bufsize -= fd_len; + } else { + bufsize = 0; + } + + if (msg != NULL) { + + if (addr != NULL) { + if (addrlen > sizeof(struct sockaddr_storage)) { + errno = EMSGSIZE; + return -1; + } + memcpy(&msg->addr, addr, addrlen); + msg->msg.msg_name = &msg->addr; + msg->msg.msg_namelen = addrlen; + } else { + msg->msg.msg_name = NULL; + msg->msg.msg_namelen = 0; + } + + msg->iov.iov_base = msg->buf + fd_len; + msg->iov.iov_len = iov_buf( + iov, iovcnt, msg->iov.iov_base, bufsize); + iov_len = msg->iov.iov_len; + + msg->msg.msg_iov = &msg->iov; + msg->msg.msg_iovlen = 1; + } else { + iov_len = iov_buflen(iov, iovcnt); + } + + needed = offsetof(struct msghdr_buf, buf) + fd_len; + if (needed < (size_t)fd_len) { + return -1; + } + needed += iov_len; + if (needed < iov_len) { + return -1; + } + + return needed; +} + +struct msghdr *msghdr_buf_msghdr(struct msghdr_buf *msg) +{ + return &msg->msg; +} diff --git a/lib/util/msghdr.h b/lib/util/msghdr.h new file mode 100644 index 0000000..c1676d2 --- /dev/null +++ b/lib/util/msghdr.h @@ -0,0 +1,42 @@ +/* + * Unix SMB/CIFS implementation. + * Copyright (C) Volker Lendecke 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LIB_MSGHDR_H__ +#define __LIB_MSGHDR_H__ + +#include <stddef.h> +#include <stdint.h> +#include <sys/uio.h> +#include <sys/socket.h> + +ssize_t msghdr_prep_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize, + const int *fds, size_t num_fds); + +struct msghdr_buf; + +ssize_t msghdr_copy(struct msghdr_buf *msg, size_t msgsize, + const void *addr, socklen_t addrlen, + const struct iovec *iov, int iovcnt, + const int *fds, size_t num_fds); +struct msghdr *msghdr_buf_msghdr(struct msghdr_buf *msg); + +size_t msghdr_prep_recv_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize, + size_t num_fds); +size_t msghdr_extract_fds(struct msghdr *msg, int *fds, size_t num_fds); + +#endif diff --git a/lib/util/params.c b/lib/util/params.c new file mode 100644 index 0000000..dac7782 --- /dev/null +++ b/lib/util/params.c @@ -0,0 +1,116 @@ +/* -------------------------------------------------------------------------- ** + * Microsoft Network Services for Unix, AKA., Andrew Tridgell's SAMBA. + * + * This module Copyright (C) 1990-1998 Karl Auer + * + * Rewritten almost completely by Christopher R. Hertel + * at the University of Minnesota, September, 1997. + * This module Copyright (C) 1997-1998 by the University of Minnesota + * -------------------------------------------------------------------------- ** + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * -------------------------------------------------------------------------- ** + * + * Module name: params + * + * -------------------------------------------------------------------------- ** + * + * This module performs lexical analysis and initial parsing of a + * Windows-like parameter file. It recognizes and handles four token + * types: section-name, parameter-name, parameter-value, and + * end-of-file. Comments and line continuation are handled + * internally. + * + * The entry point to the module is function pm_process(). This + * function opens the source file, calls the Parse() function to parse + * the input, and then closes the file when either the EOF is reached + * or a fatal error is encountered. + * + * A sample parameter file might look like this: + * + * [section one] + * parameter one = value string + * parameter two = another value + * [section two] + * new parameter = some value or t'other + * + * The parameter file is divided into sections by section headers: + * section names enclosed in square brackets (eg. [section one]). + * Each section contains parameter lines, each of which consist of a + * parameter name and value delimited by an equal sign. Roughly, the + * syntax is: + * + * <file> :== { <section> } EOF + * + * <section> :== <section header> { <parameter line> } + * + * <section header> :== '[' NAME ']' + * + * <parameter line> :== NAME '=' VALUE '\n' + * + * Blank lines and comment lines are ignored. Comment lines are lines + * beginning with either a semicolon (';') or a pound sign ('#'). + * + * All whitespace in section names and parameter names is compressed + * to single spaces. Leading and trailing whitespace is stripped from + * both names and values. + * + * Only the first equals sign in a parameter line is significant. + * Parameter values may contain equals signs, square brackets and + * semicolons. Internal whitespace is retained in parameter values, + * with the exception of the '\r' character, which is stripped for + * historic reasons. Parameter names may not start with a left square + * bracket, an equal sign, a pound sign, or a semicolon, because these + * are used to identify other tokens. + * + * -------------------------------------------------------------------------- ** + */ + +#include "replace.h" +#include "lib/util/samba_util.h" +#include "tini.h" + +bool pm_process(const char *filename, + bool (*sfunc)(const char *section, void *private_data), + bool (*pfunc)(const char *name, const char *value, + void *private_data), + void *private_data) +{ + bool ret = pm_process_with_flags( + filename, false, sfunc, pfunc, private_data); + return ret; +} + +bool pm_process_with_flags(const char *filename, + bool allow_empty_values, + bool (*sfunc)(const char *section, void *private_data), + bool (*pfunc)(const char *name, const char *value, + void *private_data), + void *private_data) +{ + FILE *f; + bool ret; + + f = fopen(filename, "r"); + if (f == NULL) { + return false; + } + + ret = tini_parse(f, allow_empty_values, sfunc, pfunc, private_data); + + fclose(f); + + return ret; +} diff --git a/lib/util/pidfile.c b/lib/util/pidfile.c new file mode 100644 index 0000000..6ffbbea --- /dev/null +++ b/lib/util/pidfile.c @@ -0,0 +1,238 @@ +/* + Unix SMB/CIFS implementation. + pidfile handling + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Amitay Isaccs 2016 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/filesys.h" + +#include "lib/util/blocking.h" +#include "lib/util/debug.h" +#include "lib/util/samba_util.h" /* For process_exists_by_pid() */ + +#include "lib/util/pidfile.h" + +int pidfile_path_create(const char *path, int *pfd, pid_t *existing_pid) +{ + struct flock lck; + char tmp[64] = { 0 }; + int fd, ret = 0; + int len; + ssize_t nwritten; + bool retried = false; + + fd = open(path, O_CREAT|O_WRONLY|O_NONBLOCK, 0644); + if (fd == -1) { + return errno; + } + + if (! set_close_on_exec(fd)) { + ret = errno; + goto fail; + } + +retry: + lck = (struct flock) { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + }; + + do { + ret = fcntl(fd, F_SETLK, &lck); + } while ((ret == -1) && (errno == EINTR)); + + if (ret != 0) { + ret = errno; + + if ((ret == EACCES) || (ret == EAGAIN)) { + do { + ret = fcntl(fd, F_GETLK, &lck); + } while ((ret == -1) && (errno == EINTR)); + + if (ret == -1) { + ret = errno; + goto fail; + } + + if (lck.l_type == F_UNLCK) { + if (!retried) { + /* Lock holder died, retry once */ + retried = true; + goto retry; + } + /* Something badly wrong */ + ret = EIO; + goto fail; + } + + if (existing_pid != NULL) { + *existing_pid = lck.l_pid; + } + return EAGAIN; + } + goto fail; + } + + /* + * PID file is locked by us so from here on we should unlink + * on failure + */ + len = snprintf(tmp, sizeof(tmp), "%u\n", getpid()); + if (len < 0) { + ret = errno; + goto fail_unlink; + } + if ((size_t)len >= sizeof(tmp)) { + ret = ENOSPC; + goto fail_unlink; + } + + do { + nwritten = write(fd, tmp, len); + } while ((nwritten == -1) && (errno == EINTR)); + + if ((nwritten == -1) || (nwritten != len)) { + ret = errno; + goto fail_unlink; + } + + do { + ret = ftruncate(fd, len); + } while ((ret == -1) && (errno == EINTR)); + + if (ret == -1) { + ret = errno; + goto fail_unlink; + } + + *pfd = fd; + return 0; + +fail_unlink: + unlink(path); +fail: + close(fd); + return ret; +} + +void pidfile_fd_close(int fd) +{ + struct flock lck = { + .l_type = F_UNLCK, + .l_whence = SEEK_SET, + }; + int ret; + + do { + ret = fcntl(fd, F_SETLK, &lck); + } while ((ret == -1) && (errno == EINTR)); + + do { + ret = close(fd); + } while ((ret == -1) && (errno == EINTR)); +} + + +/** + * return the pid in a pidfile. return 0 if the process (or pidfile) + * does not exist + */ +pid_t pidfile_pid(const char *piddir, const char *name) +{ + size_t len = strlen(piddir) + strlen(name) + 6; + char pidFile[len]; + int fd; + char pidstr[20] = { 0, }; + pid_t ret = -1; + + snprintf(pidFile, sizeof(pidFile), "%s/%s.pid", piddir, name); + + fd = open(pidFile, O_NONBLOCK | O_RDONLY, 0644); + + if (fd == -1) { + return 0; + } + + if (read(fd, pidstr, sizeof(pidstr)-1) <= 0) { + goto noproc; + } + + ret = (pid_t)atoi(pidstr); + if (ret <= 0) { + DEBUG(1, ("Could not parse contents of pidfile %s\n", + pidFile)); + goto noproc; + } + + if (!process_exists_by_pid(ret)) { + DEBUG(10, ("Process with PID=%d does not exist.\n", (int)ret)); + goto noproc; + } + + if (fcntl_lock(fd,F_SETLK,0,1,F_RDLCK)) { + /* we could get the lock - it can't be a Samba process */ + DEBUG(10, ("Process with PID=%d is not a Samba process.\n", + (int)ret)); + goto noproc; + } + + close(fd); + DEBUG(10, ("Process with PID=%d is running.\n", (int)ret)); + return ret; + + noproc: + close(fd); + return 0; +} + +/** + * create a pid file in the pid directory. open it and leave it locked + */ +void pidfile_create(const char *piddir, const char *name) +{ + size_t len = strlen(piddir) + strlen(name) + 6; + char pidFile[len]; + pid_t pid = (pid_t)-1; + int ret, fd; + + snprintf(pidFile, sizeof(pidFile), "%s/%s.pid", piddir, name); + + ret = pidfile_path_create(pidFile, &fd, &pid); + if (ret == EAGAIN) { + DEBUG(0,("ERROR: %s is already running. File %s exists and process id %d is running.\n", + name, pidFile, (int)pid)); + exit(1); + } + + /* Leave pid file open & locked for the duration... */ +} + +void pidfile_unlink(const char *piddir, const char *name) +{ + size_t len = strlen(piddir) + strlen(name) + 6; + char pidFile[len]; + int ret; + + snprintf(pidFile, sizeof(pidFile), "%s/%s.pid", piddir, name); + + ret = unlink(pidFile); + if (ret == -1) { + DEBUG(0,("Failed to delete pidfile %s. Error was %s\n", + pidFile, strerror(errno))); + } +} diff --git a/lib/util/pidfile.h b/lib/util/pidfile.h new file mode 100644 index 0000000..6f345a9 --- /dev/null +++ b/lib/util/pidfile.h @@ -0,0 +1,85 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jeremy Allison 2012. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_PIDFILE_H_ +#define _SAMBA_PIDFILE_H_ + +/** + * @file pidfile.h + * + * @brief PID file handling + */ + +/** + * @brief Create a PID file + * + * Opens file, locks it, and writes PID. Returns EAGAIN if another + * process has the PID file locked. Use unlink(2) and + * pidfile_fd_close() to remove the PID file. + * + * @param[in] path PID file name + * @param[out] outfd File descriptor of open/locked PID file + * @param[out] existing_pid Return existing PID on EAGAIN + * @return 0 on success, errno on failure + */ +int pidfile_path_create( + const char *path, int *outfd, pid_t *existing_pid); + +/** + * @brief Unlock and close a PID file + * + * @param[in] fd File descriptor of open/locked PID file + */ +void pidfile_fd_close(int fd); + +/** + * @brief Check a PID file + * + * PID file name is <piddir>/<name>.pid + * + * @param[in] piddir Directory for PID file + * @param[in] name PID file process name + * @return PID of active process, 0 if PID file missing/stale/error + */ +pid_t pidfile_pid(const char *piddir, const char *name); + +/** + * @brief Create a PID file + * + * Leave PID file open/locked on success, exit on failure. On + * success, use pidfile_unlink() to remove PID file before exiting. + * + * PID file name is <piddir>/<name>.pid + * + * @param[in] piddir Directory for PID file + * @param[in] name PID file process name + */ +void pidfile_create(const char *piddir, const char *name); + +/** + * @brief Remove a PID file + * + * PID file name is <piddir>/<name>.pid + * + * @param[in] piddir Directory for PID file + * @param[in] name PID file process name + */ +void pidfile_unlink(const char *piddir, const char *name); + +#endif diff --git a/lib/util/rbtree.c b/lib/util/rbtree.c new file mode 100644 index 0000000..aa663f4 --- /dev/null +++ b/lib/util/rbtree.c @@ -0,0 +1,429 @@ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli <andrea@suse.de> + (C) 2002 David Woodhouse <dwmw2@infradead.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + linux/lib/rbtree.c +*/ + +#include "replace.h" +#include "rbtree.h" +#include "fault.h" + +#define RB_RED 0 +#define RB_BLACK 1 + +#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) +#define rb_color(r) ((r)->rb_parent_color & 1) +#define rb_is_red(r) (!rb_color(r)) +#define rb_is_black(r) rb_color(r) +#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) +#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) + +static void rb_set_parent(struct rb_node *rb, struct rb_node *p) +{ + rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; +} +static void rb_set_color(struct rb_node *rb, int color) +{ + rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; +} + +#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) +#define RB_EMPTY_NODE(node) (rb_parent(node) == node) +#define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) + +static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *right = node->rb_right; + struct rb_node *parent = rb_parent(node); + + if ((node->rb_right = right->rb_left)) + rb_set_parent(right->rb_left, node); + right->rb_left = node; + + rb_set_parent(right, parent); + + if (parent) + { + if (node == parent->rb_left) + parent->rb_left = right; + else + parent->rb_right = right; + } + else + root->rb_node = right; + rb_set_parent(node, right); +} + +static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *left = node->rb_left; + struct rb_node *parent = rb_parent(node); + + if ((node->rb_left = left->rb_right)) + rb_set_parent(left->rb_right, node); + left->rb_right = node; + + rb_set_parent(left, parent); + + if (parent) + { + if (node == parent->rb_right) + parent->rb_right = left; + else + parent->rb_left = left; + } + else + root->rb_node = left; + rb_set_parent(node, left); +} + +void rb_insert_color(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *parent, *gparent; + + while ((parent = rb_parent(node)) && rb_is_red(parent)) + { + gparent = rb_parent(parent); + + if (parent == gparent->rb_left) + { + { + register struct rb_node *uncle = gparent->rb_right; + if (uncle && rb_is_red(uncle)) + { + rb_set_black(uncle); + rb_set_black(parent); + rb_set_red(gparent); + node = gparent; + continue; + } + } + + if (parent->rb_right == node) + { + register struct rb_node *tmp; + __rb_rotate_left(parent, root); + tmp = parent; + parent = node; + node = tmp; + } + + rb_set_black(parent); + rb_set_red(gparent); + __rb_rotate_right(gparent, root); + } else { + { + register struct rb_node *uncle = gparent->rb_left; + if (uncle && rb_is_red(uncle)) + { + rb_set_black(uncle); + rb_set_black(parent); + rb_set_red(gparent); + node = gparent; + continue; + } + } + + if (parent->rb_left == node) + { + register struct rb_node *tmp; + __rb_rotate_right(parent, root); + tmp = parent; + parent = node; + node = tmp; + } + + rb_set_black(parent); + rb_set_red(gparent); + __rb_rotate_left(gparent, root); + } + } + + rb_set_black(root->rb_node); +} + +static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, + struct rb_root *root) +{ + struct rb_node *other; + + while ((!node || rb_is_black(node)) && node != root->rb_node) + { + if (parent->rb_left == node) + { + other = parent->rb_right; + if (other == NULL) { + /* we should never get here */ + smb_panic("corrupted rb tree"); + /* satisfy static checkers */ + return; + } + if (rb_is_red(other)) + { + rb_set_black(other); + rb_set_red(parent); + __rb_rotate_left(parent, root); + other = parent->rb_right; + } + if ((!other->rb_left || rb_is_black(other->rb_left)) && + (!other->rb_right || rb_is_black(other->rb_right))) + { + rb_set_red(other); + node = parent; + parent = rb_parent(node); + } + else + { + if (!other->rb_right || rb_is_black(other->rb_right)) + { + struct rb_node *o_left; + if ((o_left = other->rb_left)) + rb_set_black(o_left); + rb_set_red(other); + __rb_rotate_right(other, root); + other = parent->rb_right; + } + rb_set_color(other, rb_color(parent)); + rb_set_black(parent); + if (other->rb_right) + rb_set_black(other->rb_right); + __rb_rotate_left(parent, root); + node = root->rb_node; + break; + } + } + else + { + other = parent->rb_left; + if (rb_is_red(other)) + { + rb_set_black(other); + rb_set_red(parent); + __rb_rotate_right(parent, root); + other = parent->rb_left; + } + if ((!other->rb_left || rb_is_black(other->rb_left)) && + (!other->rb_right || rb_is_black(other->rb_right))) + { + rb_set_red(other); + node = parent; + parent = rb_parent(node); + } + else + { + if (!other->rb_left || rb_is_black(other->rb_left)) + { + register struct rb_node *o_right; + if ((o_right = other->rb_right)) + rb_set_black(o_right); + rb_set_red(other); + __rb_rotate_left(other, root); + other = parent->rb_left; + } + rb_set_color(other, rb_color(parent)); + rb_set_black(parent); + if (other->rb_left) + rb_set_black(other->rb_left); + __rb_rotate_right(parent, root); + node = root->rb_node; + break; + } + } + } + if (node) + rb_set_black(node); +} + +void rb_erase(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *child, *parent; + int color; + + if (!node->rb_left) + child = node->rb_right; + else if (!node->rb_right) + child = node->rb_left; + else + { + struct rb_node *old = node, *left; + + node = node->rb_right; + while ((left = node->rb_left) != NULL) + node = left; + child = node->rb_right; + parent = rb_parent(node); + color = rb_color(node); + + if (child) + rb_set_parent(child, parent); + if (parent == old) { + parent->rb_right = child; + parent = node; + } else + parent->rb_left = child; + + node->rb_parent_color = old->rb_parent_color; + node->rb_right = old->rb_right; + node->rb_left = old->rb_left; + + if (rb_parent(old)) + { + if (rb_parent(old)->rb_left == old) + rb_parent(old)->rb_left = node; + else + rb_parent(old)->rb_right = node; + } else + root->rb_node = node; + + rb_set_parent(old->rb_left, node); + if (old->rb_right) + rb_set_parent(old->rb_right, node); + goto color; + } + + parent = rb_parent(node); + color = rb_color(node); + + if (child) + rb_set_parent(child, parent); + if (parent) + { + if (parent->rb_left == node) + parent->rb_left = child; + else + parent->rb_right = child; + } + else + root->rb_node = child; + + color: + if (color == RB_BLACK) + __rb_erase_color(child, parent, root); +} + +/* + * This function returns the first node (in sort order) of the tree. + */ +struct rb_node *rb_first(struct rb_root *root) +{ + struct rb_node *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_left) + n = n->rb_left; + return n; +} + +struct rb_node *rb_last(struct rb_root *root) +{ + struct rb_node *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_right) + n = n->rb_right; + return n; +} + +struct rb_node *rb_next(struct rb_node *node) +{ + struct rb_node *parent; + + if (rb_parent(node) == node) + return NULL; + + /* If we have a right-hand child, go down and then left as far + as we can. */ + if (node->rb_right) { + node = node->rb_right; + while (node->rb_left) + node=node->rb_left; + return node; + } + + /* No right-hand children. Everything down and left is + smaller than us, so any 'next' node must be in the general + direction of our parent. Go up the tree; any time the + ancestor is a right-hand child of its parent, keep going + up. First time it's a left-hand child of its parent, said + parent is our 'next' node. */ + while ((parent = rb_parent(node)) && node == parent->rb_right) + node = parent; + + return parent; +} + +struct rb_node *rb_prev(struct rb_node *node) +{ + struct rb_node *parent; + + if (rb_parent(node) == node) + return NULL; + + /* If we have a left-hand child, go down and then right as far + as we can. */ + if (node->rb_left) { + node = node->rb_left; + while (node->rb_right) + node=node->rb_right; + return node; + } + + /* No left-hand children. Go up till we find an ancestor which + is a right-hand child of its parent */ + while ((parent = rb_parent(node)) && node == parent->rb_left) + node = parent; + + return parent; +} + +void rb_replace_node(struct rb_node *victim, struct rb_node *new_node, + struct rb_root *root) +{ + struct rb_node *parent = rb_parent(victim); + + /* Set the surrounding nodes to point to the replacement */ + if (parent) { + if (victim == parent->rb_left) + parent->rb_left = new_node; + else + parent->rb_right = new_node; + } else { + root->rb_node = new_node; + } + if (victim->rb_left) + rb_set_parent(victim->rb_left, new_node); + if (victim->rb_right) + rb_set_parent(victim->rb_right, new_node); + + /* Copy the pointers/colour from the victim to the replacement */ + *new_node = *victim; +} + +void rb_link_node(struct rb_node * node, struct rb_node * parent, + struct rb_node ** rb_link) +{ + node->rb_parent_color = (unsigned long )parent; + node->rb_left = node->rb_right = NULL; + + *rb_link = node; +} diff --git a/lib/util/rbtree.h b/lib/util/rbtree.h new file mode 100644 index 0000000..1cfd346 --- /dev/null +++ b/lib/util/rbtree.h @@ -0,0 +1,132 @@ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli <andrea@suse.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + linux/include/linux/rbtree.h + + To use rbtrees you'll have to implement your own insert and search cores. + This will avoid us to use callbacks and to drop drammatically performances. + I know it's not the cleaner way, but in C (not in C++) to get + performances and genericity... + + Some example of insert and search follows here. The search is a plain + normal search over an ordered tree. The insert instead must be implemented + int two steps: as first thing the code must insert the element in + order as a red leaf in the tree, then the support library function + rb_insert_color() must be called. Such function will do the + not trivial work to rebalance the rbtree if necessary. + +----------------------------------------------------------------------- +static inline struct page * rb_search_page_cache(struct inode * inode, + unsigned long offset) +{ + struct rb_node * n = inode->i_rb_page_cache.rb_node; + struct page * page; + + while (n) + { + page = rb_entry(n, struct page, rb_page_cache); + + if (offset < page->offset) + n = n->rb_left; + else if (offset > page->offset) + n = n->rb_right; + else + return page; + } + return NULL; +} + +static inline struct page * __rb_insert_page_cache(struct inode * inode, + unsigned long offset, + struct rb_node * node) +{ + struct rb_node ** p = &inode->i_rb_page_cache.rb_node; + struct rb_node * parent = NULL; + struct page * page; + + while (*p) + { + parent = *p; + page = rb_entry(parent, struct page, rb_page_cache); + + if (offset < page->offset) + p = &(*p)->rb_left; + else if (offset > page->offset) + p = &(*p)->rb_right; + else + return page; + } + + rb_link_node(node, parent, p); + + return NULL; +} + +static inline struct page * rb_insert_page_cache(struct inode * inode, + unsigned long offset, + struct rb_node * node) +{ + struct page * ret; + if ((ret = __rb_insert_page_cache(inode, offset, node))) + goto out; + rb_insert_color(node, &inode->i_rb_page_cache); + out: + return ret; +} +----------------------------------------------------------------------- +*/ + +#ifndef _LINUX_RBTREE_H +#define _LINUX_RBTREE_H + +struct rb_node +{ + unsigned long rb_parent_color; + struct rb_node *rb_right; + struct rb_node *rb_left; +}; + +struct rb_root +{ + struct rb_node *rb_node; +}; + + +#define RB_ROOT (struct rb_root) { NULL, } + +#if 0 +#define rb_entry(ptr, type, member) container_of(ptr, type, member) +#endif + +void rb_insert_color(struct rb_node *, struct rb_root *); +void rb_erase(struct rb_node *, struct rb_root *); + +/* Find logical next and previous nodes in a tree */ +struct rb_node *rb_next(struct rb_node *); +struct rb_node *rb_prev(struct rb_node *); +struct rb_node *rb_first(struct rb_root *); +struct rb_node *rb_last(struct rb_root *); + +/* Fast replacement of a single node without remove/rebalance/add/rebalance */ +extern void rb_replace_node(struct rb_node *victim, struct rb_node *new_node, + struct rb_root *root); + +void rb_link_node(struct rb_node * node, struct rb_node * parent, + struct rb_node ** rb_link); + +#endif /* _LINUX_RBTREE_H */ diff --git a/lib/util/rfc1738.c b/lib/util/rfc1738.c new file mode 100644 index 0000000..7b8db11 --- /dev/null +++ b/lib/util/rfc1738.c @@ -0,0 +1,198 @@ +/* + * Functions for RFC 3986 percent-encoding. + * + * NOTE: + * + * This file was originally imported from the Squid project but has been + * significantly altered. The licence below is reproduced intact, but refers + * to files in Squid's repository, not in Samba. See COPYING for the GPLv3 + * notice (being the later version mentioned below). + */ + +/* + * $Id$ + * + * DEBUG: + * AUTHOR: Harvest Derived + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "replace.h" +#include <talloc.h> +#include "lib/util/samba_util.h" + +#define RFC1738_ENCODE 1 +#define RFC1738_RESERVED 2 + +/* + * According to RFC 1738, "$-_.+!*'()," are not reserved or unsafe, but as + * that has been obsolete since 2004, we sm instead for RFC 3986, where: + * + * reserved = : / ? # [ ] @ ! $ & ' ( ) * + , ; = + * unreserved = ALPHA DIGIT - . _ ~ + * + * and whatever is not in either of those are what RFC 1738 called "unsafe", + * meaning that they should are canonically but not mandatorily escaped. + * + * Characters below 0x20 or above 0x7E are always encoded. + */ + +static const unsigned char escapees[127] = { + [' '] = RFC1738_ENCODE, + ['"'] = RFC1738_ENCODE, + ['%'] = RFC1738_ENCODE, + ['<'] = RFC1738_ENCODE, + ['>'] = RFC1738_ENCODE, + ['\\'] = RFC1738_ENCODE, + ['^'] = RFC1738_ENCODE, + ['`'] = RFC1738_ENCODE, + ['{'] = RFC1738_ENCODE, + ['|'] = RFC1738_ENCODE, + ['}'] = RFC1738_ENCODE, + /* reserved : / ? # [ ] @ ! $ & ' ( ) * + , ; = */ + [':'] = RFC1738_RESERVED, + ['/'] = RFC1738_RESERVED, + ['?'] = RFC1738_RESERVED, + ['#'] = RFC1738_RESERVED, + ['['] = RFC1738_RESERVED, + [']'] = RFC1738_RESERVED, + ['@'] = RFC1738_RESERVED, + ['!'] = RFC1738_RESERVED, + ['$'] = RFC1738_RESERVED, + ['&'] = RFC1738_RESERVED, + ['\''] = RFC1738_RESERVED, + ['('] = RFC1738_RESERVED, + [')'] = RFC1738_RESERVED, + ['*'] = RFC1738_RESERVED, + ['+'] = RFC1738_RESERVED, + [','] = RFC1738_RESERVED, + [';'] = RFC1738_RESERVED, + ['='] = RFC1738_RESERVED, +}; + +/* + * rfc1738_do_escape - fills a preallocated buffer with an escaped version of + * the given string. + * + * For canonical escaping, mask should be RFC1738_ENCODE | RFC1738_RESERVED. + * For mandatory escaping, mask should be RFC1738_RESERVED. + */ +static char * +rfc1738_do_escape(char *buf, size_t bufsize, + const char *url, size_t len, unsigned char mask) +{ + size_t i; + size_t j = 0; + for (i = 0; i < len; i++) { + unsigned int c = (unsigned char) url[i]; + if (c > 126 || c < 32 || (escapees[c] & mask)) { + if (j + 3 >= bufsize) { + return NULL; + } + (void) snprintf(&buf[j], 4, "%%%02X", c); + j += 3; + } else { + if (j + 1 >= bufsize) { + return NULL; + } + buf[j] = c; + j++; + } + } + buf[j] = '\0'; + return buf; +} + +/* + * rfc1738_escape_part - Returns a talloced buffer that contains the RFC 3986 + * compliant, escaped version of the given url segment. + */ +char * +rfc1738_escape_part(TALLOC_CTX *mem_ctx, const char *url) +{ + size_t bufsize = 0; + char *buf = NULL; + + size_t len = strlen(url); + if (len >= SIZE_MAX / 3) { + return NULL; + } + + bufsize = len * 3 + 1; + buf = talloc_array(mem_ctx, char, bufsize); + if (buf == NULL) { + return NULL; + } + + talloc_set_name_const(buf, buf); + + return rfc1738_do_escape(buf, bufsize, url, len, + RFC1738_ENCODE | RFC1738_RESERVED); +} + +/* + * rfc1738_unescape() - Converts url-escaped characters in the string. + * + * The two characters following a '%' in a string should be hex digits that + * describe an encoded byte. For example, "%25" is hex 0x25 or '%' in ASCII; + * this is the only way to include a % in the unescaped string. Any character + * can be escaped, including plain letters (e.g. "%61" for "a"). Anything + * other than 2 hex characters following the % is an error. + * + * The conversion is done in-place, which is always safe as unescapes can only + * shorten the string. + * + * Returns a pointer to the end of the string (that is, the '\0' byte), or + * NULL on error, at which point s is in an undefined state. + * + * Note that after `char *e = rfc_unescape(s)`, `strlen(s)` will not equal + * `e - s` if s originally contained "%00". You might want to check for this. + */ + +_PUBLIC_ char *rfc1738_unescape(char *s) +{ + size_t i, j; /* i is write, j is read */ + for (i = 0, j = 0; s[j] != '\0'; i++, j++) { + if (s[j] == '%') { + uint8_t v; + bool ok; + + ok = hex_byte(&s[j+1], &v); + if (!ok) { + return NULL; + } + j += 2; /* OK; hex_byte() has checked ahead */ + s[i] = (unsigned char)v; + } else { + s[i] = s[j]; + } + } + s[i] = '\0'; + return s + i; +} diff --git a/lib/util/safe_string.h b/lib/util/safe_string.h new file mode 100644 index 0000000..edff296 --- /dev/null +++ b/lib/util/safe_string.h @@ -0,0 +1,64 @@ +/* + Unix SMB/CIFS implementation. + Safe string handling routines. + Copyright (C) Andrew Tridgell 1994-1998 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAFE_STRING_H +#define _SAFE_STRING_H +#ifndef _SPLINT_ /* http://www.splint.org */ + +/* Some macros to ensure people don't use buffer overflow vulnerable string + functions. */ + +#ifdef bcopy +#undef bcopy +#endif /* bcopy */ +#define bcopy(src,dest,size) __ERROR__XX__NEVER_USE_BCOPY___; + +#ifdef strcpy +#undef strcpy +#endif /* strcpy */ +#define strcpy(dest,src) __ERROR__XX__NEVER_USE_STRCPY___; + +#ifdef strcat +#undef strcat +#endif /* strcat */ +#define strcat(dest,src) __ERROR__XX__NEVER_USE_STRCAT___; + +#ifdef sprintf +#undef sprintf +#endif /* sprintf */ +#define sprintf __ERROR__XX__NEVER_USE_SPRINTF__; + +/* + * strcasecmp/strncasecmp aren't an error, but it means you're not thinking about + * multibyte. Don't use them. JRA. + */ +#ifdef strcasecmp +#undef strcasecmp +#endif +#define strcasecmp __ERROR__XX__NEVER_USE_STRCASECMP__; + +#ifdef strncasecmp +#undef strncasecmp +#endif +#define strncasecmp __ERROR__XX__NEVER_USE_STRNCASECMP__; + +#endif /* !_SPLINT_ */ + +#endif diff --git a/lib/util/samba-util.pc.in b/lib/util/samba-util.pc.in new file mode 100644 index 0000000..65876c4 --- /dev/null +++ b/lib/util/samba-util.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: samba-util +Description: Samba utility functions +Requires: talloc tevent +Version: @PACKAGE_VERSION@ +Libs: @LIB_RPATH@ -L${libdir} -lsamba-util +Cflags: -I${includedir} -DHAVE_IMMEDIATE_STRUCTURES=1 diff --git a/lib/util/samba_modules.h b/lib/util/samba_modules.h new file mode 100644 index 0000000..c698691 --- /dev/null +++ b/lib/util/samba_modules.h @@ -0,0 +1,61 @@ +/* + Unix SMB/CIFS implementation. + Handling of idle/exit events + Copyright (C) Stefan (metze) Metzmacher 2003 + Copyright (C) Andrew Bartlett 2011 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_MODULES_H +#define _SAMBA_MODULES_H + +/* Module support */ +typedef NTSTATUS (*init_module_fn) (TALLOC_CTX *ctx); + +NTSTATUS samba_init_module(TALLOC_CTX *ctx); + +/* this needs to be a string which is not in the C library. We + previously used "init_module", but that meant that modules which + did not define this function ended up calling the C library + function init_module() which makes a system call */ +#define SAMBA_INIT_MODULE "samba_init_module" + +/** + * Obtain the init function from a shared library file. + * + * The handle to dlclose() in case of error is returns in *handle if handle is not NULL + */ +init_module_fn load_module(const char *path, bool is_probe, void **handle); + +/** + * Run the specified init functions. + * + * @return true if all functions ran successfully, false otherwise + */ +bool run_init_functions(TALLOC_CTX *ctx, init_module_fn *fns); + +/** + * Load the initialization functions from DSO files for a specific subsystem. + * + * Will return an array of function pointers to initialization functions + */ +init_module_fn *load_samba_modules(TALLOC_CTX *mem_ctx, const char *subsystem); + +int smb_load_all_modules_absoute_path(const char **modules); +NTSTATUS smb_probe_module(const char *subsystem, const char *module); +NTSTATUS smb_probe_module_absolute_path(const char *module); +NTSTATUS smb_load_module(const char *subsystem, const char *module); + +#endif /* _SAMBA_MODULES_H */ diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h new file mode 100644 index 0000000..e672b4b --- /dev/null +++ b/lib/util/samba_util.h @@ -0,0 +1,708 @@ +/* + Unix SMB/CIFS implementation. + Utility functions for Samba + Copyright (C) Andrew Tridgell 1992-1999 + Copyright (C) Jelmer Vernooij 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_UTIL_H_ +#define _SAMBA_UTIL_H_ + +#ifndef SAMBA_UTIL_CORE_ONLY +#include "lib/util/charset/charset.h" +#else +#include "charset_compat.h" +#endif + +#include "lib/util/attr.h" + +/* for TALLOC_CTX */ +#include <talloc.h> + +/* for struct stat */ +#include <sys/stat.h> + +/** + * @file + * @brief Helpful macros + */ + +struct smbsrv_tcon; + +extern const char *panic_action; + +#include "lib/util/time.h" +#include "lib/util/data_blob.h" +#include "lib/util/byteorder.h" +#include "lib/util/talloc_stack.h" +#include "lib/util/talloc_keep_secret.h" + +#ifndef ABS +#define ABS(a) ((a)>0?(a):(-(a))) +#endif + +#include "lib/util/memory.h" +#include "lib/util/discard.h" + +#include "fault.h" + +#include "lib/util/util.h" + +/** + * Write backtrace to debug log + */ +_PUBLIC_ void dump_core_setup(const char *progname, const char *logfile); + +/** + register a fault handler. + Should only be called once in the execution of smbd. +*/ +_PUBLIC_ bool register_fault_handler(const char *name, void (*fault_handler)(int sig)); + +#include "lib/util/signal.h" /* Avoid /usr/include/signal.h */ + +struct sockaddr; + +_PUBLIC_ int sys_getnameinfo(const struct sockaddr *psa, + int salen, + char *host, + size_t hostlen, + char *service, + size_t servlen, + int flags); + +/* The following definitions come from lib/util/genrand.c */ + +#include "lib/util/genrand.h" + +/** + generate a single random uint32_t +**/ +_PUBLIC_ uint32_t generate_random(void); + +/** + * generate a single random uint64_t + * @see generate_unique_u64 +**/ +_PUBLIC_ uint64_t generate_random_u64(void); + +_PUBLIC_ uint64_t generate_random_u64_range(uint64_t lower, uint64_t upper); + +/** + * @brief Generate random nonces usable for re-use detection. + * + * We have a lot of places which require a unique id that can + * be used as a unique identitier for caching states. + * + * Always using generate_nonce_buffer() has it's performance costs, + * it's typically much better than generate_random_buffer(), but + * still it's overhead we want to avoid in performance critical + * workloads. + * + * We call generate_nonce_buffer() just once per given state + * and process. + * + * This is much lighter than generate_random_u64() and it's + * designed for performance critical code paths. + * + * @veto_value It is guaranteed that the return value is different from + * the veto_value. + * + * @return a unique value per given state and process + * + * @see generate_random_u64 + */ +uint64_t generate_unique_u64(uint64_t veto_value); + +/** + very basic password quality checker +**/ +_PUBLIC_ bool check_password_quality(const char *s); + +/** + * Generate a random text password (based on printable ascii characters). + * This function is designed to provide a password that + * meats the complexity requirements of UF_NORMAL_ACCOUNT objects + * and they should be human readable and writeable on any keyboard layout. + * + * Characters used are: + * ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,@$%&!?:;<=>()[]~ + */ +_PUBLIC_ char *generate_random_password(TALLOC_CTX *mem_ctx, size_t min, size_t max); + +/** + * Generate a random machine password + * + * min and max are the number of utf16 characters used + * to generate on utf8 compatible password. + * + * Note: if 'unix charset' is not 'utf8' (the default) + * then each utf16 character is only filled with + * values from 0x01 to 0x7f (ascii values without 0x00). + * This is important as the password neets to be + * a valid value as utf8 string and at the same time + * a valid value in the 'unix charset'. + * + * If 'unix charset' is 'utf8' (the default) then + * each utf16 character is a random value from 0x0000 + * 0xFFFF (excluding the surrogate ranges from 0xD800-0xDFFF) + * while the translation from CH_UTF16MUNGED + * to CH_UTF8 replaces invalid values (see utf16_munged_pull()). + * + * Note: these passwords may not pass the complexity requirements + * for UF_NORMAL_ACCOUNT objects (except krbtgt accounts). + */ +_PUBLIC_ char *generate_random_machine_password(TALLOC_CTX *mem_ctx, size_t min, size_t max); + +/** + Use the random number generator to generate a random string. +**/ +_PUBLIC_ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list); + +/** + * Generate a random text string consisting of the specified length. + * The returned string will be allocated. + * + * Characters used are: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#., + */ +_PUBLIC_ char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len); + +/** + * Generate an array of unique text strings all of the same length. + * The returned strings will be allocated. + * Returns NULL if the number of unique combinations cannot be created. + * + * Characters used are: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#., + */ +_PUBLIC_ char** generate_unique_strs(TALLOC_CTX *mem_ctx, size_t len, + uint32_t num); + +/* The following definitions come from lib/util/dprintf.c */ + +_PUBLIC_ int d_fprintf(FILE *f, const char *format, ...) PRINTF_ATTRIBUTE(2,3); +_PUBLIC_ int d_printf(const char *format, ...) PRINTF_ATTRIBUTE(1,2); +_PUBLIC_ void display_set_stderr(void); + +/* The following definitions come from lib/util/util_str.c */ + +bool next_token_talloc(TALLOC_CTX *ctx, + const char **ptr, + char **pp_buff, + const char *sep); + +/** + * Get the next token from a string, return false if none found. Handles + * double-quotes. This version does not trim leading separator characters + * before looking for a token. + */ +bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx, + const char **ptr, + char **pp_buff, + const char *sep); + + +/** + Trim the specified elements off the front and back of a string. +**/ +_PUBLIC_ bool trim_string(char *s, const char *front, const char *back); + +/** + Find the number of 'c' chars in a string +**/ +_PUBLIC_ _PURE_ size_t count_chars(const char *s, char c); + +/** + Routine to get hex characters and turn them into a 16 byte array. + the array can be variable length, and any non-hex-numeric + characters are skipped. "0xnn" or "0Xnn" is specially catered + for. + + valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" + + +**/ +_PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len); + +/** + * Parse a hex string and return a data blob. + */ +_PUBLIC_ DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex) ; + +/** + * Parse a hex dump and return a data blob + */ +_PUBLIC_ DATA_BLOB hexdump_to_data_blob(TALLOC_CTX *mem_ctx, const char *hexdump, size_t len); + +/** + * Print a buf in hex. Assumes dst is at least (srclen*2)+1 large. + */ +_PUBLIC_ void hex_encode_buf(char *dst, const uint8_t *src, size_t srclen); + +/** + * talloc version of hex_encode_buf() + */ +_PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len); + +#include "substitute.h" + +/** + Unescape a URL encoded string, in place. +**/ +_PUBLIC_ char *rfc1738_unescape(char *buf); + +/** + * rfc1738_escape_part + * Returns a static buffer that contains the RFC + * 1738 compliant, escaped version of the given url segment. (escapes + * unsafe, reserved and % chars) It would mangle the :// in http://, + * and mangle paths (because of /). + **/ +_PUBLIC_ char *rfc1738_escape_part(TALLOC_CTX *mem_ctx, const char *url); + +/** + variant of strcmp() that handles NULL ptrs +**/ +_PUBLIC_ int strcmp_safe(const char *s1, const char *s2); + +/** +return the number of bytes occupied by a buffer in ASCII format +the result includes the null termination +limited by 'n' bytes +**/ +_PUBLIC_ size_t ascii_len_n(const char *src, size_t n); + +/** + Set a boolean variable from the text value stored in the passed string. + Returns true in success, false if the passed string does not correctly + represent a boolean. +**/ +_PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean); + +/** + * Parse a string containing a boolean value. + * + * val will be set to the read value. + * + * @retval true if a boolean value was parsed, false otherwise. + */ +_PUBLIC_ bool conv_str_bool(const char * str, bool * val); + +/** + * Convert a size specification like 16K into an integral number of bytes. + **/ +_PUBLIC_ bool conv_str_size_error(const char * str, uint64_t * val); + +/** + * Parse a uint64_t value from a string + * + * val will be set to the value read. + * + * @retval true if parsing was successful, false otherwise + */ +_PUBLIC_ bool conv_str_u64(const char * str, uint64_t * val); + +/** + * @brief Constant time compare to memory regions. + * + * @param[in] s1 The first memory region to compare. + * + * @param[in] s2 The second memory region to compare. + * + * @param[in] n The length of the memory to compare. + * + * @return true when the memory regions are equal, false if not. + */ +_PUBLIC_ bool mem_equal_const_time(const void *s1, const void *s2, size_t n); + +/** +Do a case-insensitive, whitespace-ignoring string compare. +**/ +_PUBLIC_ int strwicmp(const char *psz1, const char *psz2); + +/** + String replace. +**/ +_PUBLIC_ void string_replace(char *s, char oldc, char newc); + +/** + * Compare 2 strings. + * + * @note The comparison is case-insensitive. + **/ +_PUBLIC_ bool strequal(const char *s1, const char *s2); + +#include "util_strlist.h" + +/* The following definitions come from lib/util/util_strlist_v3.c */ + +/** + * Needed for making an "unconst" list "const" + */ +_PUBLIC_ const char **const_str_list(char **list); + +/** + * str_list_make, v3 version. The v4 version does not + * look at quoted strings with embedded blanks, so + * do NOT merge this function please! + */ +char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string, + const char *sep); + + +const char **str_list_make_v3_const(TALLOC_CTX *mem_ctx, + const char *string, + const char *sep); + +/* The following definitions come from lib/util/util_file.c */ + + +/** + * Read one line (data until next newline or eof) and allocate it + */ +_PUBLIC_ char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint); + +char *fgets_slash(TALLOC_CTX *mem_ctx, char *s2, size_t maxlen, FILE *f); + +/** +load a file into memory from a fd. +**/ +_PUBLIC_ char *fd_load(int fd, size_t *size, size_t maxsize, TALLOC_CTX *mem_ctx); + + +char **file_lines_parse(const char *p, size_t size, int *numlines, TALLOC_CTX *mem_ctx); + +/** +load a file into memory +**/ +_PUBLIC_ char *file_load(const char *fname, size_t *size, size_t maxsize, TALLOC_CTX *mem_ctx); + +/** +load a file into memory and return an array of pointers to lines in the file +must be freed with talloc_free(). +**/ +_PUBLIC_ char **file_lines_load(const char *fname, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx); + +/** +load a fd into memory and return an array of pointers to lines in the file +must be freed with talloc_free(). If convert is true calls unix_to_dos on +the list. +**/ +_PUBLIC_ char **fd_lines_load(int fd, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx); + +_PUBLIC_ bool file_save_mode(const char *fname, const void *packet, + size_t length, mode_t mode); +/** + save a lump of data into a file. Mostly used for debugging +*/ +_PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length); +_PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0); +_PUBLIC_ int fdprintf(int fd, const char *format, ...) PRINTF_ATTRIBUTE(2,3); + +/* + compare two files, return true if the two files have the same content + */ +bool file_compare(const char *path1, const char *path2); + +/* + load from a pipe into memory. + */ +char *file_ploadv(char * const argl[], size_t *size); + +/* The following definitions come from lib/util/util.c */ + + +/** + Find a suitable temporary directory. The result should be copied immediately + as it may be overwritten by a subsequent call. +**/ +_PUBLIC_ const char *tmpdir(void); + +/** + * Creates and immediately unlinks a file. Returns open file descriptor. + **/ +_PUBLIC_ int create_unlink_tmp(const char *dir); + +/** + Check if a file exists - call vfs_file_exist for samba files. +**/ +_PUBLIC_ bool file_exist(const char *fname); + +/** + * @brief Return a files modification time. + * + * @param fname The name of the file. + * + * @param mt A pointer to store the modification time. + * + * @return 0 on success, errno otherwise. + */ +_PUBLIC_ int file_modtime(const char *fname, struct timespec *mt); + +/** + Check if a directory exists. +**/ +_PUBLIC_ bool directory_exist(const char *dname); + +/** + Check file permissions. +**/ +_PUBLIC_ bool file_check_permissions(const char *fname, + uid_t uid, + mode_t file_perms, + struct stat *pst); + +/** + * Try to create the specified directory if it didn't exist. + * + * @retval true if the directory already existed and has the right permissions + * or was successfully created. + */ +_PUBLIC_ bool directory_create_or_exist(const char *dname, mode_t dir_perms); + +/** + * @brief Try to create a specified directory and the parent directory if they + * don't exist. + * + * @param[in] dname The directory path to create. + * + * @param[in] dir_perms The permission of the directories. + * + * @return true on success, false otherwise. + */ +_PUBLIC_ bool directory_create_or_exists_recursive( + const char *dname, + mode_t dir_perms); + +_PUBLIC_ bool directory_create_or_exist_strict(const char *dname, + uid_t uid, + mode_t dir_perms); + +#include "blocking.h" + +/** + Sleep for a specified number of milliseconds. +**/ +_PUBLIC_ void smb_msleep(unsigned int t); + +/** + Get my own name, return in talloc'ed storage. +**/ +_PUBLIC_ char* get_myname(TALLOC_CTX *mem_ctx); + +/** + Check if a process exists. Does this work on all unixes? +**/ +_PUBLIC_ bool process_exists_by_pid(pid_t pid); + +/** + Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping + is dealt with in posix.c +**/ +_PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type); + +/** + * Write dump of binary data to the log file. + * + * The data is only written if the log level is at least level. + * 16 zero bytes in a row are omitted + */ +_PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len); + +/** + malloc that aborts with smb_panic on fail or zero size. +**/ +_PUBLIC_ void *smb_xmalloc(size_t size); + +/** + Memdup with smb_panic on fail. +**/ +_PUBLIC_ void *smb_xmemdup(const void *p, size_t size); + +/** + strdup that aborts on malloc fail. +**/ +_PUBLIC_ char *smb_xstrdup(const char *s); + +char *smb_xstrndup(const char *s, size_t n); + +/** + Like strdup but for memory. +**/ +_PUBLIC_ void *smb_memdup(const void *p, size_t size); + +/** + * see if a range of memory is all zero. A NULL pointer is considered + * to be all zero + */ +_PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size); + +/** + realloc an array, checking for integer overflow in the array size +*/ +_PUBLIC_ void *realloc_array(void *ptr, size_t el_size, unsigned count, bool free_on_fail); + +void *malloc_array(size_t el_size, unsigned int count); + +void *memalign_array(size_t el_size, size_t align, unsigned int count); + +void *calloc_array(size_t size, size_t nmemb); + +/* The following definitions come from lib/util/fsusage.c */ + + +/** + * Retrieve amount of free disk space. + * this does all of the system specific guff to get the free disk space. + * It is derived from code in the GNU fileutils package, but has been + * considerably mangled for use here + * + * results are returned in *dfree and *dsize, in 512 byte units +*/ +_PUBLIC_ int sys_fsusage(const char *path, uint64_t *dfree, uint64_t *dsize); + +/* The following definitions come from lib/util/ms_fnmatch.c */ + + +/** + * @file + * @brief MS-style Filename matching + */ + +int ms_fnmatch_protocol(const char *pattern, const char *string, int protocol, + bool is_case_sensitive); + +/** a generic fnmatch function - uses for non-CIFS pattern matching */ +int gen_fnmatch(const char *pattern, const char *string); + +#include "become_daemon.h" + +/** + * @brief Get a password from the console. + * + * You should make sure that the buffer is an empty string! + * + * You can also use this function to ask for a username. Then you can fill the + * buffer with the username and it is shows to the users. If the users just + * presses enter the buffer will be untouched. + * + * @code + * char username[128]; + * + * snprintf(username, sizeof(username), "john"); + * + * smb_getpass("Username:", username, sizeof(username), 1, 0); + * @endcode + * + * The prompt will look like this: + * + * Username: [john] + * + * If you press enter then john is used as the username, or you can type it in + * to change it. + * + * @param[in] prompt The prompt to show to ask for the password. + * + * @param[out] buf The buffer the password should be stored. It NEEDS to be + * empty or filled out. + * + * @param[in] len The length of the buffer. + * + * @param[in] echo Should we echo what you type. + * + * @param[in] verify Should we ask for the password twice. + * + * @return 0 on success, -1 on error. + */ +_PUBLIC_ int samba_getpass(const char *prompt, char *buf, size_t len, + bool echo, bool verify); + +/** + * Load a ini-style file. + */ +bool pm_process( const char *fileName, + bool (*sfunc)(const char *, void *), + bool (*pfunc)(const char *, const char *, void *), + void *userdata); +bool pm_process_with_flags(const char *filename, + bool allow_empty_values, + bool (*sfunc)(const char *section, void *private_data), + bool (*pfunc)(const char *name, const char *value, + void *private_data), + void *private_data); + +void print_asc(int level, const uint8_t *buf,int len); +void print_asc_cb(const uint8_t *buf, int len, + void (*cb)(const char *buf, void *private_data), + void *private_data); + +/** + * Add an id to an array of ids. + * + * num should be a pointer to an integer that holds the current + * number of elements in ids. It will be updated by this function. + */ + +bool add_uid_to_array_unique(TALLOC_CTX *mem_ctx, uid_t uid, + uid_t **uids, uint32_t *num_uids); +bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, + gid_t **gids, uint32_t *num_gids); + +/** + * Allocate anonymous shared memory of the given size + */ +void *anonymous_shared_allocate(size_t bufsz); +void *anonymous_shared_resize(void *ptr, size_t new_size, bool maymove); +void anonymous_shared_free(void *ptr); + +/* + run a command as a child process, with a timeout. + + any stdout/stderr from the child will appear in the Samba logs with + the specified log levels + + If callback is set then the callback is called on completion + with the return code from the command + */ +struct tevent_context; +struct tevent_req; +struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct timeval endtime, + int stdout_log_level, + int stderr_log_level, + const char * const *argv0, ...); +int samba_runcmd_recv(struct tevent_req *req, int *perrno); +int samba_runcmd_export_stdin(struct tevent_req *req); + +#ifdef DEVELOPER +void samba_start_debugger(void); +#endif + +/* + * Samba code should use samba_tevent_context_init() instead of + * tevent_context_init() in order to get the debug output. + */ +struct tevent_context *samba_tevent_context_init(TALLOC_CTX *mem_ctx); + +/* + * if same samba code needs to use a specific tevent backend + * it can use something like this: + * + * samba_tevent_set_debug(ev, "pysmb_tevent"); + */ +void samba_tevent_set_debug(struct tevent_context *ev, const char *name); + +#endif /* _SAMBA_UTIL_H_ */ diff --git a/lib/util/select.c b/lib/util/select.c new file mode 100644 index 0000000..dc79a27 --- /dev/null +++ b/lib/util/select.c @@ -0,0 +1,61 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + Samba select/poll implementation + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/select.h" +#include "lib/util/select.h" +#include "lib/util/time.h" + +int sys_poll_intr(struct pollfd *fds, int num_fds, int timeout) +{ + int orig_timeout = timeout; + struct timespec start; + int ret; + + clock_gettime_mono(&start); + + while (true) { + struct timespec now; + int64_t elapsed; + + ret = poll(fds, num_fds, timeout); + if (ret != -1) { + break; + } + if (errno != EINTR) { + break; + } + /* Infinite timeout, no need to adjust. */ + if (timeout < 0) { + continue; + } + clock_gettime_mono(&now); + elapsed = nsec_time_diff(&now, &start) / 1000000; + timeout = orig_timeout - elapsed; + /* Unlikely, but might happen eg. when getting traced. + * Make sure we're not hanging in this case. + */ + if (timeout < 0) { + timeout = 0; + } + }; + return ret; +} diff --git a/lib/util/select.h b/lib/util/select.h new file mode 100644 index 0000000..fa1970e --- /dev/null +++ b/lib/util/select.h @@ -0,0 +1,29 @@ +/* + Unix SMB/Netbios implementation. + Samba select/poll implementation + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _select_h_ +#define _select_h_ + +#include "system/select.h" + +/* The following definitions come from lib/util/select.c */ + +int sys_poll_intr(struct pollfd *fds, int num_fds, int timeout); + +#endif diff --git a/lib/util/server_id.c b/lib/util/server_id.c new file mode 100644 index 0000000..690b9dd --- /dev/null +++ b/lib/util/server_id.c @@ -0,0 +1,229 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Bartlett 2011 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "lib/util/debug.h" +#include "lib/util/fault.h" +#include "lib/util/server_id.h" +#include "lib/util/byteorder.h" +#include "librpc/gen_ndr/server_id.h" + +bool server_id_same_process(const struct server_id *p1, + const struct server_id *p2) +{ + return ((p1->pid == p2->pid) && (p1->vnn == p2->vnn)); +} + +int server_id_cmp(const struct server_id *p1, const struct server_id *p2) +{ + if (p1->vnn != p2->vnn) { + return (p1->vnn < p2->vnn) ? -1 : 1; + } + if (p1->pid != p2->pid) { + return (p1->pid < p2->pid) ? -1 : 1; + } + if (p1->task_id != p2->task_id) { + return (p1->task_id < p2->task_id) ? -1 : 1; + } + if (p1->unique_id != p2->unique_id) { + return (p1->unique_id < p2->unique_id) ? -1 : 1; + } + return 0; +} + +bool server_id_equal(const struct server_id *p1, const struct server_id *p2) +{ + int cmp = server_id_cmp(p1, p2); + return (cmp == 0); +} + +char *server_id_str_buf(struct server_id id, struct server_id_buf *dst) +{ + if (server_id_is_disconnected(&id)) { + strlcpy(dst->buf, "disconnected", sizeof(dst->buf)); + } else if ((id.vnn == NONCLUSTER_VNN) && (id.task_id == 0)) { + snprintf(dst->buf, sizeof(dst->buf), "%llu", + (unsigned long long)id.pid); + } else if (id.vnn == NONCLUSTER_VNN) { + snprintf(dst->buf, sizeof(dst->buf), "%llu.%u", + (unsigned long long)id.pid, (unsigned)id.task_id); + } else if (id.task_id == 0) { + snprintf(dst->buf, sizeof(dst->buf), "%u:%llu", + (unsigned)id.vnn, (unsigned long long)id.pid); + } else { + snprintf(dst->buf, sizeof(dst->buf), "%u:%llu.%u", + (unsigned)id.vnn, + (unsigned long long)id.pid, + (unsigned)id.task_id); + } + return dst->buf; +} + +size_t server_id_str_buf_unique(struct server_id id, char *buf, size_t buflen) +{ + struct server_id_buf idbuf; + char unique_buf[21]; /* 2^64 is 18446744073709551616, 20 chars */ + size_t idlen, unique_len, needed; + + server_id_str_buf(id, &idbuf); + + idlen = strlen(idbuf.buf); + unique_len = snprintf(unique_buf, sizeof(unique_buf), "%"PRIu64, + id.unique_id); + needed = idlen + unique_len + 2; + + if (buflen >= needed) { + memcpy(buf, idbuf.buf, idlen); + buf[idlen] = '/'; + memcpy(buf + idlen + 1, unique_buf, unique_len+1); + } + + return needed; +} + +struct server_id server_id_from_string(uint32_t local_vnn, + const char *pid_string) +{ + struct server_id templ = { + .vnn = NONCLUSTER_VNN, .pid = UINT64_MAX + }; + struct server_id result; + int ret; + + /* + * We accept various forms with 1, 2 or 3 component forms + * because the server_id_str_buf() can print different forms, and + * we want backwards compatibility for scripts that may call + * smbclient. + */ + + result = templ; + ret = sscanf(pid_string, "%"SCNu32":%"SCNu64".%"SCNu32"/%"SCNu64, + &result.vnn, &result.pid, &result.task_id, + &result.unique_id); + if (ret == 4) { + return result; + } + + result = templ; + ret = sscanf(pid_string, "%"SCNu32":%"SCNu64".%"SCNu32, + &result.vnn, &result.pid, &result.task_id); + if (ret == 3) { + return result; + } + + result = templ; + ret = sscanf(pid_string, "%"SCNu32":%"SCNu64"/%"SCNu64, + &result.vnn, &result.pid, &result.unique_id); + if (ret == 3) { + return result; + } + + result = templ; + ret = sscanf(pid_string, "%"SCNu32":%"SCNu64, + &result.vnn, &result.pid); + if (ret == 2) { + return result; + } + + result = templ; + ret = sscanf(pid_string, "%"SCNu64".%"SCNu32"/%"SCNu64, + &result.pid, &result.task_id, &result.unique_id); + if (ret == 3) { + result.vnn = local_vnn; + return result; + } + + result = templ; + ret = sscanf(pid_string, "%"SCNu64".%"SCNu32, + &result.pid, &result.task_id); + if (ret == 2) { + result.vnn = local_vnn; + return result; + } + + result = templ; + ret = sscanf(pid_string, "%"SCNu64"/%"SCNu64, + &result.pid, &result.unique_id); + if (ret == 2) { + result.vnn = local_vnn; + return result; + } + + result = templ; + ret = sscanf(pid_string, "%"SCNu64, &result.pid); + if (ret == 1) { + result.vnn = local_vnn; + return result; + } + + if (strcmp(pid_string, "disconnected") == 0) { + server_id_set_disconnected(&result); + return result; + } + + return templ; +} + +/** + * Set the serverid to the special value that represents a disconnected + * client for (e.g.) durable handles. + */ +void server_id_set_disconnected(struct server_id *id) +{ + *id = (struct server_id) { + .pid = UINT64_MAX, + .task_id = UINT32_MAX, + .vnn = NONCLUSTER_VNN, + .unique_id = SERVERID_UNIQUE_ID_NOT_TO_VERIFY, + }; +} + +/** + * check whether a serverid is the special placeholder for + * a disconnected client + */ +bool server_id_is_disconnected(const struct server_id *id) +{ + struct server_id dis; + + SMB_ASSERT(id != NULL); + + server_id_set_disconnected(&dis); + + return server_id_equal(id, &dis); +} + +void server_id_put(uint8_t buf[SERVER_ID_BUF_LENGTH], + const struct server_id id) +{ + SBVAL(buf, 0, id.pid); + SIVAL(buf, 8, id.task_id); + SIVAL(buf, 12, id.vnn); + SBVAL(buf, 16, id.unique_id); +} + +void server_id_get(struct server_id *id, + const uint8_t buf[SERVER_ID_BUF_LENGTH]) +{ + id->pid = BVAL(buf, 0); + id->task_id = IVAL(buf, 8); + id->vnn = IVAL(buf, 12); + id->unique_id = BVAL(buf, 16); +} diff --git a/lib/util/server_id.h b/lib/util/server_id.h new file mode 100644 index 0000000..5b723d5 --- /dev/null +++ b/lib/util/server_id.h @@ -0,0 +1,57 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Bartlett 2011 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __LIB_UTIL_SERVER_ID_H__ +#define __LIB_UTIL_SERVER_ID_H__ + +#include "replace.h" + +struct server_id; + +struct server_id_buf { char buf[48]; }; /* probably a bit too large ... */ + +bool server_id_same_process(const struct server_id *p1, + const struct server_id *p2); +int server_id_cmp(const struct server_id *p1, const struct server_id *p2); +bool server_id_equal(const struct server_id *p1, const struct server_id *p2); +char *server_id_str_buf(struct server_id id, struct server_id_buf *dst); +size_t server_id_str_buf_unique(struct server_id id, char *buf, size_t buflen); + +struct server_id server_id_from_string(uint32_t local_vnn, + const char *pid_string); + +/** + * Set the serverid to the special value that represents a disconnected + * client for (e.g.) durable handles. + */ +void server_id_set_disconnected(struct server_id *id); + +/** + * check whether a serverid is the special placeholder for + * a disconnected client + */ +bool server_id_is_disconnected(const struct server_id *id); + +#define SERVER_ID_BUF_LENGTH 24 +void server_id_put(uint8_t buf[SERVER_ID_BUF_LENGTH], + const struct server_id id); +void server_id_get(struct server_id *id, + const uint8_t buf[SERVER_ID_BUF_LENGTH]); + +#endif diff --git a/lib/util/server_id_db.c b/lib/util/server_id_db.c new file mode 100644 index 0000000..17b1577 --- /dev/null +++ b/lib/util/server_id_db.c @@ -0,0 +1,355 @@ +/* + * Map names to server_ids + * + * Copyright Volker Lendecke <vl@samba.org> 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/filesys.h" +#include "lib/util/server_id.h" +#include "lib/util/server_id_db.h" +#include "lib/tdb_wrap/tdb_wrap.h" +#include "lib/util/strv.h" +#include "lib/util/util_tdb.h" +#include "lib/util/samba_util.h" + +static TDB_DATA talloc_tdb_data(void *ptr) +{ + return (TDB_DATA) { .dptr = ptr, .dsize = talloc_get_size(ptr) }; +} + +struct server_id_db { + struct server_id pid; + struct tdb_wrap *tdb; + char *names; +}; + +static int server_id_db_destructor(struct server_id_db *db); + +struct server_id_db *server_id_db_init(TALLOC_CTX *mem_ctx, + struct server_id pid, + const char *base_path, + int hash_size, int tdb_flags) +{ + struct server_id_db *db; + size_t pathlen = strlen(base_path) + 11; + char path[pathlen]; + + db = talloc(mem_ctx, struct server_id_db); + if (db == NULL) { + return NULL; + } + db->pid = pid; + db->names = NULL; + + snprintf(path, pathlen, "%s/names.tdb", base_path); + + db->tdb = tdb_wrap_open(db, path, hash_size, tdb_flags, + O_RDWR|O_CREAT, 0660); + if (db->tdb == NULL) { + TALLOC_FREE(db); + return NULL; + } + + talloc_set_destructor(db, server_id_db_destructor); + + return db; +} + +void server_id_db_reinit(struct server_id_db *db, struct server_id pid) +{ + db->pid = pid; + TALLOC_FREE(db->names); +} + +struct server_id server_id_db_pid(struct server_id_db *db) +{ + return db->pid; +} + +static int server_id_db_destructor(struct server_id_db *db) +{ + char *name = NULL; + + while ((name = strv_next(db->names, name)) != NULL) { + server_id_db_remove(db, name); + } + + return 0; +} + +int server_id_db_add(struct server_id_db *db, const char *name) +{ + struct tdb_context *tdb = db->tdb->tdb; + TDB_DATA key; + char *n; + int ret; + + n = strv_find(db->names, name); + if (n != NULL) { + return EEXIST; + } + + ret = strv_add(db, &db->names, name); + if (ret != 0) { + return ret; + } + + key = string_term_tdb_data(name); + + { + size_t idlen = server_id_str_buf_unique(db->pid, NULL, 0); + char idbuf[idlen]; + + server_id_str_buf_unique(db->pid, idbuf, idlen); + + ret = tdb_append( + tdb, key, + (TDB_DATA) { .dptr = (uint8_t *)idbuf, .dsize = idlen }); + } + + if (ret != 0) { + enum TDB_ERROR err = tdb_error(tdb); + strv_delete(&db->names, strv_find(db->names, name)); + return map_unix_error_from_tdb(err); + } + + return 0; +} + +int server_id_db_prune_name(struct server_id_db *db, const char *name, + struct server_id server) +{ + struct tdb_context *tdb = db->tdb->tdb; + size_t idbuf_len = server_id_str_buf_unique(server, NULL, 0); + char idbuf[idbuf_len]; + TDB_DATA key; + uint8_t *data; + size_t datalen; + char *ids, *id; + int ret; + + key = string_term_tdb_data(name); + server_id_str_buf_unique(server, idbuf, idbuf_len); + + ret = tdb_chainlock(tdb, key); + if (ret == -1) { + enum TDB_ERROR err = tdb_error(tdb); + return map_unix_error_from_tdb(err); + } + + ret = tdb_fetch_talloc(tdb, key, db, &data); + if (ret != 0) { + tdb_chainunlock(tdb, key); + return ret; + } + + datalen = talloc_get_size(data); + if ((datalen == 0) || (data[datalen-1] != '\0')) { + tdb_chainunlock(tdb, key); + TALLOC_FREE(data); + return EINVAL; + } + + ids = (char *)data; + + id = strv_find(ids, idbuf); + if (id == NULL) { + tdb_chainunlock(tdb, key); + TALLOC_FREE(data); + return ENOENT; + } + + strv_delete(&ids, id); + + if (talloc_get_size(ids) == 0) { + ret = tdb_delete(tdb, key); + } else { + ret = tdb_store(tdb, key, talloc_tdb_data(ids), TDB_MODIFY); + } + TALLOC_FREE(data); + + tdb_chainunlock(tdb, key); + + if (ret == -1) { + enum TDB_ERROR err = tdb_error(tdb); + return map_unix_error_from_tdb(err); + } + + return 0; +} + +int server_id_db_remove(struct server_id_db *db, const char *name) +{ + char *n; + int ret; + + n = strv_find(db->names, name); + if (n == NULL) { + return ENOENT; + } + + ret = server_id_db_prune_name(db, name, db->pid); + if (ret != 0) { + return ret; + } + + strv_delete(&db->names, n); + return 0; +} + +int server_id_db_lookup(struct server_id_db *db, const char *name, + TALLOC_CTX *mem_ctx, unsigned *pnum_servers, + struct server_id **pservers) +{ + struct tdb_context *tdb = db->tdb->tdb; + TDB_DATA key; + uint8_t *data; + size_t datalen; + char *ids, *id; + unsigned num_servers; + struct server_id *servers; + int i, ret; + + key = string_term_tdb_data(name); + + ret = tdb_fetch_talloc(tdb, key, mem_ctx, &data); + if (ret != 0) { + return ret; + } + + datalen = talloc_get_size(data); + if ((datalen == 0) || (data[datalen-1] != '\0')) { + TALLOC_FREE(data); + return EINVAL; + } + + ids = (char *)data; + num_servers = strv_count(ids); + + servers = talloc_array(mem_ctx, struct server_id, num_servers); + if (servers == NULL) { + TALLOC_FREE(data); + return ENOMEM; + } + + i = 0; + + for (id = ids; id != NULL; id = strv_next(ids, id)) { + servers[i++] = server_id_from_string(NONCLUSTER_VNN, id); + } + + TALLOC_FREE(data); + + *pnum_servers = num_servers; + *pservers = servers; + + return 0; +} + +bool server_id_db_lookup_one(struct server_id_db *db, const char *name, + struct server_id *server) +{ + int ret; + unsigned num_servers; + struct server_id *servers; + + ret = server_id_db_lookup(db, name, db, &num_servers, &servers); + if (ret != 0) { + return false; + } + if (num_servers == 0) { + TALLOC_FREE(servers); + return false; + } + *server = servers[0]; + TALLOC_FREE(servers); + return true; +} + +struct server_id_db_traverse_state { + TALLOC_CTX *mem_ctx; + int (*fn)(const char *name, + unsigned num_servers, + const struct server_id *servers, + void *private_data); + void *private_data; +}; + +static int server_id_db_traverse_fn(struct tdb_context *tdb, + TDB_DATA key, TDB_DATA data, + void *private_data) +{ + struct server_id_db_traverse_state *state = private_data; + const char *name; + char *ids, *id; + unsigned num_servers; + struct server_id *servers; + int i, ret; + + if (key.dsize == 0) { + return 0; + } + if (key.dptr[key.dsize-1] != '\0') { + return 0; + } + name = (const char *)key.dptr; + + ids = (char *)talloc_memdup(state->mem_ctx, data.dptr, data.dsize); + if (ids == NULL) { + return 0; + } + + num_servers = strv_count(ids); + servers = talloc_array(ids, struct server_id, num_servers); + + i = 0; + + for (id = ids; id != NULL; id = strv_next(ids, id)) { + servers[i++] = server_id_from_string(NONCLUSTER_VNN, id); + } + + ret = state->fn(name, num_servers, servers, state->private_data); + + TALLOC_FREE(ids); + + return ret; +} + +int server_id_db_traverse_read(struct server_id_db *db, + int (*fn)(const char *name, + unsigned num_servers, + const struct server_id *servers, + void *private_data), + void *private_data) +{ + struct server_id_db_traverse_state state; + int ret; + + state = (struct server_id_db_traverse_state) { + .fn = fn, .private_data = private_data, + .mem_ctx = talloc_new(db) + }; + + if (state.mem_ctx == NULL) { + return ENOMEM; + } + + ret = tdb_traverse_read(db->tdb->tdb, server_id_db_traverse_fn, + &state); + TALLOC_FREE(state.mem_ctx); + return ret; +} diff --git a/lib/util/server_id_db.h b/lib/util/server_id_db.h new file mode 100644 index 0000000..2dcce62 --- /dev/null +++ b/lib/util/server_id_db.h @@ -0,0 +1,50 @@ +/* + * Namedb + * + * Copyright Volker Lendecke <vl@samba.org> 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SERVER_ID_DB_H_ +#define _SERVER_ID_DB_H_ + +#include "talloc.h" +#include "librpc/gen_ndr/server_id.h" + +struct server_id_db; + +struct server_id_db *server_id_db_init(TALLOC_CTX *mem_ctx, + struct server_id pid, + const char *base_path, + int hash_size, int tdb_flags); +void server_id_db_reinit(struct server_id_db *db, struct server_id pid); +struct server_id server_id_db_pid(struct server_id_db *db); +int server_id_db_add(struct server_id_db *db, const char *name); +int server_id_db_remove(struct server_id_db *db, const char *name); +int server_id_db_prune_name(struct server_id_db *db, const char *name, + struct server_id server); +int server_id_db_lookup(struct server_id_db *db, const char *name, + TALLOC_CTX *mem_ctx, unsigned *num_servers, + struct server_id **servers); +bool server_id_db_lookup_one(struct server_id_db *db, const char *name, + struct server_id *server); +int server_id_db_traverse_read(struct server_id_db *db, + int (*fn)(const char *name, + unsigned num_servers, + const struct server_id *servers, + void *private_data), + void *private_data); + +#endif diff --git a/lib/util/setid.c b/lib/util/setid.c new file mode 100644 index 0000000..1001461 --- /dev/null +++ b/lib/util/setid.c @@ -0,0 +1,249 @@ +/* + Unix SMB/CIFS implementation. + setXXid() functions for Samba. + Copyright (C) Jeremy Allison 2012 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef AUTOCONF_TEST +#include "replace.h" +#include "system/passwd.h" + +#include "../lib/util/setid.h" + +#else + +/* Inside autoconf test. */ +#if defined(HAVE_UNISTD_H) +#include <unistd.h> +#endif +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <errno.h> + +#if defined(HAVE_UNISTD_H) +#include <unistd.h> +#endif +#ifdef HAVE_SYS_PRIV_H +#include <sys/priv.h> +#endif +#ifdef HAVE_SYS_ID_H +#include <sys/id.h> +#endif + +/* autoconf tests don't include setid.h */ +int samba_setresuid(uid_t ruid, uid_t euid, uid_t suid); +int samba_setresgid(gid_t rgid, gid_t egid, gid_t sgid); +int samba_setreuid(uid_t ruid, uid_t euid); +int samba_setregid(gid_t rgid, gid_t egid); +int samba_seteuid(uid_t euid); +int samba_setegid(gid_t egid); +int samba_setuid(uid_t uid); +int samba_setgid(gid_t gid); +int samba_setuidx(int flags, uid_t uid); +int samba_setgidx(int flags, gid_t gid); +int samba_setgroups(size_t setlen, const gid_t *gidset); + +#endif + +#if defined(HAVE_LINUX_THREAD_CREDENTIALS) +#if defined(HAVE_SYSCALL_H) +#include <syscall.h> +#endif + +#if defined(HAVE_SYS_SYSCALL_H) +#include <sys/syscall.h> +#endif + +/* Ensure we can't compile in a mixed syscall setup. */ +#if !defined(USE_LINUX_32BIT_SYSCALLS) +#if defined(SYS_setresuid32) || defined(SYS_setresgid32) || defined(SYS_setreuid32) || defined(SYS_setregid32) || defined(SYS_setuid32) || defined(SYS_setgid32) || defined(SYS_setgroups32) +#error Mixture of 32-bit Linux system calls and 64-bit calls. +#endif +#endif + +#endif + +/* All the setXX[ug]id functions and setgroups Samba uses. */ +int samba_setresuid(uid_t ruid, uid_t euid, uid_t suid) +{ +#if defined(HAVE_LINUX_THREAD_CREDENTIALS) +#if defined(USE_LINUX_32BIT_SYSCALLS) + return syscall(SYS_setresuid32, ruid, euid, suid); +#else + return syscall(SYS_setresuid, ruid, euid, suid); +#endif +#elif defined(HAVE_SETRESUID) + return setresuid(ruid, euid, suid); +#else + errno = ENOSYS; + return -1; +#endif +} + +int samba_setresgid(gid_t rgid, gid_t egid, gid_t sgid) +{ +#if defined(HAVE_LINUX_THREAD_CREDENTIALS) +#if defined(USE_LINUX_32BIT_SYSCALLS) + return syscall(SYS_setresgid32, rgid, egid, sgid); +#else + return syscall(SYS_setresgid, rgid, egid, sgid); +#endif +#elif defined(HAVE_SETRESGID) + return setresgid(rgid, egid, sgid); +#else + errno = ENOSYS; + return -1; +#endif +} + +int samba_setreuid(uid_t ruid, uid_t euid) +{ +#if defined(HAVE_LINUX_THREAD_CREDENTIALS) +#if defined(USE_LINUX_32BIT_SYSCALLS) + return syscall(SYS_setreuid32, ruid, euid); +#else + return syscall(SYS_setreuid, ruid, euid); +#endif +#elif defined(HAVE_SETREUID) + return setreuid(ruid, euid); +#else + errno = ENOSYS; + return -1; +#endif +} + +int samba_setregid(gid_t rgid, gid_t egid) +{ +#if defined(HAVE_LINUX_THREAD_CREDENTIALS) +#if defined(USE_LINUX_32BIT_SYSCALLS) + return syscall(SYS_setregid32, rgid, egid); +#else + return syscall(SYS_setregid, rgid, egid); +#endif +#elif defined(HAVE_SETREGID) + return setregid(rgid, egid); +#else + errno = ENOSYS; + return -1; +#endif +} + +int samba_seteuid(uid_t euid) +{ +#if defined(HAVE_LINUX_THREAD_CREDENTIALS) +#if defined(USE_LINUX_32BIT_SYSCALLS) + /* seteuid is not a separate system call. */ + return syscall(SYS_setresuid32, -1, euid, -1); +#else + /* seteuid is not a separate system call. */ + return syscall(SYS_setresuid, -1, euid, -1); +#endif +#elif defined(HAVE_SETEUID) + return seteuid(euid); +#else + errno = ENOSYS; + return -1; +#endif +} + +int samba_setegid(gid_t egid) +{ +#if defined(HAVE_LINUX_THREAD_CREDENTIALS) +#if defined(USE_LINUX_32BIT_SYSCALLS) + /* setegid is not a separate system call. */ + return syscall(SYS_setresgid32, -1, egid, -1); +#else + /* setegid is not a separate system call. */ + return syscall(SYS_setresgid, -1, egid, -1); +#endif +#elif defined(HAVE_SETEGID) + return setegid(egid); +#else + errno = ENOSYS; + return -1; +#endif +} + +int samba_setuid(uid_t uid) +{ +#if defined(HAVE_LINUX_THREAD_CREDENTIALS) +#if defined(USE_LINUX_32BIT_SYSCALLS) + return syscall(SYS_setuid32, uid); +#else + return syscall(SYS_setuid, uid); +#endif +#elif defined(HAVE_SETUID) + return setuid(uid); +#else + errno = ENOSYS; + return -1; +#endif +} + +int samba_setgid(gid_t gid) +{ +#if defined(HAVE_LINUX_THREAD_CREDENTIALS) +#if defined(USE_LINUX_32BIT_SYSCALLS) + return syscall(SYS_setgid32, gid); +#else + return syscall(SYS_setgid, gid); +#endif +#elif defined(HAVE_SETGID) + return setgid(gid); +#else + errno = ENOSYS; + return -1; +#endif +} + +int samba_setuidx(int flags, uid_t uid) +{ +#if defined(HAVE_SETUIDX) + return setuidx(flags, uid); +#else + /* HAVE_LINUX_THREAD_CREDENTIALS doesn't have this. */ + errno = ENOSYS; + return -1; +#endif +} + +int samba_setgidx(int flags, gid_t gid) +{ +#if defined(HAVE_SETGIDX) + return setgidx(flags, gid); +#else + /* HAVE_LINUX_THREAD_CREDENTIALS doesn't have this. */ + errno = ENOSYS; + return -1; +#endif +} + +int samba_setgroups(size_t setlen, const gid_t *gidset) +{ +#if defined(HAVE_LINUX_THREAD_CREDENTIALS) +#if defined(USE_LINUX_32BIT_SYSCALLS) + return syscall(SYS_setgroups32, setlen, gidset); +#else + return syscall(SYS_setgroups, setlen, gidset); +#endif +#elif defined(HAVE_SETGROUPS) + return setgroups(setlen, gidset); +#else + errno = ENOSYS; + return -1; +#endif +} diff --git a/lib/util/setid.h b/lib/util/setid.h new file mode 100644 index 0000000..59ae44c --- /dev/null +++ b/lib/util/setid.h @@ -0,0 +1,43 @@ +/* + Unix SMB/CIFS implementation. + setXXid() functions for Samba. + Copyright (C) Jeremy Allison 2012 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SETID_H +#define _SETID_H + +/* + * NB. We don't wrap initgroups although on some systems + * this can call setgroups. On systems with thread-specific + * credentials (Linux so far) we know they have getgrouplist() + * which doesn't make a system call. + */ + +/* All the setXX[ug]id functions and setgroups Samba uses. */ +int samba_setresuid(uid_t ruid, uid_t euid, uid_t suid); +int samba_setresgid(gid_t rgid, gid_t egid, gid_t sgid); +int samba_setreuid(uid_t ruid, uid_t euid); +int samba_setregid(gid_t rgid, gid_t egid); +int samba_seteuid(uid_t euid); +int samba_setegid(gid_t egid); +int samba_setuid(uid_t uid); +int samba_setgid(gid_t gid); +int samba_setuidx(int flags, uid_t uid); +int samba_setgidx(int flags, gid_t gid); +int samba_setgroups(size_t setlen, const gid_t *gidset); + +#endif diff --git a/lib/util/signal.c b/lib/util/signal.c new file mode 100644 index 0000000..3fc63b2 --- /dev/null +++ b/lib/util/signal.c @@ -0,0 +1,146 @@ +/* + Unix SMB/CIFS implementation. + signal handling functions + + Copyright (C) Andrew Tridgell 1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/wait.h" +#include "debug.h" +#include "lib/util/signal.h" /* Avoid /usr/include/signal.h */ + +/** + * @file + * @brief Signal handling + */ + +/**************************************************************************** + Catch child exits and reap the child zombie status. +****************************************************************************/ + +static void sig_cld(int signum) +{ + while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) + ; + + /* + * Turns out it's *really* important not to + * restore the signal handler here if we have real POSIX + * signal handling. If we do, then we get the signal re-delivered + * immediately - hey presto - instant loop ! JRA. + */ + +#if !defined(HAVE_SIGACTION) + CatchSignal(SIGCLD, sig_cld); +#endif +} + +/**************************************************************************** +catch child exits - leave status; +****************************************************************************/ + +static void sig_cld_leave_status(int signum) +{ + /* + * Turns out it's *really* important not to + * restore the signal handler here if we have real POSIX + * signal handling. If we do, then we get the signal re-delivered + * immediately - hey presto - instant loop ! JRA. + */ + +#if !defined(HAVE_SIGACTION) + CatchSignal(SIGCLD, sig_cld_leave_status); +#endif +} + +/** + Block sigs. +**/ + +void BlockSignals(bool block, int signum) +{ +#ifdef HAVE_SIGPROCMASK + sigset_t set; + sigemptyset(&set); + sigaddset(&set,signum); + sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL); +#elif defined(HAVE_SIGBLOCK) + if (block) { + sigblock(sigmask(signum)); + } else { + sigsetmask(siggetmask() & ~sigmask(signum)); + } +#else + /* yikes! This platform can't block signals? */ + static int done; + if (!done) { + DEBUG(0,("WARNING: No signal blocking available\n")); + done=1; + } +#endif +} + +/** + Catch a signal. This should implement the following semantics: + + 1) The handler remains installed after being called. + 2) The signal should be blocked during handler execution. +**/ + +void (*CatchSignal(int signum,void (*handler)(int )))(int) +{ +#ifdef HAVE_SIGACTION + struct sigaction act; + struct sigaction oldact; + + ZERO_STRUCT(act); + + act.sa_handler = handler; +#ifdef SA_RESTART + /* + * We *want* SIGALRM to interrupt a system call. + */ + if(signum != SIGALRM) + act.sa_flags = SA_RESTART; +#endif + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask,signum); + sigaction(signum,&act,&oldact); + return oldact.sa_handler; +#else /* !HAVE_SIGACTION */ + /* FIXME: need to handle sigvec and systems with broken signal() */ + return signal(signum, handler); +#endif +} + +/** + Ignore SIGCLD via whatever means is necessary for this OS. +**/ + +void (*CatchChild(void))(int) +{ + return CatchSignal(SIGCLD, sig_cld); +} + +/** + Catch SIGCLD but leave the child around so it's status can be reaped. +**/ + +void (*CatchChildLeaveStatus(void))(int) +{ + return CatchSignal(SIGCLD, sig_cld_leave_status); +} diff --git a/lib/util/signal.h b/lib/util/signal.h new file mode 100644 index 0000000..f662ee1 --- /dev/null +++ b/lib/util/signal.h @@ -0,0 +1,50 @@ +/* + Unix SMB/CIFS implementation. + signal handling functions + + Copyright (C) Andrew Tridgell 1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_UTIL_SIGNAL_H_ +#define _SAMBA_UTIL_SIGNAL_H_ + +#include <signal.h> +#include <stdbool.h> + +/** + Block sigs. +**/ +void BlockSignals(bool block, int signum); + +/** + Catch a signal. This should implement the following semantics: + + 1) The handler remains installed after being called. + 2) The signal should be blocked during handler execution. +**/ +void (*CatchSignal(int signum,void (*handler)(int )))(int); + +/** + Ignore SIGCLD via whatever means is necessary for this OS. +**/ +void (*CatchChild(void))(int); + +/** + Catch SIGCLD but leave the child around so it's status can be reaped. +**/ +void (*CatchChildLeaveStatus(void))(int); + +#endif /* _SAMBA_UTIL_SIGNAL_H_ */ diff --git a/lib/util/smb_strtox.c b/lib/util/smb_strtox.c new file mode 100644 index 0000000..7a477dc --- /dev/null +++ b/lib/util/smb_strtox.c @@ -0,0 +1,177 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) Swen Schillig 2019 + * + * ** NOTE! The following LGPL license applies to this file. + * ** This does NOT imply that all of Samba is released + * ** under the LGPL + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "smb_strtox.h" + +/** + * Convert a string to an unsigned long integer + * + * @param nptr pointer to string which is to be converted + * @param endptr [optional] reference to remainder of the string + * @param base base of the numbering scheme + * @param err error occurred during conversion + * @flags controlling conversion feature + * @result result of the conversion as provided by strtoul + * + * The following flags are supported + * SMB_STR_STANDARD # raise error if negative or non-numeric + * SMB_STR_ALLOW_NEGATIVE # allow strings with a leading "-" + * SMB_STR_FULL_STR_CONV # entire string must be converted + * SMB_STR_ALLOW_NO_CONVERSION # allow empty strings or non-numeric + * SMB_STR_GLIBC_STANDARD # act exactly as the standard glibc strtoul + * + * The following errors are detected + * - wrong base + * - value overflow + * - string with a leading "-" indicating a negative number + * - no conversion due to empty string or not representing a number + */ +unsigned long int +smb_strtoul(const char *nptr, char **endptr, int base, int *err, int flags) +{ + unsigned long int val; + int saved_errno = errno; + char *needle = NULL; + char *tmp_endptr = NULL; + + errno = 0; + *err = 0; + + val = strtoul(nptr, &tmp_endptr, base); + + if (endptr != NULL) { + *endptr = tmp_endptr; + } + + if (errno != 0) { + *err = errno; + errno = saved_errno; + return val; + } + + if ((flags & SMB_STR_ALLOW_NO_CONVERSION) == 0) { + /* got an invalid number-string resulting in no conversion */ + if (nptr == tmp_endptr) { + *err = EINVAL; + goto out; + } + } + + if ((flags & SMB_STR_ALLOW_NEGATIVE ) == 0) { + /* did we convert a negative "number" ? */ + needle = strchr(nptr, '-'); + if (needle != NULL && needle < tmp_endptr) { + *err = EINVAL; + goto out; + } + } + + if ((flags & SMB_STR_FULL_STR_CONV) != 0) { + /* did we convert the entire string ? */ + if (tmp_endptr[0] != '\0') { + *err = EINVAL; + goto out; + } + } + +out: + errno = saved_errno; + return val; +} + +/** + * Convert a string to an unsigned long long integer + * + * @param nptr pointer to string which is to be converted + * @param endptr [optional] reference to remainder of the string + * @param base base of the numbering scheme + * @param err error occurred during conversion + * @flags controlling conversion feature + * @result result of the conversion as provided by strtoull + * + * The following flags are supported + * SMB_STR_STANDARD # raise error if negative or non-numeric + * SMB_STR_ALLOW_NEGATIVE # allow strings with a leading "-" + * SMB_STR_FULL_STR_CONV # entire string must be converted + * SMB_STR_ALLOW_NO_CONVERSION # allow empty strings or non-numeric + * SMB_STR_GLIBC_STANDARD # act exactly as the standard glibc strtoul + * + * The following errors are detected + * - wrong base + * - value overflow + * - string with a leading "-" indicating a negative number + * - no conversion due to empty string or not representing a number + */ +unsigned long long int +smb_strtoull(const char *nptr, char **endptr, int base, int *err, int flags) +{ + unsigned long long int val; + int saved_errno = errno; + char *needle = NULL; + char *tmp_endptr = NULL; + + errno = 0; + *err = 0; + + val = strtoull(nptr, &tmp_endptr, base); + + if (endptr != NULL) { + *endptr = tmp_endptr; + } + + if (errno != 0) { + *err = errno; + errno = saved_errno; + return val; + } + + if ((flags & SMB_STR_ALLOW_NO_CONVERSION) == 0) { + /* got an invalid number-string resulting in no conversion */ + if (nptr == tmp_endptr) { + *err = EINVAL; + goto out; + } + } + + if ((flags & SMB_STR_ALLOW_NEGATIVE ) == 0) { + /* did we convert a negative "number" ? */ + needle = strchr(nptr, '-'); + if (needle != NULL && needle < tmp_endptr) { + *err = EINVAL; + goto out; + } + } + + if ((flags & SMB_STR_FULL_STR_CONV) != 0) { + /* did we convert the entire string ? */ + if (tmp_endptr[0] != '\0') { + *err = EINVAL; + goto out; + } + } + +out: + errno = saved_errno; + return val; +} diff --git a/lib/util/smb_strtox.h b/lib/util/smb_strtox.h new file mode 100644 index 0000000..fcbedbe --- /dev/null +++ b/lib/util/smb_strtox.h @@ -0,0 +1,40 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) Swen Schillig 2019 + * + * ** NOTE! The following LGPL license applies to this file. + * ** This does NOT imply that all of Samba is released + * ** under the LGPL + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SMB_STRTOX_H +#define SMB_STRTOX_H + +#define SMB_STR_STANDARD 0x00 +#define SMB_STR_ALLOW_NEGATIVE 0x01 +#define SMB_STR_FULL_STR_CONV 0x02 +#define SMB_STR_ALLOW_NO_CONVERSION 0x04 +#define SMB_STR_GLIBC_STANDARD (SMB_STR_ALLOW_NO_CONVERSION | \ + SMB_STR_ALLOW_NEGATIVE) + +unsigned long int +smb_strtoul(const char *nptr, char **endptr, int base, int *err, int flags); + +unsigned long long int +smb_strtoull(const char *nptr, char **endptr, int base, int *err, int flags); + +#endif diff --git a/lib/util/smb_threads.c b/lib/util/smb_threads.c new file mode 100644 index 0000000..421dac9 --- /dev/null +++ b/lib/util/smb_threads.c @@ -0,0 +1,206 @@ +/* + Unix SMB/CIFS implementation. + SMB client library implementation (thread interface functions). + Copyright (C) Jeremy Allison, 2009. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * This code is based in the ideas in openssl + * but somewhat simpler and expended to include + * thread local storage. + */ + +#include "replace.h" +#include "smb_threads.h" +#include "smb_threads_internal.h" +#include "lib/util/debug.h" +#include "lib/util/fault.h" +#include "lib/util/memory.h" + +/********************************************************* + Functions to vector the locking primitives used internally + by libsmbclient. +*********************************************************/ + +const struct smb_thread_functions *global_tfp; + +/********************************************************* + Dynamic lock array. +*********************************************************/ + +void **global_lock_array; + +/********************************************************* + Mutex used for our internal "once" function +*********************************************************/ + +static void *once_mutex = NULL; + + +/********************************************************* + Function to set the locking primitives used by libsmbclient. +*********************************************************/ + +int smb_thread_set_functions(const struct smb_thread_functions *tf) +{ + int i; + + global_tfp = tf; + +#if defined(PARANOID_MALLOC_CHECKER) +#ifdef malloc +#undef malloc +#endif +#endif + + /* Here we initialize any static locks we're using. */ + global_lock_array = (void **)malloc(sizeof(void *) *NUM_GLOBAL_LOCKS); + +#if defined(PARANOID_MALLOC_CHECKER) +#define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY +#endif + + if (global_lock_array == NULL) { + return ENOMEM; + } + + for (i = 0; i < NUM_GLOBAL_LOCKS; i++) { + char *name = NULL; + if (asprintf(&name, "global_lock_%d", i) == -1) { + SAFE_FREE(global_lock_array); + return ENOMEM; + } + if (global_tfp->create_mutex(name, + &global_lock_array[i], + __location__)) { + smb_panic("smb_thread_set_functions: create mutexes failed"); + } + SAFE_FREE(name); + } + + /* Create the mutex we'll use for our "once" function */ + if (SMB_THREAD_CREATE_MUTEX("smb_once", once_mutex) != 0) { + smb_panic("smb_thread_set_functions: failed to create 'once' mutex"); + } + + return 0; +} + +/******************************************************************* + Call a function only once. We implement this ourselves + using our own mutex rather than using the thread implementation's + *_once() function because each implementation has its own + type for the variable which keeps track of whether the function + has been called, and there's no easy way to allocate the correct + size variable in code internal to Samba without knowing the + implementation's "once" type. +********************************************************************/ + +int smb_thread_once(smb_thread_once_t *ponce, + void (*init_fn)(void *pdata), + void *pdata) +{ + int ret; + + /* Lock our "once" mutex in order to test and initialize ponce */ + if (SMB_THREAD_LOCK(once_mutex) != 0) { + smb_panic("error locking 'once'"); + } + + /* Keep track of whether we ran their init function */ + ret = ! *ponce; + + /* + * See if another thread got here after we tested it initially but + * before we got our lock. + */ + if (! *ponce) { + /* Nope, we need to run the initialization function */ + (*init_fn)(pdata); + + /* Now we can indicate that the function has been run */ + *ponce = true; + } + + /* Unlock the mutex */ + if (SMB_THREAD_UNLOCK(once_mutex) != 0) { + smb_panic("error unlocking 'once'"); + } + + /* + * Tell 'em whether we ran their init function. If they passed a data + * pointer to the init function and the init function could change + * something in the pointed-to data, this will tell them whether that + * data is valid or not. + */ + return ret; +} + + +#if 0 +/* Test. - pthread implementations. */ +#include <pthread.h> + +#ifdef malloc +#undef malloc +#endif + +SMB_THREADS_DEF_PTHREAD_IMPLEMENTATION(tf); + +static smb_thread_once_t ot = SMB_THREAD_ONCE_INIT; +void *pkey = NULL; + +static void init_fn(void) +{ + int ret; + + if (!global_tfp) { + /* Non-thread safe init case. */ + if (ot) { + return; + } + ot = true; + } + + if ((ret = SMB_THREAD_CREATE_TLS("test_tls", pkey)) != 0) { + printf("Create tls once error: %d\n", ret); + } +} + +/* Test function. */ +int test_threads(void) +{ + int ret; + void *plock = NULL; + smb_thread_set_functions(&tf); + + SMB_THREAD_ONCE(&ot, init_fn); + + if ((ret = SMB_THREAD_CREATE_MUTEX("test", plock)) != 0) { + printf("Create lock error: %d\n", ret); + } + if ((ret = SMB_THREAD_LOCK(plock, SMB_THREAD_LOCK)) != 0) { + printf("lock error: %d\n", ret); + } + if ((ret = SMB_THREAD_LOCK(plock, SMB_THREAD_UNLOCK)) != 0) { + printf("unlock error: %d\n", ret); + } + SMB_THREAD_DESTROY_MUTEX(plock); + SMB_THREAD_DESTROY_TLS(pkey); + + return 0; +} +#endif diff --git a/lib/util/smb_threads.h b/lib/util/smb_threads.h new file mode 100644 index 0000000..67d05b8 --- /dev/null +++ b/lib/util/smb_threads.h @@ -0,0 +1,137 @@ +/* + Unix SMB/CIFS implementation. + SMB thread interface functions. + Copyright (C) Jeremy Allison, 2009. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _smb_threads_h_ +#define _smb_threads_h_ + +typedef bool smb_thread_once_t; +#define SMB_THREAD_ONCE_INIT false + +enum smb_thread_lock_type { + SMB_THREAD_LOCK = 1, + SMB_THREAD_UNLOCK +}; + +struct smb_thread_functions { + /* Mutex and tls functions. */ + int (*create_mutex)(const char *lockname, + void **pplock, + const char *location); + void (*destroy_mutex)(void *plock, + const char *location); + int (*lock_mutex)(void *plock, + int lock_type, + const char *location); + + /* Thread local storage. */ + int (*create_tls)(const char *keyname, + void **ppkey, + const char *location); + void (*destroy_tls)(void **pkey, + const char *location); + int (*set_tls)(void *pkey, const void *pval, const char *location); + void *(*get_tls)(void *pkey, const char *location); +}; + +int smb_thread_set_functions(const struct smb_thread_functions *tf); +int smb_thread_once(smb_thread_once_t *ponce, + void (*init_fn)(void *pdata), + void *pdata); + +extern const struct smb_thread_functions *global_tfp; + +/* Define the pthread version of the functions. */ + +#define SMB_THREADS_DEF_PTHREAD_IMPLEMENTATION(tf) \ + \ +static int smb_create_mutex_pthread(const char *lockname, void **pplock, const char *location) \ +{ \ + pthread_mutex_t *pmut = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); \ + if (!pmut) { \ + return ENOMEM; \ + } \ + pthread_mutex_init(pmut, NULL); \ + *pplock = (void *)pmut; \ + return 0; \ +} \ + \ +static void smb_destroy_mutex_pthread(void *plock, const char *location) \ +{ \ + pthread_mutex_destroy((pthread_mutex_t *)plock); \ + free(plock); \ +} \ + \ +static int smb_lock_pthread(void *plock, int lock_type, const char *location) \ +{ \ + if (lock_type == SMB_THREAD_UNLOCK) { \ + return pthread_mutex_unlock((pthread_mutex_t *)plock); \ + } else { \ + return pthread_mutex_lock((pthread_mutex_t *)plock); \ + } \ +} \ + \ +static int smb_create_tls_pthread(const char *keyname, void **ppkey, const char *location) \ +{ \ + int ret; \ + pthread_key_t *pkey; \ + pkey = (pthread_key_t *)malloc(sizeof(pthread_key_t)); \ + if (!pkey) { \ + return ENOMEM; \ + } \ + ret = pthread_key_create(pkey, NULL); \ + if (ret) { \ + free(pkey); \ + return ret; \ + } \ + *ppkey = (void *)pkey; \ + return 0; \ +} \ + \ +static void smb_destroy_tls_pthread(void **ppkey, const char *location) \ +{ \ + if (*ppkey) { \ + pthread_key_delete(*(pthread_key_t *)ppkey); \ + free(*ppkey); \ + *ppkey = NULL; \ + } \ +} \ + \ +static int smb_set_tls_pthread(void *pkey, const void *pval, const char *location) \ +{ \ + return pthread_setspecific(*(pthread_key_t *)pkey, pval); \ +} \ + \ +static void *smb_get_tls_pthread(void *pkey, const char *location) \ +{ \ + if (pkey == NULL) { \ + return NULL; \ + } \ + return pthread_getspecific(*(pthread_key_t *)pkey); \ +} \ + \ +static const struct smb_thread_functions (tf) = { \ + smb_create_mutex_pthread, \ + smb_destroy_mutex_pthread, \ + smb_lock_pthread, \ + smb_create_tls_pthread, \ + smb_destroy_tls_pthread, \ + smb_set_tls_pthread, \ + smb_get_tls_pthread } + +#endif diff --git a/lib/util/smb_threads_internal.h b/lib/util/smb_threads_internal.h new file mode 100644 index 0000000..afd7559 --- /dev/null +++ b/lib/util/smb_threads_internal.h @@ -0,0 +1,74 @@ +/* + SMB/CIFS implementation. + SMB thread interface internal macros. + Copyright (C) Jeremy Allison, 2009. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _smb_threads_internal_h_ +#define _smb_threads_internal_h_ + +#define SMB_THREAD_CREATE_MUTEX(name, lockvar) \ + (global_tfp ? global_tfp->create_mutex((name), &(lockvar), __location__) : 0) + +#define SMB_THREAD_DESTROY_MUTEX(plock) \ + do { \ + if (global_tfp) { \ + global_tfp->destroy_mutex(plock, __location__); \ + }; \ + } while (0) + +#define SMB_THREAD_LOCK_INTERNAL(plock, type, location) \ + (global_tfp ? global_tfp->lock_mutex((plock), (type), location) : 0) + +#define SMB_THREAD_LOCK(plock) \ + SMB_THREAD_LOCK_INTERNAL(plock, SMB_THREAD_LOCK, __location__) + +#define SMB_THREAD_UNLOCK(plock) \ + SMB_THREAD_LOCK_INTERNAL(plock, SMB_THREAD_UNLOCK, __location__) + +#define SMB_THREAD_ONCE(ponce, init_fn, pdata) \ + (global_tfp \ + ? (! *(ponce) \ + ? smb_thread_once((ponce), (init_fn), (pdata)) \ + : 0) \ + : ((init_fn(pdata)), *(ponce) = true, 1)) + +#define SMB_THREAD_CREATE_TLS(keyname, key) \ + (global_tfp ? global_tfp->create_tls((keyname), &(key), __location__) : 0) + +#define SMB_THREAD_DESTROY_TLS(key) \ + do { \ + if (global_tfp) { \ + global_tfp->destroy_tls(&(key), __location__); \ + }; \ + } while (0) + +#define SMB_THREAD_SET_TLS(key, val) \ + (global_tfp ? global_tfp->set_tls((key),(val),__location__) : \ + ((key) = (val), 0)) + +#define SMB_THREAD_GET_TLS(key) \ + (global_tfp ? global_tfp->get_tls((key), __location__) : (key)) + +/* + * Global thread lock list. + */ + +#define NUM_GLOBAL_LOCKS 1 + +#define GLOBAL_LOCK(locknum) (global_lock_array ? global_lock_array[(locknum)] : NULL) + +#endif diff --git a/lib/util/stable_sort.c b/lib/util/stable_sort.c new file mode 100644 index 0000000..47667c4 --- /dev/null +++ b/lib/util/stable_sort.c @@ -0,0 +1,250 @@ +/* + Stable sort routines + + Copyright © Douglas Bagnall <douglas.bagnall@catalyst.net.nz> + + ** NOTE! The following LGPL license applies to this file which is used by + ** the ldb library. This does NOT imply that all of Samba is released + ** under the LGPL. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <talloc.h> +#include "replace.h" +#include "stable_sort.h" + +static void sort_few(char *array, char *aux, + size_t n, + size_t s, + samba_compare_with_context_fn_t cmpfn, + void *opaque) +{ + /* a kind of insertion sort for small n. */ + int i, j, dist; + int cmp; + char *a, *b; + + for (i = 1; i < n; i++) { + a = &array[i * s]; + /* leftwards is sorted. look until we find this one's place */ + for (j = i - 1; j >= 0; j--) { + b = &array[j * s]; + cmp = cmpfn(a, b, opaque); + if (cmp >= 0) { + break; + } + } + dist = i - 1 - j; + if (dist == 0) { + /* a is already in the right place */ + continue; + } + + b = &array[(i - dist) * s]; + memcpy(aux, a, s); + memmove(b + s, b, s * dist); + memcpy(b, aux, s); + } +} + + +static void merge(char *dest, + char *a, size_t alen, + char *b, size_t blen, + size_t s, + samba_compare_with_context_fn_t cmpfn, + void *opaque) +{ + size_t ai = 0; + size_t bi = 0; + size_t di = 0; + while (ai < alen && bi < blen) { + int cmp = cmpfn(&a[ai * s], &b[bi * s], opaque); + if (cmp <= 0) { + memcpy(&dest[di * s], &a[ai * s], s); + ai++; + } else { + memcpy(&dest[di * s], &b[bi * s], s); + bi++; + } + di++; + } + if (ai < alen) { + memcpy(&dest[di * s], &a[ai * s], s * (alen - ai)); + } else if (bi < blen) { + memcpy(&dest[di * s], &b[bi * s], s * (blen - bi)); + } +} + + +bool stable_sort_r(void *array, void *aux, + size_t n, + size_t s, + samba_compare_with_context_fn_t cmpfn, + void * opaque) +{ + char *src = array, *dest = aux, *tmp = NULL; + size_t i, j, k; + size_t runsize; + if (array == NULL || aux == NULL) { + return false; + } + + if (n < 20) { + sort_few(array, aux, n, s, cmpfn, opaque); + return true; + } + + if (n > SIZE_MAX / s) { + /* + * We will have an integer overflow if we continue. + * + * This means that the *supposed* size of the allocated buffer + * is greater than SIZE_MAX, which is not possible in theory + * or practice, and is a sign the caller has got very + * confused. + */ + return false; + } + + /* + * This is kind of a bottom-up merge sort. + * + * We start but sorting into a whole lot of little runs, using an + * insertion sort which is efficient for small numbers. Empirically, + * on 2 machines, a run size of around 8 seems optimal, but the peak + * is wide, and it seems worth adapting the size to avoid an + * unbalanced final merge at the top. That is, if we pick the right + * runsize now, we will finish with a merge of roughly n/2:n/2, and + * not have to follow that with an merge of roughly n:[a few], which + * we would sometimes do with a fixed size at the lowest level. + * + * The aim is a runsize of n / (a power of 2) rounded up, in the + * target range. + */ + + runsize = n; + while (runsize > 10) { + runsize++; + runsize >>= 1; + } + + for (i = 0; i < n; i += runsize) { + size_t nn = MIN(n - i, runsize); + sort_few(&src[i * s], aux, nn, s, cmpfn, opaque); + } + + while (runsize < n) { + for (i = 0; i < n; i += runsize * 2) { + j = i + runsize; + if (j >= n) { + /* + * first run doesn't fit, meaning this chunk + * is already sorted. We just need to copy + * it. + */ + size_t nn = n - i; + memcpy(&dest[i * s], &src[i * s], nn * s); + break; + } + k = j + runsize; + if (k > n) { + merge(&dest[i * s], + &src[i * s], runsize, + &src[j * s], n - j, + s, + cmpfn, opaque); + } else { + merge(&dest[i * s], + &src[i * s], runsize, + &src[j * s], runsize, + s, + cmpfn, opaque); + } + } + + tmp = src; + src = dest; + dest = tmp; + runsize *= 2; + } + /* + * We have sorted the array into src, which is either array or aux. + */ + if (src != array) { + memcpy(array, src, n * s); + } + return true; +} + + + +/* + * A wrapper that allocates (and frees) the temporary buffer if necessary. + * + * returns false on allocation error, true otherwise. + */ + +bool stable_sort_talloc_r(TALLOC_CTX *mem_ctx, + void *array, + size_t n, + size_t s, + samba_compare_with_context_fn_t cmpfn, + void *opaque) +{ + bool ok; + char *mem = talloc_array_size(mem_ctx, s, n); + if (mem == NULL) { + return false; + } + ok = stable_sort_r(array, mem, n, s, cmpfn, opaque); + talloc_free(mem); + return ok; +} + + +bool stable_sort(void *array, void *aux, + size_t n, + size_t s, + samba_compare_fn_t cmpfn) +{ + /* + * What is this magic, casting cmpfn into a different type that takes + * an extra parameter? Is that allowed? + * + * A: Yes. It's fine. The extra argument will be passed on the stack + * or (more likely) a register, and the cmpfn will remain blissfully + * unaware. + */ + return stable_sort_r(array, aux, n, s, + (samba_compare_with_context_fn_t)cmpfn, + NULL); +} + + +bool stable_sort_talloc(TALLOC_CTX *mem_ctx, + void *array, + size_t n, + size_t s, + samba_compare_fn_t cmpfn) +{ + return stable_sort_talloc_r(mem_ctx, array, n, s, + (samba_compare_with_context_fn_t)cmpfn, + NULL); +} diff --git a/lib/util/stable_sort.h b/lib/util/stable_sort.h new file mode 100644 index 0000000..17329b8 --- /dev/null +++ b/lib/util/stable_sort.h @@ -0,0 +1,46 @@ +#ifndef HAVE_STABLE_SORT_H +#define HAVE_STABLE_SORT_H 1 + +#ifdef __COMPAR_FN_T +typedef __compar_fn_t samba_compare_fn_t; + +#ifdef __USE_GNU +/* glibc defines __compar_d_fn_t for qsort_r */ +typedef __compar_d_fn_t samba_compare_with_context_fn_t; +#endif + +#else +typedef int (*samba_compare_fn_t) (const void *, const void *); +typedef int (*samba_compare_with_context_fn_t) (const void *, const void *, void *); +#endif + + + +bool stable_sort_r(void *array, void *aux, + size_t n, + size_t s, + samba_compare_with_context_fn_t cmpfn, + void *opaque); + +bool stable_sort(void *array, void *aux, + size_t n, + size_t s, + samba_compare_fn_t cmpfn); + + +bool stable_sort_talloc_r(TALLOC_CTX *mem_ctx, + void *array, + size_t n, + size_t s, + samba_compare_with_context_fn_t cmpfn, + void *opaque); + + +bool stable_sort_talloc(TALLOC_CTX *mem_ctx, + void *array, + size_t n, + size_t s, + samba_compare_fn_t cmpfn); + + +#endif /* HAVE_STABLE_SORT_H */ diff --git a/lib/util/string_wrappers.h b/lib/util/string_wrappers.h new file mode 100644 index 0000000..7625cd0 --- /dev/null +++ b/lib/util/string_wrappers.h @@ -0,0 +1,99 @@ +/* + Unix SMB/CIFS implementation. + + string wrappers, for checking string sizes + + Copyright (C) Andrew Tridgell 1994-2011 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _STRING_WRAPPERS_H +#define _STRING_WRAPPERS_H + +#include "lib/replace/replace.h" /* for config symbols */ + +#define strlcpy_base(dest, src, base, size) \ +do { \ + const char *_strlcpy_base_src = (const char *)src; \ + strlcpy((dest), _strlcpy_base_src? _strlcpy_base_src : "", (size)-PTR_DIFF((dest),(base))); \ +} while (0) + +/* String copy functions - macro hell below adds 'type checking' (limited, + but the best we can do in C) */ + +#define fstrcpy(d,s) \ +do { \ + const char *_fstrcpy_src = (const char *)(s); \ + strlcpy((d),_fstrcpy_src ? _fstrcpy_src : "",sizeof(fstring)); \ +} while (0) + +#define fstrcat(d,s) \ +do { \ + const char *_fstrcat_src = (const char *)(s); \ + strlcat((d),_fstrcat_src ? _fstrcat_src : "",sizeof(fstring)); \ +} while (0) +#define unstrcpy(d,s) \ +do { \ + const char *_unstrcpy_src = (const char *)(s); \ + strlcpy((d),_unstrcpy_src ? _unstrcpy_src : "",sizeof(unstring)); \ +} while (0) + +#ifdef HAVE_COMPILER_WILL_OPTIMIZE_OUT_FNS + +/* We need a number of different prototypes for our + non-existent functions */ +char * __unsafe_string_function_usage_here__(void); + +size_t __unsafe_string_function_usage_here_size_t__(void); + +NTSTATUS __unsafe_string_function_usage_here_NTSTATUS__(void); + +#define CHECK_STRING_SIZE(d, len) (sizeof(d) != (len) && sizeof(d) != sizeof(char *)) + +/* if the compiler will optimize out function calls, then use this to tell if we are + have the correct types (this works only where sizeof() returns the size of the buffer, not + the size of the pointer). */ + +#define push_string_check(dest, src, dest_len, flags) \ + (CHECK_STRING_SIZE(dest, dest_len) \ + ? __unsafe_string_function_usage_here_size_t__() \ + : push_string_check_fn(dest, src, dest_len, flags)) + +#define srvstr_push(base_ptr, smb_flags2, dest, src, dest_len, flags, ret_len) \ + (CHECK_STRING_SIZE(dest, dest_len) \ + ? __unsafe_string_function_usage_here_NTSTATUS__() \ + : srvstr_push_fn(base_ptr, smb_flags2, dest, src, dest_len, flags, ret_len)) + +/* This allows the developer to choose to check the arguments to + strlcpy. if the compiler will optimize out function calls, then + use this to tell if we are have the correct size buffer (this works only + where sizeof() returns the size of the buffer, not the size of the + pointer), so stack and static variables only */ + +#define checked_strlcpy(dest, src, size) \ + (sizeof(dest) != (size) \ + ? __unsafe_string_function_usage_here_size_t__() \ + : strlcpy(dest, src, size)) + +#else + +#define push_string_check push_string_check_fn +#define srvstr_push srvstr_push_fn +#define checked_strlcpy strlcpy + +#endif + +#endif diff --git a/lib/util/strv.c b/lib/util/strv.c new file mode 100644 index 0000000..83d84d9 --- /dev/null +++ b/lib/util/strv.c @@ -0,0 +1,191 @@ +/* + * String Vector functions modeled after glibc argv_* functions + * + * Copyright Volker Lendecke <vl@samba.org> 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "strv.h" +#include "talloc.h" +#include <string.h> + +static int _strv_append(TALLOC_CTX *mem_ctx, char **dst, const char *src, + size_t srclen) +{ + size_t dstlen = talloc_array_length(*dst); + size_t newlen = dstlen + srclen; + char *new_dst; + + if ((newlen < srclen) || (newlen < dstlen)) { + return ERANGE; + } + + new_dst = talloc_realloc(mem_ctx, *dst, char, newlen); + if (new_dst == NULL) { + return ENOMEM; + } + memcpy(&new_dst[dstlen], src, srclen); + + *dst = new_dst; + return 0; +} + +int strv_add(TALLOC_CTX *mem_ctx, char **strv, const char *string) +{ + return _strv_append(mem_ctx, strv, string, strlen(string)+1); +} + +int strv_addn(TALLOC_CTX *mem_ctx, char **strv, const char *string, size_t n) +{ + char t[n+1]; + + memcpy(t, string, n); + t[n] = '\0'; + return _strv_append(mem_ctx, strv, t, n+1); +} + +int strv_append(TALLOC_CTX *mem_ctx, char **strv, const char *src) +{ + return _strv_append(mem_ctx, strv, src, talloc_array_length(src)); +} + +static bool strv_valid_entry(const char *strv, size_t strv_len, + const char *entry, size_t *entry_len) +{ + if (strv_len == 0) { + return false; + } + if (strv[strv_len-1] != '\0') { + return false; + } + + if (entry < strv) { + return false; + } + if (entry >= (strv+strv_len)) { + return false; + } + + if (entry_len != NULL) { + *entry_len = strlen(entry); + } + + return true; +} + +const char *strv_len_next(const char *strv, size_t strv_len, + const char *entry) +{ + size_t entry_len; + + if (entry == NULL) { + if (strv_valid_entry(strv, strv_len, strv, NULL)) { + return strv; + } + return NULL; + } + + if (!strv_valid_entry(strv, strv_len, entry, &entry_len)) { + return NULL; + } + + entry += entry_len+1; + + if (entry >= (strv + strv_len)) { + return NULL; + } + return entry; +} + +char *strv_next(char *strv, const char *entry) +{ + size_t len = talloc_array_length(strv); + const char *result; + + result = strv_len_next(strv, len, entry); + return discard_const_p(char, result); +} + +size_t strv_count(char *strv) +{ + char *entry; + size_t count = 0; + + for (entry = strv; entry != NULL; entry = strv_next(strv, entry)) { + count += 1; + } + + return count; +} + +char *strv_find(char *strv, const char *entry) +{ + char *e = NULL; + + while ((e = strv_next(strv, e)) != NULL) { + if (strcmp(e, entry) == 0) { + return e; + } + } + + return NULL; +} + +void strv_delete(char **strv, char *entry) +{ + size_t len = talloc_array_length(*strv); + size_t entry_len; + + if (entry == NULL) { + return; + } + + if (!strv_valid_entry(*strv, len, entry, &entry_len)) { + return; + } + entry_len += 1; + + memmove(entry, entry+entry_len, + len - entry_len - (entry - *strv)); + + *strv = talloc_realloc(NULL, *strv, char, len - entry_len); +} + +char * const *strv_to_env(TALLOC_CTX *mem_ctx, char *strv) +{ + char **data; + char *next = NULL; + size_t i; + size_t count = strv_count(strv); + + if (strv == NULL) { + return NULL; + } + + data = talloc_array(mem_ctx, char *, count + 1); + + if (data == NULL) { + return NULL; + } + + for(i = 0; i < count; i++) { + next = strv_next(strv, next); + data[i] = next; + } + data[count] = NULL; + + return data; +} diff --git a/lib/util/strv.h b/lib/util/strv.h new file mode 100644 index 0000000..a6197e5 --- /dev/null +++ b/lib/util/strv.h @@ -0,0 +1,37 @@ +/* + * String Vector functions modeled after glibc argv_* functions + * + * Copyright Volker Lendecke <vl@samba.org> 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _STRV_H_ +#define _STRV_H_ + +#include "replace.h" +#include <talloc.h> + +int strv_add(TALLOC_CTX *mem_ctx, char **strv, const char *string); +int strv_addn(TALLOC_CTX *mem_ctx, char **strv, const char *src, size_t srclen); +int strv_append(TALLOC_CTX *mem_ctx, char **strv, const char *src); +char *strv_next(char *strv, const char *entry); +const char *strv_len_next(const char *strv, size_t strv_len, + const char *entry); +char *strv_find(char *strv, const char *entry); +size_t strv_count(char *strv); +void strv_delete(char **strv, char *entry); +char * const *strv_to_env(TALLOC_CTX *mem_ctx, char *strv); + +#endif diff --git a/lib/util/strv_util.c b/lib/util/strv_util.c new file mode 100644 index 0000000..9da3eb2 --- /dev/null +++ b/lib/util/strv_util.c @@ -0,0 +1,61 @@ +/* + * strv-based utilities + * + * Copyright Martin Schwenke <martin@meltin.net> 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" + +#include <string.h> +#include <talloc.h> + +#include "strv.h" + +#include "strv_util.h" + +int strv_split(TALLOC_CTX *mem_ctx, char **strv, + const char *src, const char *sep) +{ + const char *s; + + if (src == NULL) { + return 0; + } + + s = src; + while (*s != '\0') { + size_t len; + + /* Skip separators */ + len = strspn(s, sep); + if (len != 0) { + s += len; + } + + /* Find non-separator substring */ + len = strcspn(s, sep); + if (len != 0) { + int ret = strv_addn(mem_ctx, strv, s, len); + if (ret != 0) { + TALLOC_FREE(*strv); + return ret; + } + s += len; + } + } + + return 0; +} diff --git a/lib/util/strv_util.h b/lib/util/strv_util.h new file mode 100644 index 0000000..9456d43 --- /dev/null +++ b/lib/util/strv_util.h @@ -0,0 +1,30 @@ +/* + * strv-based utilities + * + * Copyright Martin Schwenke <martin@meltin.net> 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _STRV_UTIL_H_ +#define _STRV_UTIL_H_ + +#include <talloc.h> + +/* Split string at characters in sep, adding non-separator words to + * *strv. On failure *strv is undefined. */ +int strv_split(TALLOC_CTX *mem_ctx, char **strv, + const char *string, const char *sep); + +#endif diff --git a/lib/util/substitute.c b/lib/util/substitute.c new file mode 100644 index 0000000..b7b5588 --- /dev/null +++ b/lib/util/substitute.c @@ -0,0 +1,280 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Simo Sorce 2001-2002 + Copyright (C) Martin Pool 2003 + Copyright (C) James Peach 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "debug.h" +#ifndef SAMBA_UTIL_CORE_ONLY +#include "charset/charset.h" +#else +#include "charset_compat.h" +#endif +#include "substitute.h" + +/** + * @file + * @brief Substitute utilities. + **/ + +/** + Substitute a string for a pattern in another string. Make sure there is + enough room! + + This routine looks for pattern in s and replaces it with + insert. It may do multiple replacements or just one. + + Any of " ; ' $ or ` in the insert string are replaced with _ + if len==0 then the string cannot be extended. This is different from the old + use of len==0 which was for no length checks to be done. +**/ + +static void string_sub2(char *s,const char *pattern, const char *insert, size_t len, + bool remove_unsafe_characters, bool replace_once, + bool allow_trailing_dollar) +{ + char *p; + size_t ls, lp, li, i; + + if (!insert || !pattern || !*pattern || !s) + return; + + ls = strlen(s); + lp = strlen(pattern); + li = strlen(insert); + + if (len == 0) + len = ls + 1; /* len is number of *bytes* */ + + while (lp <= ls && (p = strstr_m(s,pattern))) { + if (ls + li - lp >= len) { + DBG_ERR("ERROR: string overflow by " + "%zu in string_sub(%.50s, %zu)\n", + ls + li - lp + 1 - len, + pattern, + len); + break; + } + if (li != lp) { + memmove(p+li,p+lp,strlen(p+lp)+1); + } + for (i=0;i<li;i++) { + switch (insert[i]) { + case '$': + /* allow a trailing $ + * (as in machine accounts) */ + if (allow_trailing_dollar && (i == li - 1 )) { + p[i] = insert[i]; + break; + } + FALL_THROUGH; + case '`': + case '"': + case '\'': + case ';': + case '%': + case '\r': + case '\n': + if ( remove_unsafe_characters ) { + p[i] = '_'; + /* yes this break should be here + * since we want to fall throw if + * not replacing unsafe chars */ + break; + } + FALL_THROUGH; + default: + p[i] = insert[i]; + } + } + s = p + li; + ls = ls + li - lp; + + if (replace_once) + break; + } +} + +void string_sub(char *s,const char *pattern, const char *insert, size_t len) +{ + string_sub2( s, pattern, insert, len, true, false, false ); +} + +/** + Similar to string_sub() but allows for any character to be substituted. + Use with caution! + if len==0 then the string cannot be extended. This is different from the old + use of len==0 which was for no length checks to be done. +**/ + +_PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len) +{ + char *p; + size_t ls,lp,li; + + if (!insert || !pattern || !s) + return; + + ls = strlen(s); + lp = strlen(pattern); + li = strlen(insert); + + if (!*pattern) + return; + + if (len == 0) + len = ls + 1; /* len is number of *bytes* */ + + while (lp <= ls && (p = strstr_m(s,pattern))) { + if (ls + li - lp >= len) { + DBG_ERR("ERROR: string overflow by " + "%zu in all_string_sub(%.50s, %zu)\n", + ls + li - lp + 1 - len, + pattern, + len); + break; + } + if (li != lp) { + memmove(p+li,p+lp,strlen(p+lp)+1); + } + memcpy(p, insert, li); + s = p + li; + ls = ls + li - lp; + } +} + +/* + * Internal guts of talloc_string_sub and talloc_all_string_sub. + * talloc version of string_sub2. + */ + +char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src, + const char *pattern, + const char *insert, + bool remove_unsafe_characters, + bool replace_once, + bool allow_trailing_dollar) +{ + char *p, *in; + char *s; + char *string; + ssize_t ls,lp,li,ld, i; + + if (!insert || !pattern || !*pattern || !src) { + return NULL; + } + + string = talloc_strdup(mem_ctx, src); + if (string == NULL) { + DEBUG(0, ("talloc_string_sub2: " + "talloc_strdup failed\n")); + return NULL; + } + + s = string; + + in = talloc_strdup(mem_ctx, insert); + if (!in) { + DEBUG(0, ("talloc_string_sub2: ENOMEM\n")); + talloc_free(string); + return NULL; + } + ls = (ssize_t)strlen(s); + lp = (ssize_t)strlen(pattern); + li = (ssize_t)strlen(insert); + ld = li - lp; + + for (i=0;i<li;i++) { + switch (in[i]) { + case '$': + /* allow a trailing $ + * (as in machine accounts) */ + if (allow_trailing_dollar && (i == li - 1 )) { + break; + } + + FALL_THROUGH; + case '`': + case '"': + case '\'': + case ';': + case '%': + case '\r': + case '\n': + if (remove_unsafe_characters) { + in[i] = '_'; + break; + } + + FALL_THROUGH; + default: + /* ok */ + break; + } + } + + while ((p = strstr_m(s,pattern))) { + if (ld > 0) { + int offset = PTR_DIFF(s,string); + string = (char *)talloc_realloc_size(mem_ctx, string, + ls + ld + 1); + if (!string) { + DEBUG(0, ("talloc_string_sub: out of " + "memory!\n")); + TALLOC_FREE(in); + return NULL; + } + p = string + offset + (p - s); + } + if (li != lp) { + memmove(p+li,p+lp,strlen(p+lp)+1); + } + memcpy(p, in, li); + s = p + li; + ls += ld; + + if (replace_once) { + break; + } + } + TALLOC_FREE(in); + return string; +} + +/* Same as string_sub, but returns a talloc'ed string */ + +char *talloc_string_sub(TALLOC_CTX *mem_ctx, + const char *src, + const char *pattern, + const char *insert) +{ + return talloc_string_sub2(mem_ctx, src, pattern, insert, + true, false, false); +} + +char *talloc_all_string_sub(TALLOC_CTX *ctx, + const char *src, + const char *pattern, + const char *insert) +{ + return talloc_string_sub2(ctx, src, pattern, insert, + false, false, false); +} diff --git a/lib/util/substitute.h b/lib/util/substitute.h new file mode 100644 index 0000000..3134cfc --- /dev/null +++ b/lib/util/substitute.h @@ -0,0 +1,64 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Simo Sorce 2001-2002 + Copyright (C) Martin Pool 2003 + Copyright (C) James Peach 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_SUBSTITUTE_H_ +#define _SAMBA_SUBSTITUTE_H_ + +#include <talloc.h> + +/** + Substitute a string for a pattern in another string. Make sure there is + enough room! + + This routine looks for pattern in s and replaces it with + insert. It may do multiple replacements. + + Any of " ; ' $ or ` in the insert string are replaced with _ + if len==0 then the string cannot be extended. This is different from the old + use of len==0 which was for no length checks to be done. +**/ +void string_sub(char *s,const char *pattern, const char *insert, size_t len); + +/** + Similar to string_sub() but allows for any character to be substituted. + Use with caution! + if len==0 then the string cannot be extended. This is different from the old + use of len==0 which was for no length checks to be done. +**/ +void all_string_sub(char *s,const char *pattern,const char *insert, size_t len); + +char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src, + const char *pattern, + const char *insert, + bool remove_unsafe_characters, + bool replace_once, + bool allow_trailing_dollar); +char *talloc_string_sub(TALLOC_CTX *mem_ctx, + const char *src, + const char *pattern, + const char *insert); +char *talloc_all_string_sub(TALLOC_CTX *ctx, + const char *src, + const char *pattern, + const char *insert); +#endif /* _SAMBA_SUBSTITUTE_H_ */ diff --git a/lib/util/sys_popen.c b/lib/util/sys_popen.c new file mode 100644 index 0000000..f62199b --- /dev/null +++ b/lib/util/sys_popen.c @@ -0,0 +1,177 @@ +/* + * Unix SMB/CIFS implementation. + * Samba system utilities + * Copyright (C) Jeremy Allison 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/wait.h" +#include "system/filesys.h" +#include <talloc.h> +#include "lib/util/sys_popen.h" +#include "lib/util/debug.h" + +/************************************************************************** + Wrapper for popen. Safer as it doesn't search a path. + Modified from the glibc sources. + modified by tridge to return a file descriptor. We must kick our FILE* habit +****************************************************************************/ + +typedef struct _popen_list +{ + int fd; + pid_t child_pid; + struct _popen_list *next; +} popen_list; + +static popen_list *popen_chain; + +int sys_popenv(char * const argl[]) +{ + int parent_end, child_end; + int pipe_fds[2]; + popen_list *entry = NULL; + const char *command = NULL; + int ret; + + if (argl == NULL) { + errno = EINVAL; + return -1; + } + command = argl[0]; + + if (!*command) { + errno = EINVAL; + return -1; + } + + ret = pipe(pipe_fds); + if (ret < 0) { + DBG_ERR("error opening pipe: %s\n", + strerror(errno)); + return -1; + } + + parent_end = pipe_fds[0]; + child_end = pipe_fds[1]; + + entry = talloc_zero(NULL, popen_list); + if (entry == NULL) { + DBG_ERR("talloc failed\n"); + goto err_exit; + } + + entry->child_pid = fork(); + + if (entry->child_pid == -1) { + DBG_ERR("fork failed: %s\n", strerror(errno)); + goto err_exit; + } + + if (entry->child_pid == 0) { + + /* + * Child ! + */ + + int child_std_end = STDOUT_FILENO; + popen_list *p; + + close(parent_end); + if (child_end != child_std_end) { + dup2 (child_end, child_std_end); + close (child_end); + } + + /* + * POSIX.2: "popen() shall ensure that any streams from previous + * popen() calls that remain open in the parent process are closed + * in the new child process." + */ + + for (p = popen_chain; p; p = p->next) + close(p->fd); + + ret = execv(argl[0], argl); + if (ret == -1) { + DBG_ERR("ERROR executing command " + "'%s': %s\n", command, strerror(errno)); + } + _exit (127); + } + + /* + * Parent. + */ + + close (child_end); + + /* Link into popen_chain. */ + entry->next = popen_chain; + popen_chain = entry; + entry->fd = parent_end; + + return entry->fd; + +err_exit: + + TALLOC_FREE(entry); + close(pipe_fds[0]); + close(pipe_fds[1]); + return -1; +} + +/************************************************************************** + Wrapper for pclose. Modified from the glibc sources. +****************************************************************************/ + +int sys_pclose(int fd) +{ + int wstatus; + popen_list **ptr = &popen_chain; + popen_list *entry = NULL; + pid_t wait_pid; + int status = -1; + + /* Unlink from popen_chain. */ + for ( ; *ptr != NULL; ptr = &(*ptr)->next) { + if ((*ptr)->fd == fd) { + entry = *ptr; + *ptr = (*ptr)->next; + status = 0; + break; + } + } + + if (status < 0 || close(entry->fd) < 0) + return -1; + + /* + * As Samba is catching and eating child process + * exits we don't really care about the child exit + * code, a -1 with errno = ECHILD will do fine for us. + */ + + do { + wait_pid = waitpid (entry->child_pid, &wstatus, 0); + } while (wait_pid == -1 && errno == EINTR); + + TALLOC_FREE(entry); + + if (wait_pid == -1) + return -1; + return wstatus; +} diff --git a/lib/util/sys_popen.h b/lib/util/sys_popen.h new file mode 100644 index 0000000..be43748 --- /dev/null +++ b/lib/util/sys_popen.h @@ -0,0 +1,26 @@ +/* + * Unix SMB/CIFS implementation. + * Samba system utilities + * Copyright (C) Jeremy Allison 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LIB_SYS_POPEN_H__ +#define __LIB_SYS_POPEN_H__ + +int sys_popenv(char * const argl[]); +int sys_pclose(int fd); + +#endif diff --git a/lib/util/sys_rw.c b/lib/util/sys_rw.c new file mode 100644 index 0000000..d25a42b --- /dev/null +++ b/lib/util/sys_rw.c @@ -0,0 +1,295 @@ +/* + * Unix SMB/CIFS implementation. + * Samba system utilities + * Copyright (C) Andrew Tridgell 1992-1998 + * Copyright (C) Jeremy Allison 1998-2005 + * Copyright (C) Timur Bakeyev 2005 + * Copyright (C) Bjoern Jacke 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/filesys.h" +#include "lib/util/sys_rw.h" +#include <assert.h> + +bool sys_valid_io_range(off_t offset, size_t length) +{ + uint64_t last_byte_ofs; + + if (offset < 0) { + return false; + } + + if (offset > INT64_MAX) { + return false; + } + + if (length > UINT32_MAX) { + return false; + } + + last_byte_ofs = (uint64_t)offset + (uint64_t)length; + if (last_byte_ofs > INT64_MAX) { + return false; + } + + return true; +} + +bool sys_io_ranges_overlap(size_t c1, off_t o1, + size_t c2, off_t o2) +{ + if (c1 == 0 || c2 == 0) { + return false; + } + if (o2 < o1) { + /* + * o1 + * |····c1····| + * o2 + * |····c2···| ? + */ + return (o2 + c2 > o1); + } else { + /* + * o1 + * |····c1···| + * o2 + * |····c2····| ? + */ + return (o1 + c1 > o2); + } +} + +off_t sys_block_align_truncate(off_t len, off_t align) +{ + assert(align > 1); + assert(((align - 1) & align) == 0); + return len & (~align + 1); +} + +off_t sys_block_align(off_t len, off_t align) +{ + assert(align > 1); + assert(((align - 1) & align) == 0); + return (len + (align - 1)) & ~(align - 1); +} + +/******************************************************************* +A read wrapper that will deal with EINTR/EWOULDBLOCK +********************************************************************/ + +ssize_t sys_read(int fd, void *buf, size_t count) +{ + ssize_t ret; + + do { + ret = read(fd, buf, count); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN || + errno == EWOULDBLOCK)); + + return ret; +} + +/** + * read wrapper, void variant: + * This is intended to be used as a void variant of + * read in situations where the caller wants to ignore + * the result. Hence not checking for EAGAIN|EWOULDBLOCK. + */ +void sys_read_v(int fd, void *buf, size_t count) +{ + ssize_t ret; + + do { + ret = read(fd, buf, count); + } while (ret == -1 && errno == EINTR); +} + + +/******************************************************************* +A write wrapper that will deal with EINTR/EWOULDBLOCK. +********************************************************************/ + +ssize_t sys_write(int fd, const void *buf, size_t count) +{ + ssize_t ret; + + do { + ret = write(fd, buf, count); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN || + errno == EWOULDBLOCK)); + + return ret; +} + +/** + * write wrapper to deal with EINTR and friends. + * void-variant that ignores the number of bytes written. + * This is intended to be used as a void variant of + * write in situations where the caller wants to ignore + * the result. Hence not checking for EAGAIN|EWOULDBLOCK. + */ +void sys_write_v(int fd, const void *buf, size_t count) +{ + ssize_t ret; + + do { + ret = write(fd, buf, count); + } while (ret == -1 && errno == EINTR); +} + + +/******************************************************************* +A writev wrapper that will deal with EINTR. +********************************************************************/ + +ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt) +{ + ssize_t ret; + + do { + ret = writev(fd, iov, iovcnt); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN || + errno == EWOULDBLOCK)); + + return ret; +} + +/******************************************************************* +A pread wrapper that will deal with EINTR +********************************************************************/ + +ssize_t sys_pread(int fd, void *buf, size_t count, off_t off) +{ + ssize_t ret; + + do { + ret = pread(fd, buf, count, off); + } while (ret == -1 && errno == EINTR); + return ret; +} + +/******************************************************************* + A pread wrapper that will deal with EINTR and never return a short + read unless pread returns zero meaning EOF. +********************************************************************/ + +ssize_t sys_pread_full(int fd, void *buf, size_t count, off_t off) +{ + ssize_t total_read = 0; + uint8_t *curr_buf = (uint8_t *)buf; + size_t curr_count = count; + off_t curr_off = off; + bool ok; + + ok = sys_valid_io_range(off, count); + if (!ok) { + errno = EINVAL; + return -1; + } + + while (curr_count != 0) { + ssize_t ret = sys_pread(fd, + curr_buf, + curr_count, + curr_off); + + if (ret == -1) { + return -1; + } + if (ret == 0) { + /* EOF */ + break; + } + + if (ret > curr_count) { + errno = EIO; + return -1; + } + + curr_buf += ret; + curr_count -= ret; + curr_off += ret; + + total_read += ret; + } + + return total_read; +} + +/******************************************************************* +A write wrapper that will deal with EINTR +********************************************************************/ + +ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off) +{ + ssize_t ret; + + do { + ret = pwrite(fd, buf, count, off); + } while (ret == -1 && errno == EINTR); + return ret; +} + +/******************************************************************* + A pwrite wrapper that will deal with EINTR and never allow a short + write unless the file system returns an error. +********************************************************************/ + +ssize_t sys_pwrite_full(int fd, const void *buf, size_t count, off_t off) +{ + ssize_t total_written = 0; + const uint8_t *curr_buf = (const uint8_t *)buf; + size_t curr_count = count; + off_t curr_off = off; + bool ok; + + ok = sys_valid_io_range(off, count); + if (!ok) { + errno = EINVAL; + return -1; + } + + while (curr_count != 0) { + ssize_t ret = sys_pwrite(fd, + curr_buf, + curr_count, + curr_off); + + if (ret == -1) { + return -1; + } + if (ret == 0) { + /* Ensure we can never spin. */ + errno = ENOSPC; + return -1; + } + + if (ret > curr_count) { + errno = EIO; + return -1; + } + + curr_buf += ret; + curr_count -= ret; + curr_off += ret; + + total_written += ret; + } + + return total_written; +} diff --git a/lib/util/sys_rw.h b/lib/util/sys_rw.h new file mode 100644 index 0000000..3812159 --- /dev/null +++ b/lib/util/sys_rw.h @@ -0,0 +1,45 @@ +/* + * Unix SMB/CIFS implementation. + * Samba system utilities + * Copyright (C) Andrew Tridgell 1992-1998 + * Copyright (C) Jeremy Allison 1998-2005 + * Copyright (C) Timur Bakeyev 2005 + * Copyright (C) Bjoern Jacke 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LIB_SYS_RW_H__ +#define __LIB_SYS_RW_H__ + +#include <unistd.h> + +struct iovec; + +off_t sys_block_align_truncate(off_t len, off_t align); +off_t sys_block_align(off_t len, off_t align); +bool sys_valid_io_range(off_t offset, size_t length); +bool sys_io_ranges_overlap(size_t c1, off_t o1, + size_t c2, off_t o2); +ssize_t sys_read(int fd, void *buf, size_t count); +void sys_read_v(int fd, void *buf, size_t count); +ssize_t sys_write(int fd, const void *buf, size_t count); +void sys_write_v(int fd, const void *buf, size_t count); +ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt); +ssize_t sys_pread(int fd, void *buf, size_t count, off_t off); +ssize_t sys_pread_full(int fd, void *buf, size_t count, off_t off); +ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off); +ssize_t sys_pwrite_full(int fd, const void *buf, size_t count, off_t off); + +#endif diff --git a/lib/util/sys_rw_data.c b/lib/util/sys_rw_data.c new file mode 100644 index 0000000..a0d69f7 --- /dev/null +++ b/lib/util/sys_rw_data.c @@ -0,0 +1,117 @@ +/* + * Unix SMB/CIFS implementation. + * Samba system utilities + * Copyright (C) Andrew Tridgell 1992-1998 + * Copyright (C) Jeremy Allison 1998-2005 + * Copyright (C) Timur Bakeyev 2005 + * Copyright (C) Bjoern Jacke 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/filesys.h" +#include "lib/util/sys_rw_data.h" +#include "lib/util/sys_rw.h" +#include "lib/util/iov_buf.h" + +/**************************************************************************** + Write all data from an iov array + NB. This can be called with a non-socket fd, don't add dependencies + on socket calls. +****************************************************************************/ + +ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt) +{ + ssize_t to_send; + ssize_t thistime; + size_t sent; + struct iovec iov_copy[iovcnt]; + struct iovec *iov; + + to_send = iov_buflen(orig_iov, iovcnt); + if (to_send == -1) { + errno = EINVAL; + return -1; + } + + thistime = sys_writev(fd, orig_iov, iovcnt); + if ((thistime <= 0) || (thistime == to_send)) { + return thistime; + } + sent = thistime; + + /* + * We could not send everything in one call. Make a copy of iov that + * we can mess with. + */ + + memcpy(iov_copy, orig_iov, sizeof(struct iovec) * iovcnt); + iov = iov_copy; + + while (sent < (size_t)to_send) { + bool ok; + + ok = iov_advance(&iov, &iovcnt, thistime); + if (!ok) { + errno = EIO; + return -1; + } + + thistime = sys_writev(fd, iov, iovcnt); + if (thistime <= 0) { + break; + } + sent += thistime; + } + + return sent; +} + +/**************************************************************************** + Write data to a fd. + NB. This can be called with a non-socket fd, don't add dependencies + on socket calls. +****************************************************************************/ + +ssize_t write_data(int fd, const void *buffer, size_t n) +{ + struct iovec iov; + + iov.iov_base = discard_const_p(void, buffer); + iov.iov_len = n; + return write_data_iov(fd, &iov, 1); +} + +/* + * Blocking read n bytes from a fd + */ + +ssize_t read_data(int fd, void *buffer, size_t n) +{ + ssize_t nread; + + nread = 0; + + while ((size_t)nread < n) { + ssize_t ret; + ret = sys_read(fd, ((char *)buffer) + nread, n - nread); + if (ret <= 0) { + return ret; + } + nread += ret; + } + + return nread; +} diff --git a/lib/util/sys_rw_data.h b/lib/util/sys_rw_data.h new file mode 100644 index 0000000..bda3795 --- /dev/null +++ b/lib/util/sys_rw_data.h @@ -0,0 +1,34 @@ +/* + * Unix SMB/CIFS implementation. + * Samba system utilities + * Copyright (C) Andrew Tridgell 1992-1998 + * Copyright (C) Jeremy Allison 1998-2005 + * Copyright (C) Timur Bakeyev 2005 + * Copyright (C) Bjoern Jacke 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LIB_SYS_RW_DATA_H__ +#define __LIB_SYS_RW_DATA_H__ + +#include <unistd.h> + +struct iovec; + +ssize_t write_data_iov(int fd, const struct iovec *iov, int iovcnt); +ssize_t write_data(int fd, const void *buffer, size_t n); +ssize_t read_data(int fd, void *buffer, size_t n); + +#endif diff --git a/lib/util/system.c b/lib/util/system.c new file mode 100644 index 0000000..558aa5b --- /dev/null +++ b/lib/util/system.c @@ -0,0 +1,65 @@ +/* + Unix SMB/CIFS implementation. + Samba system utilities + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "system/network.h" +#include "system/filesys.h" + +#undef malloc + +/* + The idea is that this file will eventually have wrappers around all + important system calls in samba. The aims are: + + - to enable easier porting by putting OS dependent stuff in here + + - to allow for hooks into other "pseudo-filesystems" + + - to allow easier integration of things like the japanese extensions + + - to support the philosophy of Samba to expose the features of + the OS within the SMB model. In general whatever file/printer/variable + expansions/etc make sense to the OS should be acceptable to Samba. +*/ + + +_PUBLIC_ int sys_getnameinfo(const struct sockaddr *psa, + int salen, + char *host, + size_t hostlen, + char *service, + size_t servlen, + int flags) +{ + /* + * For Solaris we must make sure salen is the + * correct length for the incoming sa_family. + */ + + if (salen == sizeof(struct sockaddr_storage)) { + salen = sizeof(struct sockaddr_in); +#if defined(HAVE_IPV6) + if (psa->sa_family == AF_INET6) { + salen = sizeof(struct sockaddr_in6); + } +#endif + } + return getnameinfo(psa, salen, host, hostlen, service, servlen, flags); +} diff --git a/lib/util/talloc_keep_secret.c b/lib/util/talloc_keep_secret.c new file mode 100644 index 0000000..2104865 --- /dev/null +++ b/lib/util/talloc_keep_secret.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019 Andreas Schneider <asn@samba.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include <talloc.h> +#include "lib/util/fault.h" +#include "talloc_keep_secret.h" + +static int talloc_keep_secret_destructor(void *ptr) +{ + int ret; + size_t size = talloc_get_size(ptr); + + if (unlikely(size == 0)) { + return 0; + } + + ret = memset_s(ptr, size, 0, size); + if (unlikely(ret != 0)) { + char *msg = NULL; + int ret2; + ret2 = asprintf(&msg, + "talloc_keep_secret_destructor: memset_s() failed: %s", + strerror(ret)); + if (ret2 != -1) { + smb_panic(msg); + } else { + smb_panic("talloc_keep_secret_destructor: memset_s() failed"); + } + } + + return 0; +} + +void _talloc_keep_secret(void *ptr, const char *name) +{ + size_t size; + + if (unlikely(ptr == NULL)) { +#ifdef DEVELOPER + smb_panic("Invalid talloc pointer"); +#endif + return; + } + + size = talloc_get_size(ptr); + if (unlikely(size == 0)) { + return; + } + + talloc_set_name_const(ptr, name); + talloc_set_destructor(ptr, talloc_keep_secret_destructor); +} diff --git a/lib/util/talloc_keep_secret.h b/lib/util/talloc_keep_secret.h new file mode 100644 index 0000000..44a26ae --- /dev/null +++ b/lib/util/talloc_keep_secret.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 Andreas Schneider <asn@samba.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _TALLOC_KEEP_SECRET_H +#define _TALLOC_KEEP_SECRET_H + +#ifdef DOXYGEN +/** + * @brief Keep the memory secret when freeing. + * + * This can be used to define memory as secret. For example memory which holds + * passwords or other secrets like session keys. The memory will be zeroed + * before is being freed. + * + * If you duplicate memory, e.g. using talloc_strdup() or talloc_asprintf() you + * need to call talloc_keep_secret() on the newly allocated memory too! + * + * @param[in] ptr The talloc chunk to mark as secure. + * + * @warning Do not use this in combination with talloc_realloc(). + */ +void talloc_keep_secret(const void *ptr); +#else +#define talloc_keep_secret(ptr) _talloc_keep_secret(ptr, #ptr); +void _talloc_keep_secret(void *ptr, const char *name); +#endif + +#endif /* _TALLOC_KEEP_SECRET_H */ diff --git a/lib/util/talloc_report.c b/lib/util/talloc_report.c new file mode 100644 index 0000000..0aec966 --- /dev/null +++ b/lib/util/talloc_report.c @@ -0,0 +1,184 @@ +/* + * talloc_report into a string + * + * Copyright Volker Lendecke <vl@samba.org> 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "talloc_report.h" + +/* + * talloc_vasprintf into a buffer that doubles its size. The real string + * length is maintained in "pstr_len". + */ + +static char *talloc_vasprintf_append_largebuf(char *buf, ssize_t *pstr_len, + const char *fmt, va_list ap) + PRINTF_ATTRIBUTE(3,0); + +static char *talloc_vasprintf_append_largebuf(char *buf, ssize_t *pstr_len, + const char *fmt, va_list ap) +{ + ssize_t str_len = *pstr_len; + size_t buflen, needed, space = 0; + char *start = NULL, *tmpbuf = NULL; + va_list ap2; + int printlen; + + if (str_len == -1) { + return NULL; + } + if (buf == NULL) { + return NULL; + } + if (fmt == NULL) { + return NULL; + } + buflen = talloc_get_size(buf); + + if (buflen > (size_t)str_len) { + start = buf + str_len; + space = buflen - str_len; + } else { + return NULL; + } + + va_copy(ap2, ap); + printlen = vsnprintf(start, space, fmt, ap2); + va_end(ap2); + + if (printlen < 0) { + goto fail; + } + + needed = str_len + printlen + 1; + + if (needed > buflen) { + buflen = MAX(128, buflen); + + while (buflen < needed) { + buflen *= 2; + } + + tmpbuf = talloc_realloc(NULL, buf, char, buflen); + if (tmpbuf == NULL) { + goto fail; + } + buf = tmpbuf; + + va_copy(ap2, ap); + vsnprintf(buf + str_len, buflen - str_len, fmt, ap2); + va_end(ap2); + } + *pstr_len = (needed - 1); + return buf; +fail: + *pstr_len = -1; + return buf; +} + +static char *talloc_asprintf_append_largebuf(char *buf, ssize_t *pstr_len, + const char *fmt, ...) + PRINTF_ATTRIBUTE(3,4); + +static char *talloc_asprintf_append_largebuf(char *buf, ssize_t *pstr_len, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + buf = talloc_vasprintf_append_largebuf(buf, pstr_len, fmt, ap); + va_end(ap); + return buf; +} + +struct talloc_report_str_state { + ssize_t str_len; + char *s; +}; + +static void talloc_report_str_helper(const void *ptr, int depth, int max_depth, + int is_ref, void *private_data) +{ + struct talloc_report_str_state *state = private_data; + const char *name = talloc_get_name(ptr); + + if (ptr == state->s) { + return; + } + + if (is_ref) { + state->s = talloc_asprintf_append_largebuf( + state->s, &state->str_len, + "%*sreference to: %s\n", depth*4, "", name); + return; + } + + if (depth == 0) { + state->s = talloc_asprintf_append_largebuf( + state->s, &state->str_len, + "%stalloc report on '%s' " + "(total %6lu bytes in %3lu blocks)\n", + (max_depth < 0 ? "full " :""), name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + return; + } + + if (strcmp(name, "char") == 0) { + /* + * Print out the first 50 bytes of the string + */ + state->s = talloc_asprintf_append_largebuf( + state->s, &state->str_len, + "%*s%-30s contains %6lu bytes in %3lu blocks " + "(ref %zu): %*s\n", depth*4, "", name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr), + talloc_reference_count(ptr), + (int)MIN(50, talloc_get_size(ptr)), + (const char *)ptr); + return; + } + + state->s = talloc_asprintf_append_largebuf( + state->s, &state->str_len, + "%*s%-30s contains %6lu bytes in %3lu blocks (ref %zu) %p\n", + depth*4, "", name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr), + talloc_reference_count(ptr), ptr); +} + +char *talloc_report_str(TALLOC_CTX *mem_ctx, TALLOC_CTX *root) +{ + struct talloc_report_str_state state; + + state.s = talloc_strdup(mem_ctx, ""); + if (state.s == NULL) { + return NULL; + } + state.str_len = 0; + + talloc_report_depth_cb(root, 0, -1, talloc_report_str_helper, &state); + + if (state.str_len == -1) { + talloc_free(state.s); + return NULL; + } + + return talloc_realloc(mem_ctx, state.s, char, state.str_len+1); +} diff --git a/lib/util/talloc_report.h b/lib/util/talloc_report.h new file mode 100644 index 0000000..53d0385 --- /dev/null +++ b/lib/util/talloc_report.h @@ -0,0 +1,27 @@ +/* + * talloc_report into a string + * + * Copyright Volker Lendecke <vl@samba.org> 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _TALLOC_REPORT_H_ +#define _TALLOC_REPORT_H_ + +#include <talloc.h> + +char *talloc_report_str(TALLOC_CTX *mem_ctx, TALLOC_CTX *root); + +#endif diff --git a/lib/util/talloc_report_printf.c b/lib/util/talloc_report_printf.c new file mode 100644 index 0000000..3011c62 --- /dev/null +++ b/lib/util/talloc_report_printf.c @@ -0,0 +1,134 @@ +/* + * talloc_report into a FILE + * + * Copyright Volker Lendecke <vl@samba.org> 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "talloc_report_printf.h" + +static void talloc_report_printf_helper( + const void *ptr, + int depth, + int max_depth, + int is_ref, + void *private_data) +{ + FILE *f = private_data; + const char *name = talloc_get_name(ptr); + + if (is_ref) { + fprintf(f, + "%*sreference to: %s\n", + depth*4, + "", + name); + return; + } + + if (depth == 0) { + fprintf(f, + "%stalloc report on '%s' " + "(total %6zu bytes in %3zu blocks)\n", + (max_depth < 0 ? "full " :""), name, + talloc_total_size(ptr), + talloc_total_blocks(ptr)); + return; + } + + if (strcmp(name, "char") == 0) { + /* + * Print out the first 50 bytes of the string + */ + fprintf(f, + "%*s%-30s contains %6zu bytes in %3zu blocks " + "(ref %zu): %*s\n", depth*4, "", name, + talloc_total_size(ptr), + talloc_total_blocks(ptr), + talloc_reference_count(ptr), + (int)MIN(50, talloc_get_size(ptr)), + (const char *)ptr); + return; + } + + fprintf(f, + "%*s%-30s contains %6zu bytes in %3zu blocks (ref %zu) %p\n", + depth*4, "", name, + talloc_total_size(ptr), + talloc_total_blocks(ptr), + talloc_reference_count(ptr), + ptr); +} + +void talloc_full_report_printf(TALLOC_CTX *root, FILE *f) +{ + talloc_report_depth_cb(root, 0, -1, talloc_report_printf_helper, f); +#if defined(HAVE_MALLINFO2) + { + struct mallinfo2 mi2 = mallinfo2(); + + fprintf(f, + "mallinfo:\n" + " arena: %zu\n" + " ordblks: %zu\n" + " smblks: %zu\n" + " hblks: %zu\n" + " hblkhd: %zu\n" + " usmblks: %zu\n" + " fsmblks: %zu\n" + " uordblks: %zu\n" + " fordblks: %zu\n" + " keepcost: %zu\n", + mi2.arena, + mi2.ordblks, + mi2.smblks, + mi2.hblks, + mi2.hblkhd, + mi2.usmblks, + mi2.fsmblks, + mi2.uordblks, + mi2.fordblks, + mi2.keepcost); + } +#elif defined(HAVE_MALLINFO) + { + struct mallinfo mi = mallinfo(); + + fprintf(f, + "mallinfo:\n" + " arena: %d\n" + " ordblks: %d\n" + " smblks: %d\n" + " hblks: %d\n" + " hblkhd: %d\n" + " usmblks: %d\n" + " fsmblks: %d\n" + " uordblks: %d\n" + " fordblks: %d\n" + " keepcost: %d\n", + mi.arena, + mi.ordblks, + mi.smblks, + mi.hblks, + mi.hblkhd, + mi.usmblks, + mi.fsmblks, + mi.uordblks, + mi.fordblks, + mi.keepcost); + } +#endif /* HAVE_MALLINFO2 or HAVE_MALLINFO */ +} diff --git a/lib/util/talloc_report_printf.h b/lib/util/talloc_report_printf.h new file mode 100644 index 0000000..7881e65 --- /dev/null +++ b/lib/util/talloc_report_printf.h @@ -0,0 +1,29 @@ +/* + * talloc_report into a FILE + * + * Copyright Volker Lendecke <vl@samba.org> 2019 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _TALLOC_REPORT_PRINTF_H_ +#define _TALLOC_REPORT_PRINTF_H_ + +#include "replace.h" +#include "system/filesys.h" +#include <talloc.h> + +void talloc_full_report_printf(TALLOC_CTX *root, FILE *f); + +#endif diff --git a/lib/util/talloc_stack.c b/lib/util/talloc_stack.c new file mode 100644 index 0000000..fdd0a30 --- /dev/null +++ b/lib/util/talloc_stack.c @@ -0,0 +1,259 @@ +/* + Unix SMB/CIFS implementation. + Implement a stack of talloc contexts + Copyright (C) Volker Lendecke 2007 + Copyright (C) Jeremy Allison 2009 - made thread safe. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + * Implement a stack of talloc frames. + * + * When a new talloc stackframe is allocated with talloc_stackframe(), then + * the TALLOC_CTX returned with talloc_tos() is reset to that new + * frame. Whenever that stack frame is TALLOC_FREE()'ed, then the reverse + * happens: The previous talloc_tos() is restored. + * + * This API is designed to be robust in the sense that if someone forgets to + * TALLOC_FREE() a stackframe, then the next outer one correctly cleans up and + * resets the talloc_tos(). + * + * This robustness feature means that we can't rely on a linked list with + * talloc destructors because in a hierarchy of talloc destructors the parent + * destructor is called before its children destructors. The child destructor + * called after the parent would set the talloc_tos() to the wrong value. + */ + +#include "replace.h" +#include <talloc.h> +#include "lib/util/talloc_stack.h" +#include "lib/util/smb_threads.h" +#include "lib/util/smb_threads_internal.h" +#include "lib/util/fault.h" +#include "lib/util/debug.h" + +struct talloc_stackframe { + int talloc_stacksize; + int talloc_stack_arraysize; + TALLOC_CTX **talloc_stack; +}; + +/* + * In the single threaded case this is a pointer + * to the global talloc_stackframe. In the MT-case + * this is the pointer to the thread-specific key + * used to look up the per-thread talloc_stackframe + * pointer. + */ + +static void *global_ts; + +/* Variable to ensure TLS value is only initialized once. */ +static smb_thread_once_t ts_initialized = SMB_THREAD_ONCE_INIT; + +static void talloc_stackframe_init(void * unused) +{ + if (SMB_THREAD_CREATE_TLS("talloc_stackframe", global_ts)) { + smb_panic("talloc_stackframe_init create_tls failed"); + } +} + +static struct talloc_stackframe *talloc_stackframe_create(void) +{ +#if defined(PARANOID_MALLOC_CHECKER) +#ifdef calloc +#undef calloc +#endif +#endif + struct talloc_stackframe *ts = (struct talloc_stackframe *)calloc( + 1, sizeof(struct talloc_stackframe)); +#if defined(PARANOID_MALLOC_CHECKER) +#define calloc(n, s) __ERROR_DONT_USE_MALLOC_DIRECTLY +#endif + + if (!ts) { + smb_panic("talloc_stackframe_init malloc failed"); + } + + SMB_THREAD_ONCE(&ts_initialized, talloc_stackframe_init, NULL); + + if (SMB_THREAD_SET_TLS(global_ts, ts)) { + smb_panic("talloc_stackframe_init set_tls failed"); + } + return ts; +} + +static int talloc_pop(TALLOC_CTX *frame) +{ + struct talloc_stackframe *ts = + (struct talloc_stackframe *)SMB_THREAD_GET_TLS(global_ts); + size_t blocks; + int i; + + /* Catch lazy frame-freeing. */ + if (ts->talloc_stack[ts->talloc_stacksize-1] != frame) { + DEBUG(0, ("Freed frame %s, expected %s.\n", + talloc_get_name(frame), + talloc_get_name(ts->talloc_stack + [ts->talloc_stacksize-1]))); +#ifdef DEVELOPER + smb_panic("Frame not freed in order."); +#endif + } + + for (i=0; i<10; i++) { + + /* + * We have to free our children first, calling all + * destructors. If a destructor hanging deeply off + * "frame" uses talloc_tos() itself while freeing the + * toplevel frame, we panic because that nested + * talloc_tos() in the destructor does not find a + * stackframe anymore. + * + * Do it in a loop up to 10 times as the destructors + * might use more of talloc_tos(). + */ + + talloc_free_children(frame); + + blocks = talloc_total_blocks(frame); + if (blocks == 1) { + break; + } + } + + if (blocks != 1) { + DBG_WARNING("Left %zu blocks after %i " + "talloc_free_children(frame) calls\n", + blocks, i); + } + + for (i=ts->talloc_stacksize-1; i>0; i--) { + if (frame == ts->talloc_stack[i]) { + break; + } + TALLOC_FREE(ts->talloc_stack[i]); + } + + ts->talloc_stack[i] = NULL; + ts->talloc_stacksize = i; + return 0; +} + +/* + * Create a new talloc stack frame. + * + * When free'd, it frees all stack frames that were created after this one and + * not explicitly freed. + */ + +static TALLOC_CTX *talloc_stackframe_internal(const char *location, + size_t poolsize) +{ + TALLOC_CTX **tmp, *top; + struct talloc_stackframe *ts = + (struct talloc_stackframe *)SMB_THREAD_GET_TLS(global_ts); + + if (ts == NULL) { + ts = talloc_stackframe_create(); + } + + if (ts->talloc_stack_arraysize < ts->talloc_stacksize + 1) { + tmp = talloc_realloc(NULL, ts->talloc_stack, TALLOC_CTX *, + ts->talloc_stacksize + 1); + if (tmp == NULL) { + goto fail; + } + ts->talloc_stack = tmp; + ts->talloc_stack_arraysize = ts->talloc_stacksize + 1; + } + + if (poolsize) { + top = talloc_pool(ts->talloc_stack, poolsize); + } else { + TALLOC_CTX *parent; + /* We chain parentage, so if one is a pool we draw from it. */ + if (ts->talloc_stacksize == 0) { + parent = ts->talloc_stack; + } else { + parent = ts->talloc_stack[ts->talloc_stacksize-1]; + } + top = talloc_new(parent); + } + + if (top == NULL) { + goto fail; + } + talloc_set_name_const(top, location); + talloc_set_destructor(top, talloc_pop); + + ts->talloc_stack[ts->talloc_stacksize++] = top; + return top; + + fail: + smb_panic("talloc_stackframe failed"); + return NULL; +} + +TALLOC_CTX *_talloc_stackframe(const char *location) +{ + return talloc_stackframe_internal(location, 0); +} + +TALLOC_CTX *_talloc_stackframe_pool(const char *location, size_t poolsize) +{ + return talloc_stackframe_internal(location, poolsize); +} + +/* + * Get us the current top of the talloc stack. + */ + +TALLOC_CTX *_talloc_tos(const char *location) +{ + struct talloc_stackframe *ts = + (struct talloc_stackframe *)SMB_THREAD_GET_TLS(global_ts); + + if (ts == NULL || ts->talloc_stacksize == 0) { + _talloc_stackframe(location); + ts = (struct talloc_stackframe *)SMB_THREAD_GET_TLS(global_ts); + DEBUG(0, ("no talloc stackframe at %s, leaking memory\n", + location)); +#ifdef DEVELOPER + smb_panic("No talloc stackframe"); +#endif + } + + return ts->talloc_stack[ts->talloc_stacksize-1]; +} + +/* + * return true if a talloc stackframe exists + * this can be used to prevent memory leaks for code that can + * optionally use a talloc stackframe (eg. nt_errstr()) + */ + +bool talloc_stackframe_exists(void) +{ + struct talloc_stackframe *ts = + (struct talloc_stackframe *)SMB_THREAD_GET_TLS(global_ts); + + if (ts == NULL || ts->talloc_stacksize == 0) { + return false; + } + return true; +} diff --git a/lib/util/talloc_stack.h b/lib/util/talloc_stack.h new file mode 100644 index 0000000..fceb41f --- /dev/null +++ b/lib/util/talloc_stack.h @@ -0,0 +1,66 @@ +/* + Unix SMB/CIFS implementation. + Implement a stack of talloc contexts + Copyright (C) Volker Lendecke 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * Implement a stack of talloc frames. + * + * When a new talloc stackframe is allocated with talloc_stackframe(), then + * the TALLOC_CTX returned with talloc_tos() is reset to that new + * frame. Whenever that stack frame is TALLOC_FREE()'ed, then the reverse + * happens: The previous talloc_tos() is restored. + * + * This API is designed to be robust in the sense that if someone forgets to + * TALLOC_FREE() a stackframe, then the next outer one correctly cleans up and + * resets the talloc_tos(). + * + */ + +#ifndef _TALLOC_STACK_H +#define _TALLOC_STACK_H + +#include <talloc.h> + +/* + * Create a new talloc stack frame. + * + * When free'd, it frees all stack frames that were created after this one and + * not explicitly freed. + */ + +#define talloc_stackframe() _talloc_stackframe(__location__) +#define talloc_stackframe_pool(sz) _talloc_stackframe_pool(__location__, (sz)) +TALLOC_CTX *_talloc_stackframe(const char *location); +TALLOC_CTX *_talloc_stackframe_pool(const char *location, size_t poolsize); + +/* + * Get us the current top of the talloc stack. + */ + +#define talloc_tos() _talloc_tos(__location__) +TALLOC_CTX *_talloc_tos(const char *location); + +/* + * return true if a talloc stackframe exists + * this can be used to prevent memory leaks for code that can + * optionally use a talloc stackframe (eg. nt_errstr()) + */ + +bool talloc_stackframe_exists(void); + +#endif diff --git a/lib/util/tests/README b/lib/util/tests/README new file mode 100644 index 0000000..c1337d5 --- /dev/null +++ b/lib/util/tests/README @@ -0,0 +1,22 @@ +tfork tests +=========== + +To run the tfork torture testsuite under valgrind with the helgrind or drd +thread checkers, run valgrind with the --suppress option passing a suppressions +file. + +For helgrind: + +$ valgrind \ + --trace-children=yes \ + --tool=helgrind \ + --suppressions=lib/util/tests/tfork-helgrind.supp \ + ./bin/smbtorture ncalrpc:localhost local.tfork.tfork_threads + +For drd: + +$ valgrind \ + --trace-children=yes \ + --tool=drd \ + --suppressions=lib/util/tests/tfork-drd.supp \ + ./bin/smbtorture ncalrpc:localhost local.tfork.tfork_threads diff --git a/lib/util/tests/anonymous_shared.c b/lib/util/tests/anonymous_shared.c new file mode 100644 index 0000000..512a53f --- /dev/null +++ b/lib/util/tests/anonymous_shared.c @@ -0,0 +1,70 @@ +/* + Unix SMB/CIFS implementation. + + anonymous_shared testing + + Copyright (C) Stefan Metzmacher 2011 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "torture/local/proto.h" + +static bool test_anonymous_shared_simple(struct torture_context *tctx) +{ + void *ptr; + size_t len; + + torture_comment(tctx, "anonymous_shared_free(NULL)\n"); + anonymous_shared_free(NULL); + + len = 500; + torture_comment(tctx, "anonymous_shared_allocate(%llu)\n", + (unsigned long long)len); + ptr = anonymous_shared_allocate(len); + torture_assert(tctx, ptr, "valid pointer"); + memset(ptr, 0xfe, len); + torture_comment(tctx, "anonymous_shared_free(ptr)\n"); + anonymous_shared_free(ptr); + + len = 50000; + torture_comment(tctx, "anonymous_shared_allocate(%llu)\n", + (unsigned long long)len); + ptr = anonymous_shared_allocate(len); + torture_assert(tctx, ptr, "valid pointer"); + memset(ptr, 0xfe, len); + torture_comment(tctx, "anonymous_shared_free(ptr)\n"); + anonymous_shared_free(ptr); + + memset(&len, 0xFF, sizeof(len)); + torture_comment(tctx, "anonymous_shared_allocate(%llu)\n", + (unsigned long long)len); + ptr = anonymous_shared_allocate(len); + torture_assert(tctx, ptr == NULL, "null pointer"); + + return true; +} + +/* local.anonymous_shared test suite creation */ +struct torture_suite *torture_local_util_anonymous_shared(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "anonymous_shared"); + + torture_suite_add_simple_test(suite, "simple", + test_anonymous_shared_simple); + + return suite; +} diff --git a/lib/util/tests/asn1_tests.c b/lib/util/tests/asn1_tests.c new file mode 100644 index 0000000..f2bd163 --- /dev/null +++ b/lib/util/tests/asn1_tests.c @@ -0,0 +1,383 @@ +/* + Unix SMB/CIFS implementation. + + util_asn1 testing + + Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2009 + Copyright (C) Volker Lendecke 2004 + Copyright (C) Andrew Bartlett 2011 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "torture/local/proto.h" +#include "../asn1.h" + +struct oid_data { + const char *oid; /* String OID */ + const char *bin_oid; /* Binary OID represented as string */ +}; + +/* Data for successful OIDs conversions */ +static const struct oid_data oid_data_ok[] = { + { + .oid = "2.5.4.0", + .bin_oid = "550400" + }, + { + .oid = "2.5.4.1", + .bin_oid = "550401" + }, + { + .oid = "2.5.4.130", + .bin_oid = "55048102" + }, + { + .oid = "2.5.130.4", + .bin_oid = "55810204" + }, + { + .oid = "2.5.4.16387", + .bin_oid = "5504818003" + }, + { + .oid = "2.5.16387.4", + .bin_oid = "5581800304" + }, + { + .oid = "2.5.2097155.4", + .bin_oid = "558180800304" + }, + { + .oid = "2.5.4.130.16387.2097155.268435459", + .bin_oid = "55048102818003818080038180808003" + }, +}; + +/* Data for successful OIDs conversions */ +static const char *oid_data_err[] = { + "", /* empty OID */ + ".2.5.4.130", /* first sub-identifier is empty */ + "2.5.4.130.", /* last sub-identifier is empty */ + "2..5.4.130", /* second sub-identifier is empty */ + "2.5..4.130", /* third sub-identifier is empty */ + "2.abc.4.130", /* invalid sub-identifier */ + "2.5abc.4.130", /* invalid sub-identifier (alphanumeric)*/ +}; + +/* Data for successful Partial OIDs conversions */ +static const struct oid_data partial_oid_data_ok[] = { + { + .oid = "2.5.4.130:0x81", + .bin_oid = "5504810281" + }, + { + .oid = "2.5.4.16387:0x8180", + .bin_oid = "55048180038180" + }, + { + .oid = "2.5.4.16387:0x81", + .bin_oid = "550481800381" + }, + { + .oid = "2.5.2097155.4:0x818080", + .bin_oid = "558180800304818080" + }, + { + .oid = "2.5.2097155.4:0x8180", + .bin_oid = "5581808003048180" + }, + { + .oid = "2.5.2097155.4:0x81", + .bin_oid = "55818080030481" + }, +}; + +static const struct { + DATA_BLOB blob; + int value; +} integer_tests[] = { + { + .blob = { discard_const_p(uint8_t, "\x02\x01\x00"), 3}, + .value = 0 + }, + { + .blob = { discard_const_p(uint8_t, "\x02\x01\x7f"), 3}, + .value = 127 + }, + { + .blob = { discard_const_p(uint8_t, "\x02\x02\x00\x80"), 4}, + .value = 128 + }, + { + .blob = { discard_const_p(uint8_t, "\x02\x02\x01\x00"), 4}, + .value = 256 + }, + { + .blob = { discard_const_p(uint8_t, "\x02\x01\x80"), 3}, + .value = -128 + }, + { + .blob = { discard_const_p(uint8_t, "\x02\x02\xff\x7f"), 4}, + .value = -129 + }, + { + .blob = { discard_const_p(uint8_t, "\x02\x01\xff"), 3}, + .value = -1 + }, + { + .blob = { discard_const_p(uint8_t, "\x02\x02\xff\x01"), 4}, + .value = -255 + }, + { + .blob = { discard_const_p(uint8_t, "\x02\x02\x00\xff"), 4}, + .value = 255 + }, + { + .blob = { discard_const_p(uint8_t, "\x02\x04\x80\x00\x00\x00"), 6}, + .value = 0x80000000 + }, + { + .blob = { discard_const_p(uint8_t, "\x02\x04\x7f\xff\xff\xff"), 6}, + .value = 0x7fffffff + } +}; + +/* Testing ber_write_OID_String() function */ +static bool test_ber_write_OID_String(struct torture_context *tctx) +{ + int i; + char *hex_str; + DATA_BLOB blob; + TALLOC_CTX *mem_ctx; + const struct oid_data *data = oid_data_ok; + + mem_ctx = talloc_new(tctx); + + /* check for valid OIDs */ + for (i = 0; i < ARRAY_SIZE(oid_data_ok); i++) { + torture_assert(tctx, ber_write_OID_String(mem_ctx, &blob, data[i].oid), + "ber_write_OID_String failed"); + + hex_str = hex_encode_talloc(mem_ctx, blob.data, blob.length); + torture_assert(tctx, hex_str, "No memory!"); + + torture_assert(tctx, strequal(data[i].bin_oid, hex_str), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + /* check for invalid OIDs */ + for (i = 0; i < ARRAY_SIZE(oid_data_err); i++) { + torture_assert(tctx, + !ber_write_OID_String(mem_ctx, &blob, oid_data_err[i]), + talloc_asprintf(mem_ctx, + "Should fail for [%s] -> %s", + oid_data_err[i], + hex_encode_talloc(mem_ctx, blob.data, blob.length))); + } + + talloc_free(mem_ctx); + + return true; +} + +/* Testing ber_read_OID_String() function */ +static bool test_ber_read_OID_String(struct torture_context *tctx) +{ + int i; + char *oid; + DATA_BLOB oid_blob; + TALLOC_CTX *mem_ctx; + const struct oid_data *data = oid_data_ok; + + mem_ctx = talloc_new(tctx); + + for (i = 0; i < ARRAY_SIZE(oid_data_ok); i++) { + oid_blob = strhex_to_data_blob(mem_ctx, data[i].bin_oid); + + torture_assert(tctx, ber_read_OID_String(mem_ctx, oid_blob, &oid), + "ber_read_OID_String failed"); + + torture_assert(tctx, strequal(data[i].oid, oid), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + talloc_free(mem_ctx); + + return true; +} + +/* Testing ber_write_partial_OID_String() function */ +static bool test_ber_write_partial_OID_String(struct torture_context *tctx) +{ + int i; + char *hex_str; + DATA_BLOB blob; + TALLOC_CTX *mem_ctx; + const struct oid_data *data = oid_data_ok; + + mem_ctx = talloc_new(tctx); + + /* ber_write_partial_OID_String() should work with not partial OIDs also */ + for (i = 0; i < ARRAY_SIZE(oid_data_ok); i++) { + torture_assert(tctx, ber_write_partial_OID_String(mem_ctx, &blob, data[i].oid), + "ber_write_partial_OID_String failed"); + + hex_str = hex_encode_talloc(mem_ctx, blob.data, blob.length); + torture_assert(tctx, hex_str, "No memory!"); + + torture_assert(tctx, strequal(data[i].bin_oid, hex_str), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + /* ber_write_partial_OID_String() test with partial OIDs */ + data = partial_oid_data_ok; + for (i = 0; i < ARRAY_SIZE(partial_oid_data_ok); i++) { + torture_assert(tctx, ber_write_partial_OID_String(mem_ctx, &blob, data[i].oid), + "ber_write_partial_OID_String failed"); + + hex_str = hex_encode_talloc(mem_ctx, blob.data, blob.length); + torture_assert(tctx, hex_str, "No memory!"); + + torture_assert(tctx, strequal(data[i].bin_oid, hex_str), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + talloc_free(mem_ctx); + + return true; +} + +/* Testing ber_read_partial_OID_String() function */ +static bool test_ber_read_partial_OID_String(struct torture_context *tctx) +{ + int i; + char *oid; + DATA_BLOB oid_blob; + TALLOC_CTX *mem_ctx; + const struct oid_data *data = oid_data_ok; + + mem_ctx = talloc_new(tctx); + + /* ber_read_partial_OID_String() should work with not partial OIDs also */ + for (i = 0; i < ARRAY_SIZE(oid_data_ok); i++) { + oid_blob = strhex_to_data_blob(mem_ctx, data[i].bin_oid); + + torture_assert(tctx, ber_read_partial_OID_String(mem_ctx, oid_blob, &oid), + "ber_read_partial_OID_String failed"); + + torture_assert(tctx, strequal(data[i].oid, oid), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + /* ber_read_partial_OID_String() test with partial OIDs */ + data = partial_oid_data_ok; + for (i = 0; i < ARRAY_SIZE(partial_oid_data_ok); i++) { + oid_blob = strhex_to_data_blob(mem_ctx, data[i].bin_oid); + + torture_assert(tctx, ber_read_partial_OID_String(mem_ctx, oid_blob, &oid), + "ber_read_partial_OID_String failed"); + + torture_assert(tctx, strequal(data[i].oid, oid), + talloc_asprintf(mem_ctx, + "Failed: oid=%s, bin_oid:%s", + data[i].oid, data[i].bin_oid)); + } + + talloc_free(mem_ctx); + + return true; +} + +/* + * Testing asn1_read_Integer and asn1_write_Integer functions, + * inspired by Love Hornquist Astrand + */ + +static bool test_asn1_Integer(struct torture_context *tctx) +{ + int i; + TALLOC_CTX *mem_ctx; + bool ret = false; + + mem_ctx = talloc_new(tctx); + + for (i = 0; i < ARRAY_SIZE(integer_tests); i++) { + ASN1_DATA *data; + DATA_BLOB blob; + int val; + + data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH); + if (!data) { + goto err; + } + + if (!asn1_write_Integer(data, integer_tests[i].value)) goto err; + + if (!asn1_blob(data, &blob)) { + goto err; + } + + torture_assert_data_blob_equal(tctx, blob, integer_tests[i].blob, "asn1_write_Integer gave incorrect result"); + + if (!asn1_load(data, blob)) goto err; + torture_assert(tctx, asn1_read_Integer(data, &val), "asn1_write_Integer output could not be read by asn1_read_Integer()"); + + torture_assert_int_equal(tctx, val, integer_tests[i].value, + "readback of asn1_write_Integer output by asn1_read_Integer() failed"); + } + + ret = true; + + err: + + talloc_free(mem_ctx); + return ret; +} + + +/* LOCAL-ASN1 test suite creation */ +struct torture_suite *torture_local_util_asn1(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "asn1"); + + torture_suite_add_simple_test(suite, "ber_write_OID_String", + test_ber_write_OID_String); + + torture_suite_add_simple_test(suite, "ber_read_OID_String", + test_ber_read_OID_String); + + torture_suite_add_simple_test(suite, "ber_write_partial_OID_String", + test_ber_write_partial_OID_String); + + torture_suite_add_simple_test(suite, "ber_read_partial_OID_String", + test_ber_read_partial_OID_String); + + torture_suite_add_simple_test(suite, "asn1_Integer", + test_asn1_Integer); + + return suite; +} diff --git a/lib/util/tests/binsearch.c b/lib/util/tests/binsearch.c new file mode 100644 index 0000000..b3ecda1 --- /dev/null +++ b/lib/util/tests/binsearch.c @@ -0,0 +1,173 @@ +/* + Unix SMB/CIFS implementation. + + Tests for binsearch.h macros. + + Copyright Catalyst IT 2016. + + Written by Douglas Bagnall <douglas.bagnall@catalyst.net.nz> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "lib/util/binsearch.h" +#include "torture/torture.h" +#include "torture/local/proto.h" + +static int int_cmp(int a, int b) +{ + return a - b; +} + +static int int_cmp_p(int a, int *b) +{ + return a - *b; +} + +static bool test_binsearch_v(struct torture_context *tctx) +{ + int array[] = { -11, -7, 0, 1, 723, 1000000}; + int misses[] = { -121, 17, -10, 10, -1, -723, 1000002}; + int i; + int *result = NULL; + + for (i = 0; i < ARRAY_SIZE(misses); i++) { + BINARY_ARRAY_SEARCH_V(array, ARRAY_SIZE(array), + misses[i], int_cmp, result); + torture_comment(tctx, "looking for misses[%d] == %d\n", i, misses[i]); + torture_assert(tctx, result == NULL, "failed to miss"); + } + + for (i = 0; i < ARRAY_SIZE(array); i++) { + BINARY_ARRAY_SEARCH_V(array, ARRAY_SIZE(array), + array[i], int_cmp, result); + torture_comment(tctx, "looking for array[%d] == %d, %p; got %p\n", + i, array[i], &array[i], result); + torture_assert(tctx, result == &array[i], + "failed to find element"); + } + return true; +} + +static bool test_binsearch_gte(struct torture_context *tctx) +{ + int array[] = { -11, -7, -7, -7, -1, 0, 0, 1, 723, 723, 723, + 724, 724, 10000}; + size_t a_len = ARRAY_SIZE(array); + int targets[] = { -121, -8, -7, -6, 17, -10, 10, -1, 723, + 724, 725, 10002, 10000, 0, -11, 1, 11}; + int i, j, target; + int *result = NULL, *next = NULL; + + for (i = 0; i < ARRAY_SIZE(targets); i++) { + target = targets[i]; + torture_comment(tctx, "looking for targets[%d] %d\n", + i, target); + + BINARY_ARRAY_SEARCH_GTE(array, a_len, target, + int_cmp_p, result, next); + + if (result == NULL) { + /* we think there is no exact match */ + for (j = 0; j < a_len; j++) { + if (target == array[j]) { + torture_comment(tctx, + "failed to find %d\n", + targets[i]); + torture_fail(tctx, + "result is wrongly NULL"); + } + } + if (next != NULL) { + torture_assert(tctx, (next >= array && + next < array + a_len), + "next is out of bounds"); + + torture_assert(tctx, *next > target, + "next <= target"); + if (target <= array[0]) { + torture_assert(tctx, next == array, + "search before start failed"); + } + if (next != array) { + torture_assert(tctx, next[-1] < target, + "next[-1] >= target"); + } + } + else { + torture_assert(tctx, array[a_len - 1] < target, + "next was not found\n"); + } + } else { + /* we think we found an exact match */ + torture_assert(tctx, *result == target, + "result has wrong value"); + + torture_assert(tctx, (result >= array && + result < array + a_len), + "result is out of bounds!"); + + torture_assert(tctx, next == NULL, + "next should be NULL on exact match\n"); + if (result != array) { + torture_assert(tctx, result[-1] != target, + "didn't find first target\n"); + } + } + if (target >= array[a_len - 1]) { + torture_assert(tctx, next == NULL, + "next is not NULL at array end\n"); + } + } + + /* try again, with result and next the same pointer */ + for (i = 0; i < ARRAY_SIZE(targets); i++) { + target = targets[i]; + torture_comment(tctx, "looking for targets[%d] %d\n", + i, target); + + BINARY_ARRAY_SEARCH_GTE(array, a_len, target, + int_cmp_p, result, result); + + if (result == NULL) { + /* we think the target is greater than all elements */ + torture_assert(tctx, array[a_len - 1] < target, + "element >= target not found\n"); + } else { + /* we think an element is >= target */ + torture_assert(tctx, *result >= target, + "result has wrong value"); + + torture_assert(tctx, (result >= array && + result < array + a_len), + "result is out of bounds!"); + + if (result != array) { + torture_assert(tctx, result[-1] < target, + "didn't find first target\n"); + } + } + } + + return true; +} + +struct torture_suite *torture_local_util_binsearch(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "binsearch"); + torture_suite_add_simple_test(suite, "binsearch_v", test_binsearch_v); + torture_suite_add_simple_test(suite, "binsearch_gte", test_binsearch_gte); + return suite; +} diff --git a/lib/util/tests/data_blob.c b/lib/util/tests/data_blob.c new file mode 100644 index 0000000..e1e8129 --- /dev/null +++ b/lib/util/tests/data_blob.c @@ -0,0 +1,172 @@ +/* + Unix SMB/CIFS implementation. + + data blob testing + + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "torture/local/proto.h" + +static bool test_string(struct torture_context *tctx) +{ + DATA_BLOB blob = data_blob_string_const("bla"); + + torture_assert_int_equal(tctx, blob.length, 3, "blob length"); + torture_assert_str_equal(tctx, (char *)blob.data, "bla", "blob data"); + + return true; +} + +static bool test_string_null(struct torture_context *tctx) +{ + DATA_BLOB blob = data_blob_string_const_null("bla"); + + torture_assert_int_equal(tctx, blob.length, 4, "blob length"); + torture_assert_str_equal(tctx, (char *)blob.data, "bla", "blob data"); + + return true; +} + +static bool test_zero(struct torture_context *tctx) +{ + int i; + DATA_BLOB z = data_blob_talloc_zero(tctx, 4); + torture_assert_int_equal(tctx, z.length, 4, "length"); + for (i = 0; i < z.length; i++) + torture_assert_int_equal(tctx, z.data[i], 0, "contents"); + data_blob_free(&z); + return true; +} + + +static bool test_clear(struct torture_context *tctx) +{ + int i; + DATA_BLOB z = data_blob("lalala", 6); + torture_assert_int_equal(tctx, z.length, 6, "length"); + data_blob_clear(&z); + for (i = 0; i < z.length; i++) + torture_assert_int_equal(tctx, z.data[i], 0, "contents"); + data_blob_free(&z); + return true; +} + +static bool test_cmp(struct torture_context *tctx) +{ + DATA_BLOB a = data_blob_string_const("bla"); + DATA_BLOB b = data_blob_string_const("blae"); + torture_assert(tctx, data_blob_cmp(&a, &b) != 0, "cmp different"); + torture_assert(tctx, data_blob_cmp(&a, &a) == 0, "cmp self"); + return true; +} + +static bool test_equal_const_time(struct torture_context *tctx) +{ + const char *test_string = "foobarfoo"; + + DATA_BLOB null = data_blob_const(NULL, 0); + DATA_BLOB foobar = data_blob_const(test_string, 6); + DATA_BLOB bar = data_blob_const(test_string + 3, 3); + + /* These data blobs both contain 'foo', but at different addresses. */ + DATA_BLOB foo_same = data_blob_const(test_string, 3); + DATA_BLOB foo_other = data_blob_const(test_string + 6, 3); + + /* Test all equality combinations behave as expected. */ + torture_assert(tctx, data_blob_equal_const_time(&null, &null), "null == null"); + torture_assert(tctx, !data_blob_equal_const_time(&null, &foobar), "null != 'foobar'"); + torture_assert(tctx, !data_blob_equal_const_time(&null, &bar), "null != 'bar'"); + torture_assert(tctx, !data_blob_equal_const_time(&null, &foo_same), "null != 'foo'"); + torture_assert(tctx, !data_blob_equal_const_time(&null, &foo_other), "null != 'foo'"); + + torture_assert(tctx, !data_blob_equal_const_time(&foobar, &null), "'foobar' != null"); + torture_assert(tctx, data_blob_equal_const_time(&foobar, &foobar), "'foobar' == 'foobar'"); + torture_assert(tctx, !data_blob_equal_const_time(&foobar, &bar), "'foobar' != 'bar'"); + torture_assert(tctx, !data_blob_equal_const_time(&foobar, &foo_same), "'foobar' != 'foo'"); + torture_assert(tctx, !data_blob_equal_const_time(&foobar, &foo_other), "'foobar' != 'foo'"); + + torture_assert(tctx, !data_blob_equal_const_time(&foo_same, &null), "'foo' != null"); + torture_assert(tctx, !data_blob_equal_const_time(&foo_same, &foobar), "'foo' != 'foobar'"); + torture_assert(tctx, !data_blob_equal_const_time(&foo_same, &bar), "'foo' != 'bar'"); + torture_assert(tctx, data_blob_equal_const_time(&foo_same, &foo_same), "'foo' == 'foo'"); + torture_assert(tctx, data_blob_equal_const_time(&foo_same, &foo_other), "'foo' == 'foo'"); + + torture_assert(tctx, !data_blob_equal_const_time(&foo_other, &null), "'foo' != null"); + torture_assert(tctx, !data_blob_equal_const_time(&foo_other, &foobar), "'foo' != 'foobar'"); + torture_assert(tctx, !data_blob_equal_const_time(&foo_other, &bar), "'foo' != 'bar'"); + torture_assert(tctx, data_blob_equal_const_time(&foo_other, &foo_same), "'foo' == 'foo'"); + torture_assert(tctx, data_blob_equal_const_time(&foo_other, &foo_other), "'foo' == 'foo'"); + + torture_assert(tctx, !data_blob_equal_const_time(&bar, &null), "'bar' != null"); + torture_assert(tctx, !data_blob_equal_const_time(&bar, &foobar), "'bar' != 'foobar'"); + torture_assert(tctx, data_blob_equal_const_time(&bar, &bar), "'bar' == 'bar'"); + torture_assert(tctx, !data_blob_equal_const_time(&bar, &foo_same), "'bar' != 'foo'"); + torture_assert(tctx, !data_blob_equal_const_time(&bar, &foo_other), "'bar' != 'foo'"); + + return true; +} + +static bool test_hex_string(struct torture_context *tctx) +{ + DATA_BLOB a = data_blob_string_const("\xC\xA\xF\xE"); + torture_assert_str_equal(tctx, data_blob_hex_string_lower(tctx, &a), "0c0a0f0e", "hex string"); + torture_assert_str_equal(tctx, data_blob_hex_string_upper(tctx, &a), "0C0A0F0E", "hex string"); + return true; +} + +static bool test_append_NULL_0(struct torture_context *tctx) +{ + DATA_BLOB z = data_blob_talloc_zero(tctx, 0); + torture_assert_int_equal(tctx, z.length, 0, "length"); + torture_assert(tctx, z.data == NULL, "data"); + torture_assert(tctx, data_blob_append(NULL, &z, NULL, 0), "append NULL,0"); + torture_assert(tctx, data_blob_append(NULL, &z, "", 0), "append '',0"); + torture_assert_int_equal(tctx, z.length, 0, "length"); + torture_assert(tctx, z.data == NULL, "data"); + return true; +} + +static bool test_append_empty_0(struct torture_context *tctx) +{ + DATA_BLOB e = data_blob_talloc(tctx, "", 0); + torture_assert_int_equal(tctx, e.length, 0, "length"); + torture_assert(tctx, e.data != NULL, "data"); + torture_assert(tctx, data_blob_append(NULL, &e, NULL, 0), "append NULL,0"); + torture_assert(tctx, data_blob_append(NULL, &e, "", 0), "append '',0"); + torture_assert_int_equal(tctx, e.length, 0, "length"); + torture_assert(tctx, e.data != NULL, "data"); + return true; +} + +struct torture_suite *torture_local_util_data_blob(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "datablob"); + + torture_suite_add_simple_test(suite, "string", test_string); + torture_suite_add_simple_test(suite, "string_null", test_string_null); + torture_suite_add_simple_test(suite, "zero", test_zero);; + torture_suite_add_simple_test(suite, "clear", test_clear); + torture_suite_add_simple_test(suite, "cmp", test_cmp); + torture_suite_add_simple_test(suite, "equal_const_time", test_equal_const_time); + torture_suite_add_simple_test(suite, "hex string", test_hex_string); + torture_suite_add_simple_test(suite, "append_NULL_0", test_append_NULL_0); + torture_suite_add_simple_test(suite, "append_empty_0", test_append_empty_0); + + return suite; +} diff --git a/lib/util/tests/dlinklist.c b/lib/util/tests/dlinklist.c new file mode 100644 index 0000000..50adab3 --- /dev/null +++ b/lib/util/tests/dlinklist.c @@ -0,0 +1,131 @@ +/* + Unix SMB/CIFS implementation. + + local testing of DLIST_*() macros + + Copyright (C) Andrew Tridgell 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "torture/local/proto.h" +#include "lib/util/dlinklist.h" + +struct listel { + struct listel *next, *prev; +}; + +static bool torture_local_dlinklist_simple(struct torture_context *tctx) +{ + TALLOC_CTX *mem_ctx = talloc_new(tctx); + struct listel *l1 = NULL, *l2 = NULL, *el, *el2; + int i; + + torture_comment(tctx, "add 5 elements at front\n"); + for (i=0; i<5; i++) { + el = talloc(mem_ctx, struct listel); + DLIST_ADD(l1, el); + } + + torture_comment(tctx, "add 5 elements at end\n"); + for (i=0; i<5; i++) { + el = talloc(mem_ctx, struct listel); + DLIST_ADD_END(l1, el); + } + + torture_comment(tctx, "delete 3 from front\n"); + for (i=0; i < 3; i++) { + el = l1; + DLIST_REMOVE(l1, l1); + DLIST_ADD(l2, el); + } + + torture_comment(tctx, "delete 3 from back\n"); + for (i=0; i < 3; i++) { + el = DLIST_TAIL(l1); + DLIST_REMOVE(l1, el); + DLIST_ADD_END(l2, el); + } + + torture_comment(tctx, "count forward\n"); + for (i=0,el=l1; el; el=el->next) i++; + torture_assert_int_equal(tctx, i, 4, "should have 4 elements"); + + torture_comment(tctx, "count backwards\n"); + for (i=0,el=DLIST_TAIL(l1); el; el=DLIST_PREV(el)) i++; + torture_assert_int_equal(tctx, i, 4, "should have 4 elements"); + + torture_comment(tctx, "check DLIST_HEAD\n"); + el = DLIST_TAIL(l1); + DLIST_HEAD(el, el2); + torture_assert(tctx, el2 == l1, "should find head"); + + torture_comment(tctx, "check DLIST_ADD_AFTER\n"); + el = talloc(mem_ctx, struct listel); + el2 = talloc(mem_ctx, struct listel); + DLIST_ADD_AFTER(l1, el, l1); + DLIST_ADD_AFTER(l1, el2, el); + torture_assert(tctx, l1->next == el, "2nd in list"); + torture_assert(tctx, el->next == el2, "3rd in list"); + + torture_comment(tctx, "check DLIST_PROMOTE\n"); + DLIST_PROMOTE(l1, el2); + torture_assert(tctx, el2==l1, "1st in list"); + torture_assert(tctx, el2->next->next == el, "3rd in list"); + + torture_comment(tctx, "check DLIST_DEMOTE\n"); + DLIST_DEMOTE(l1, el); + torture_assert(tctx, el->next == NULL, "last in list"); + torture_assert(tctx, el2->prev == el, "backlink from head"); + + torture_comment(tctx, "count forward\n"); + for (i=0,el=l1; el; el=el->next) i++; + torture_assert_int_equal(tctx, i, 6, "should have 6 elements"); + + torture_comment(tctx, "count backwards\n"); + for (i=0,el=DLIST_TAIL(l1); el; el=DLIST_PREV(el)) i++; + torture_assert_int_equal(tctx, i, 6, "should have 6 elements"); + + torture_comment(tctx, "check DLIST_CONCATENATE\n"); + DLIST_CONCATENATE(l1, l2); + torture_comment(tctx, "count forward\n"); + for (i=0,el=l1; el; el=el->next) i++; + torture_assert_int_equal(tctx, i, 12, "should have 12 elements"); + + torture_comment(tctx, "count backwards\n"); + for (i=0,el=DLIST_TAIL(l1); el; el=DLIST_PREV(el)) i++; + torture_assert_int_equal(tctx, i, 12, "should have 12 elements"); + + torture_comment(tctx, "free forwards\n"); + for (el=l1; el; el=el2) { + el2 = el->next; + DLIST_REMOVE(l1, el); + talloc_free(el); + } + + torture_assert(tctx, l1 == NULL, "list empty"); + torture_assert_int_equal(tctx, talloc_total_blocks(mem_ctx), 1, "1 block"); + + talloc_free(mem_ctx); + return true; +} + +struct torture_suite *torture_local_dlinklist(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "dlinklist"); + torture_suite_add_simple_test(suite, "dlinklist", torture_local_dlinklist_simple); + return suite; +} diff --git a/lib/util/tests/file.c b/lib/util/tests/file.c new file mode 100644 index 0000000..3501c7e --- /dev/null +++ b/lib/util/tests/file.c @@ -0,0 +1,291 @@ +/* + Unix SMB/CIFS implementation. + + util_file testing + + Copyright (C) Jelmer Vernooij 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "torture/torture.h" +#include "torture/local/proto.h" + +#define TEST_FILENAME "utilfile.test" +#define TEST_LINE1 "This is list line 1..." +#define TEST_LINE2 ".. and this is line 2" +#define TEST_LINE3 "and end of the file" + +#define TEST_DATA TEST_LINE1 "\n" TEST_LINE2 "\n" TEST_LINE3 + +static bool test_file_load_save(struct torture_context *tctx) +{ + size_t len; + char *data; + TALLOC_CTX *mem_ctx = tctx; + + torture_assert(tctx, file_save(TEST_FILENAME, TEST_DATA, strlen(TEST_DATA)), + "saving file"); + + torture_assert_file_contains_text(tctx, TEST_FILENAME, TEST_DATA, + "file contents"); + + data = file_load(TEST_FILENAME, &len, 0, mem_ctx); + torture_assert(tctx, data, "loading file"); + + torture_assert_int_equal(tctx, len, strlen(TEST_DATA), "Length"); + + torture_assert_mem_equal(tctx, data, TEST_DATA, len, "Contents"); + + data = file_load(TEST_FILENAME, &len, 5, mem_ctx); + + torture_assert_int_equal(tctx, len, 5, "Length"); + + torture_assert_mem_equal(tctx, data, TEST_DATA, len, "Contents"); + + unlink(TEST_FILENAME); + return true; +} + +#define TEST_DATA_WITH_NEWLINE TEST_DATA "\n" +#define TEST_DATA_NO_NEWLINE TEST_DATA +#define TEST_DATA_EMPTY "" +#define TEST_DATA_BLANKS_ONLY "\n\n\n\n\n" +#define TEST_DATA_WITH_TRAILING_BLANKS TEST_DATA TEST_DATA_BLANKS_ONLY + +static bool test_file_lines_load(struct torture_context *tctx) +{ + char **lines; + int numlines; + TALLOC_CTX *mem_ctx = tctx; + + /* + * Last line has trailing whitespace + */ + + torture_assert(tctx, + file_save(TEST_FILENAME, + TEST_DATA_WITH_NEWLINE, + strlen(TEST_DATA_WITH_NEWLINE)), + "saving file"); + + lines = file_lines_load(TEST_FILENAME, &numlines, 0, mem_ctx); + + torture_assert_int_equal(tctx, numlines, 3, "Lines"); + + torture_assert_mem_equal(tctx, + lines[0], + TEST_LINE1, + strlen(TEST_LINE1), + "Line 1"); + + torture_assert_mem_equal(tctx, + lines[1], + TEST_LINE2, + strlen(TEST_LINE2), + "Line 2"); + + torture_assert_mem_equal(tctx, + lines[2], + TEST_LINE3, + strlen(TEST_LINE3), + "Line 3"); + + unlink(TEST_FILENAME); + + /* + * Last line has NO trailing whitespace + */ + + torture_assert(tctx, + file_save(TEST_FILENAME, + TEST_DATA_NO_NEWLINE, + strlen(TEST_DATA_NO_NEWLINE)), + "saving file"); + + lines = file_lines_load(TEST_FILENAME, &numlines, 0, mem_ctx); + + torture_assert_int_equal(tctx, numlines, 3, "Lines"); + + torture_assert_mem_equal(tctx, + lines[0], + TEST_LINE1, + strlen(TEST_LINE1), + "Line 1"); + + torture_assert_mem_equal(tctx, + lines[1], + TEST_LINE2, + strlen(TEST_LINE2), + "Line 2"); + + torture_assert_mem_equal(tctx, + lines[2], + TEST_LINE3, + strlen(TEST_LINE3), + "Line 3"); + + unlink(TEST_FILENAME); + + /* + * Empty file + */ + + torture_assert(tctx, + file_save(TEST_FILENAME, + TEST_DATA_EMPTY, + strlen(TEST_DATA_EMPTY)), + "saving file"); + + (void)file_lines_load(TEST_FILENAME, &numlines, 0, mem_ctx); + + torture_assert_int_equal(tctx, numlines, 0, "Lines"); + + unlink(TEST_FILENAME); + + /* + * Just blank lines + */ + + torture_assert(tctx, + file_save(TEST_FILENAME, + TEST_DATA_BLANKS_ONLY, + strlen(TEST_DATA_BLANKS_ONLY)), + "saving file"); + + lines = file_lines_load(TEST_FILENAME, &numlines, 0, mem_ctx); + + torture_assert_int_equal(tctx, numlines, 0, "Lines"); + + unlink(TEST_FILENAME); + + /* + * Several trailing blank lines + */ + + torture_assert(tctx, + file_save(TEST_FILENAME, + TEST_DATA_WITH_TRAILING_BLANKS, + strlen(TEST_DATA_WITH_TRAILING_BLANKS)), + "saving file"); + + lines = file_lines_load(TEST_FILENAME, &numlines, 0, mem_ctx); + + torture_assert_int_equal(tctx, numlines, 3, "Lines"); + + torture_assert_mem_equal(tctx, + lines[0], + TEST_LINE1, + strlen(TEST_LINE1), + "Line 1"); + + torture_assert_mem_equal(tctx, + lines[1], + TEST_LINE2, + strlen(TEST_LINE2), + "Line 2"); + + torture_assert_mem_equal(tctx, + lines[2], + TEST_LINE3, + strlen(TEST_LINE3), + "Line 3"); + + unlink(TEST_FILENAME); + + return true; +} + +static bool test_afdgets(struct torture_context *tctx) +{ + int fd; + char *line; + TALLOC_CTX *mem_ctx = tctx; + bool ret = false; + + torture_assert(tctx, file_save(TEST_FILENAME, (const void *)TEST_DATA, + strlen(TEST_DATA)), + "saving file"); + + fd = open(TEST_FILENAME, O_RDONLY); + + torture_assert(tctx, fd != -1, "opening file"); + + line = afdgets(fd, mem_ctx, 8); + torture_assert_goto(tctx, strcmp(line, TEST_LINE1) == 0, ret, done, + "line 1 mismatch"); + + line = afdgets(fd, mem_ctx, 8); + torture_assert_goto(tctx, strcmp(line, TEST_LINE2) == 0, ret, done, + "line 2 mismatch"); + + line = afdgets(fd, mem_ctx, 8); + torture_assert_goto(tctx, strcmp(line, TEST_LINE3) == 0, ret, done, + "line 3 mismatch"); + ret = true; +done: + close(fd); + + unlink(TEST_FILENAME); + return ret; +} + +static bool test_file_lines_parse(struct torture_context *tctx) +{ + char **lines; + int numlines; + TALLOC_CTX *mem_ctx = tctx; + char *buf; + size_t size; + + torture_assert(tctx, file_save(TEST_FILENAME, + (const void *)TEST_DATA, + strlen(TEST_DATA)), + "saving file"); + + buf = file_load(TEST_FILENAME, &size, 0, mem_ctx); + torture_assert(tctx, buf, "failed to load file"); + unlink(TEST_FILENAME); + + lines = file_lines_parse(buf, + size, + &numlines, + mem_ctx); + torture_assert(tctx, lines, "failed to parse lines"); + + TALLOC_FREE(lines); + TALLOC_FREE(buf); + return true; +} + +struct torture_suite *torture_local_util_file(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "file"); + + torture_suite_add_simple_test(suite, "file_load_save", + test_file_load_save); + + torture_suite_add_simple_test(suite, + "file_lines_load", + test_file_lines_load); + + torture_suite_add_simple_test(suite, "afdgets", test_afdgets); + + torture_suite_add_simple_test(suite, "file_lines_parse", + test_file_lines_parse); + + return suite; +} diff --git a/lib/util/tests/genrand.c b/lib/util/tests/genrand.c new file mode 100644 index 0000000..3987c33 --- /dev/null +++ b/lib/util/tests/genrand.c @@ -0,0 +1,61 @@ +/* + Unix SMB/CIFS implementation. + + local testing of random data routines. + + Copyright (C) Jelmer Vernooij <jelmer@samba.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "torture/local/proto.h" + +static bool test_check_password_quality(struct torture_context *tctx) +{ + torture_assert(tctx, !check_password_quality(""), "empty password"); + torture_assert(tctx, !check_password_quality("a"), "one char password"); + torture_assert(tctx, !check_password_quality("aaaaaaaaaaaa"), "same char password"); + torture_assert(tctx, !check_password_quality("BLA"), "multiple upcases password"); + torture_assert(tctx, !check_password_quality("123"), "digits only"); + torture_assert(tctx, !check_password_quality("matthiéu"), "not enough high symbols"); + torture_assert(tctx, !check_password_quality("abcdééàçè"), "only lower case"); + torture_assert(tctx, !check_password_quality("abcdééàçè+"), "only lower and symbols"); + torture_assert(tctx, check_password_quality("abcdééàçè+ढ"), "valid"); + torture_assert(tctx, check_password_quality("ç+ढ"), "valid"); + torture_assert(tctx, check_password_quality("A2e"), "valid"); + torture_assert(tctx, check_password_quality("BA2eLi443"), "valid"); + return true; +} + +static bool test_generate_random_str(struct torture_context *tctx) +{ + TALLOC_CTX *mem_ctx = talloc_init(__FUNCTION__); + char *r = generate_random_str(mem_ctx, 10); + torture_assert_int_equal(tctx, strlen(r), 10, "right length generated"); + r = generate_random_str(mem_ctx, 5); + torture_assert_int_equal(tctx, strlen(r), 5, "right length generated"); + + TALLOC_FREE(mem_ctx); + return true; +} + +struct torture_suite *torture_local_genrand(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "genrand"); + torture_suite_add_simple_test(suite, "check_password_quality", test_check_password_quality); + torture_suite_add_simple_test(suite, "generate_random_str", test_generate_random_str); + return suite; +} diff --git a/lib/util/tests/genrandperf.c b/lib/util/tests/genrandperf.c new file mode 100644 index 0000000..32d19ab --- /dev/null +++ b/lib/util/tests/genrandperf.c @@ -0,0 +1,39 @@ +/* + Unix SMB/CIFS implementation. + local testing of random data routines. + Copyright (C) Volker Lendecke <vl@samba.org> 2015 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "lib/util/genrand.h" + +int main(int argc, const char *argv[]) +{ + int i, num; + uint64_t val; + + if (argc != 2) { + fprintf(stderr, "genrandperf <num>\n"); + exit(1); + } + num = atoi(argv[1]); + + for(i=0; i<num; i++) { + generate_random_buffer((uint8_t *)&val, sizeof(val)); + } + printf("%"PRIu64"\n", val); + return 0; +} diff --git a/lib/util/tests/idtree.c b/lib/util/tests/idtree.c new file mode 100644 index 0000000..d54ab27 --- /dev/null +++ b/lib/util/tests/idtree.c @@ -0,0 +1,123 @@ +/* + Unix SMB/CIFS implementation. + + local testing of idtree routines. + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "torture/local/proto.h" +#include "lib/util/idtree.h" + +static bool torture_local_idtree_simple(struct torture_context *tctx) +{ + struct idr_context *idr; + int i, ret; + int *ids; + int *present; + extern int torture_numops; + int n = torture_numops; + TALLOC_CTX *mem_ctx = tctx; + + idr = idr_init(mem_ctx); + + ids = talloc_zero_array(mem_ctx, int, n); + present = talloc_zero_array(mem_ctx, int, n); + + for (i=0;i<n;i++) { + ids[i] = -1; + } + + for (i=0;i<n;i++) { + int ii = random() % n; + void *p = idr_find(idr, ids[ii]); + if (present[ii]) { + if (p != &ids[ii]) { + torture_fail(tctx, talloc_asprintf(tctx, + "wrong ptr at %d - %p should be %p", + ii, p, &ids[ii])); + } + if (random() % 7 == 0) { + if (idr_remove(idr, ids[ii]) != 0) { + torture_fail(tctx, talloc_asprintf(tctx, + "remove failed at %d (id=%d)", + i, ids[ii])); + } + present[ii] = 0; + ids[ii] = -1; + } + } else { + if (p != NULL) { + torture_fail(tctx, + talloc_asprintf(tctx, + "non-present at %d gave %p (would be %d)", + ii, p, + (int)((((char *)p) - (char *)(&ids[0])) / sizeof(int)))); + } + if (random() % 5) { + ids[ii] = idr_get_new(idr, &ids[ii], n); + if (ids[ii] < 0) { + torture_fail(tctx, talloc_asprintf(tctx, + "alloc failure at %d (ret=%d)", + ii, ids[ii])); + } else { + present[ii] = 1; + } + } + } + } + + torture_comment(tctx, "done %d random ops\n", i); + + for (i=0;i<n;i++) { + if (present[i]) { + if (idr_remove(idr, ids[i]) != 0) { + torture_fail(tctx, talloc_asprintf(tctx, + "delete failed on cleanup at %d (id=%d)", + i, ids[i])); + } + } + } + + /* now test some limits */ + for (i=0;i<25000;i++) { + ret = idr_get_new_above(idr, &ids[0], random() % 25000, 0x10000-3); + torture_assert(tctx, ret != -1, "idr_get_new_above failed"); + } + + ret = idr_get_new_above(idr, &ids[0], 0x10000-2, 0x10000); + torture_assert_int_equal(tctx, ret, 0x10000-2, "idr_get_new_above failed"); + ret = idr_get_new_above(idr, &ids[0], 0x10000-1, 0x10000); + torture_assert_int_equal(tctx, ret, 0x10000-1, "idr_get_new_above failed"); + ret = idr_get_new_above(idr, &ids[0], 0x10000, 0x10000); + torture_assert_int_equal(tctx, ret, 0x10000, "idr_get_new_above failed"); + ret = idr_get_new_above(idr, &ids[0], 0x10000+1, 0x10000); + torture_assert_int_equal(tctx, ret, -1, "idr_get_new_above succeeded above limit"); + ret = idr_get_new_above(idr, &ids[0], 0x10000+2, 0x10000); + torture_assert_int_equal(tctx, ret, -1, "idr_get_new_above succeeded above limit"); + + torture_comment(tctx, "cleaned up\n"); + return true; +} + +struct torture_suite *torture_local_idtree(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "idtree"); + torture_suite_add_simple_test(suite, "idtree", torture_local_idtree_simple); + return suite; +} diff --git a/lib/util/tests/rfc1738.c b/lib/util/tests/rfc1738.c new file mode 100644 index 0000000..4f7eced --- /dev/null +++ b/lib/util/tests/rfc1738.c @@ -0,0 +1,411 @@ +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <stdint.h> +#include <cmocka.h> +#include "lib/replace/replace.h" + +#include <errno.h> +#include <unistd.h> +#include <talloc.h> +#include <ctype.h> +#include <string.h> +#include "lib/util/samba_util.h" + +/* These flags say what can be asserted about a relationship between a string + and its supposedly escaped equivalent. + + The first part of the flag name indicates the direction of transformation; + the second part is the expected result. For example, ESCAPE_EQ means the + escape is expected to succeed and result is expected to be equal to the + given answer. ESCAPE_EQ_CASECMP is only equal when compared + case-insensitively. UNESCAPE_ERR means unescaping the escaped string should + result in an error. +*/ +#define UNESCAPE_ERR 1 +#define ESCAPE_ERR 2 +#define ESCAPE_EQ 4 +#define UNESCAPE_EQ 8 +#define ESCAPE_NE 16 +#define UNESCAPE_NE 32 +#define ESCAPE_EQ_CASECMP 64 + +struct rfc1738_test { + const char *escaped; /* original for unescape; result for escape */ + const char *unescaped; /* result in unescape; original for escape */ + uint32_t flags; /* see above */ + int unesc_len; /* end - start will be this */ + int unesc_strlen; /* strlen() will say this */ + int esc_len; /* escaped string length */ +}; + +/* unreserved = ALPHA DIGIT - . _ ~ */ + +char spectrum[255 + 1]; +char spectrum_escaped[255 * 3 + 1]; + +struct rfc1738_test examples[] = { + +#define SIMPLE1 "this_is_a_simple-string._With_no_escapes~" /* maps to self */ + { + SIMPLE1, + SIMPLE1, + ESCAPE_EQ | UNESCAPE_EQ, /* round trip should work */ + sizeof(SIMPLE1) - 1, + sizeof(SIMPLE1) - 1, + sizeof(SIMPLE1) - 1, + }, +#define SIMPLE2 "no escapes, but\n non-printables \xc5\x8d\x99" +#define SIMPLE2_ESC "no%20escapes%2C%20but%0A%20non-printables%20%C5%8D%99" + { + SIMPLE2_ESC, + SIMPLE2, + ESCAPE_EQ | UNESCAPE_EQ, + sizeof(SIMPLE2) - 1, + sizeof(SIMPLE2) - 1, + sizeof(SIMPLE2_ESC) - 1, + }, +#define SIMPLE3 "this @#$^&*()_+{}:;" +#define SIMPLE3_ESC "this%20%40%23%24%5E%26%2A%28%29_%2B%7B%7D%3A%3B" + { + SIMPLE3_ESC, + SIMPLE3, + ESCAPE_EQ | UNESCAPE_EQ, + sizeof(SIMPLE3) - 1, + sizeof(SIMPLE3) - 1, + sizeof(SIMPLE3_ESC) - 1, + }, + +#define ESCAPE1 "%/\x06this string has expected escapes" +#define ESCAPE1_ESC "%25%2F%06this%20string%20has%20expected%20escapes" +#define ESCAPE1_ESC_ESC "%2525%252F%2506this%2520string%2520has%2520expected"\ + "%2520escapes" + { + ESCAPE1_ESC, + ESCAPE1, + ESCAPE_EQ | UNESCAPE_EQ, + sizeof(ESCAPE1) - 1, + sizeof(ESCAPE1) - 1, + sizeof(ESCAPE1_ESC) - 1, + }, + { + ESCAPE1_ESC_ESC, /*re-escaping */ + ESCAPE1_ESC, + ESCAPE_EQ | UNESCAPE_EQ, + sizeof(ESCAPE1_ESC) - 1, + sizeof(ESCAPE1_ESC) - 1, + sizeof(ESCAPE1_ESC_ESC) - 1, + }, +#define ESCAPE2 "%25%2f%06-this-string-has-expected-lowercase-escapes-%ab" +#define ESCAPE2_UNESC "%/\x06-this-string-has-expected-lowercase-escapes-\xab" + { + ESCAPE2, + ESCAPE2_UNESC, + ESCAPE_EQ_CASECMP | UNESCAPE_EQ, /* escape won't match case */ + sizeof(ESCAPE2_UNESC) - 1, + sizeof(ESCAPE2_UNESC) - 1, + sizeof(ESCAPE2) - 1, + }, +#define ESCAPE3 "%25%2f%06 %32 %44 %6a%AA THIS string h%61s random escapes %ab" +#define ESCAPE3_UNESC "%/\x06 2 D j\xAA THIS string has random escapes \xab" + { + ESCAPE3, + ESCAPE3_UNESC, + ESCAPE_NE | UNESCAPE_EQ, /* escape will have escaped spaces */ + sizeof(ESCAPE3_UNESC) - 1, + sizeof(ESCAPE3_UNESC) - 1, + sizeof(ESCAPE3) - 1, + }, +#define ESCAPE4 "%25%25%25" /* */ +#define ESCAPE4_UNESC "%%%" /* */ +#define ESCAPE4_ESC "%2525%2525%2525" + { + ESCAPE4, + ESCAPE4_UNESC, + ESCAPE_EQ | UNESCAPE_EQ, + sizeof(ESCAPE4_UNESC) - 1, + sizeof(ESCAPE4_UNESC) - 1, + sizeof(ESCAPE4) - 1, + }, + { + ESCAPE4_ESC, + ESCAPE4, + ESCAPE_EQ | UNESCAPE_EQ, + sizeof(ESCAPE4) - 1, + sizeof(ESCAPE4) - 1, + sizeof(ESCAPE4_ESC) - 1, + }, +#define BAD1 "trailing percent is bad %" +#define BAD1_ESC "trailing%20percent%20is%20bad%20%25" + { + BAD1_ESC, + BAD1, + UNESCAPE_EQ |ESCAPE_EQ, + sizeof(BAD1) - 1, + sizeof(BAD1) - 1, + sizeof(BAD1_ESC) - 1, + }, + { + BAD1, + NULL, + UNESCAPE_ERR, + 0, + 0, + sizeof(BAD1) - 1, + }, +#define BAD2 "trailing percent is bad %1" +#define BAD3 "bad characters %1 " + { + BAD2, + NULL, + UNESCAPE_ERR, + 0, + 0, + sizeof(BAD2) - 1, + }, + { + BAD3, + NULL, + UNESCAPE_ERR, + 0, + 0, + sizeof(BAD3) - 1, + }, +#define BAD4 "bad characters %1 " + { + BAD4, + NULL, + UNESCAPE_ERR, + 0, + 0, + sizeof(BAD4) - 1, + }, +#define BAD5 "bad characters %1- " + { + BAD5, + NULL, + UNESCAPE_ERR, + 0, + 0, + sizeof(BAD5) - 1, + }, +#define BAD6 "bad characters %1G " + { + BAD6, + NULL, + UNESCAPE_ERR, + 0, + 0, + sizeof(BAD6) - 1, + }, +#define BAD7 "bad characters %%1 " + { + BAD7, + NULL, + UNESCAPE_ERR, + 0, + 0, + sizeof(BAD7) - 1, + }, +#define BAD8 "bad characters %sb " + { + BAD8, + NULL, + UNESCAPE_ERR, + 0, + 0, + sizeof(BAD8) - 1, + }, +#define BAD_SSCANF "sscanf would be happy with this\n" +#define BAD_SSCANF_ESC "sscanf would be happy with this% a" + { + BAD_SSCANF_ESC, + BAD_SSCANF, + ESCAPE_NE | UNESCAPE_ERR, + sizeof(BAD_SSCANF) - 1, + sizeof(BAD_SSCANF) - 1, + sizeof(BAD_SSCANF_ESC) - 1, + }, + /* now try some with zeros in. escaping can't see past zeros, and the result is truncated */ +#define ZERO "%00" +#define ZERO_UNESC "\0" + { + ESCAPE4 ZERO ESCAPE4, + ESCAPE4_UNESC ZERO_UNESC ESCAPE4_UNESC, + ESCAPE_NE | UNESCAPE_EQ, + sizeof(ESCAPE4_UNESC ZERO_UNESC ESCAPE4_UNESC) - 1, + sizeof(ESCAPE4_UNESC) - 1, + sizeof(ESCAPE4 ZERO ESCAPE4) - 1, + }, + { + ZERO ESCAPE4, + ZERO_UNESC ESCAPE4_UNESC, + ESCAPE_NE | UNESCAPE_EQ, + sizeof(ZERO_UNESC ESCAPE4_UNESC) - 1, + 0, + sizeof(ZERO ESCAPE4) - 1, + }, + { + ZERO, + ZERO_UNESC, + ESCAPE_NE | UNESCAPE_EQ, + sizeof(ZERO_UNESC) - 1, + 0, + sizeof(ZERO) - 1, + }, + { + spectrum_escaped, + spectrum, + ESCAPE_EQ | UNESCAPE_EQ, + 255, + 255, + 255 * 3, + }, +}; + +static struct rfc1738_test * dup_test(struct rfc1738_test *src) +{ + struct rfc1738_test *dest = malloc(sizeof(*dest)); + char *esc = NULL, *unesc = NULL; + if (dest == NULL) { + return NULL; + } + *dest = *src; + if (src->esc_len) { + esc = malloc(src->esc_len + 1); + if (esc == NULL) { + free(dest); + return NULL; + } + memcpy(esc, src->escaped, src->esc_len + 1); + dest->escaped = esc; + } + + if (src->unesc_len) { + unesc = malloc(src->unesc_len + 1); + if (unesc == NULL) { + free(esc); + free(dest); + return NULL; + } + memcpy(unesc, src->unescaped, src->unesc_len + 1); + dest->unescaped = unesc; + } + + return dest; +} + +static void free_test(struct rfc1738_test *t) +{ + free(discard_const_p(char, t->escaped)); + free(discard_const_p(char, t->unescaped)); + free(t); +} + + +static void test_unescape(void **state) +{ + uint i; + char *s, *e; + struct rfc1738_test *test, *orig; + for (i = 0; i < ARRAY_SIZE(examples); i++) { + orig = &examples[i]; + if ((orig->flags & (UNESCAPE_ERR | + UNESCAPE_EQ | + UNESCAPE_NE)) == 0) { + continue; + } + test = dup_test(&examples[i]); + s = discard_const_p(char, test->escaped); + e = rfc1738_unescape(s); + if (test->flags & UNESCAPE_ERR) { + assert_null(e); + free_test(test); + continue; + } + assert_non_null(e); + assert_int_equal(e - s, test->unesc_len); + + if (test->flags & UNESCAPE_EQ) { + assert_memory_equal(s, + orig->unescaped, + orig->unesc_len); + assert_int_equal(strlen(s), + orig->unesc_strlen); + } else { + assert_memory_not_equal(s, + orig->unescaped, + orig->unesc_len); + assert_int_equal(strlen(s), + orig->unesc_strlen); + } + free_test(test); + } +} + +static void test_escape(void **state) +{ + uint i; + char *s, *e; + struct rfc1738_test *test, *orig; + for (i = 0; i < ARRAY_SIZE(examples); i++) { + orig = &examples[i]; + if ((orig->flags & (ESCAPE_EQ | + ESCAPE_EQ_CASECMP | + ESCAPE_NE)) == 0) { + continue; + } + test = dup_test(&examples[i]); + s = discard_const_p(char, test->unescaped); + e = rfc1738_escape_part(NULL, s); + if (test->flags & ESCAPE_EQ) { + assert_memory_equal(e, test->escaped, + test->esc_len + 1); + } else if (test->flags & ESCAPE_EQ_CASECMP) { + int cmp = strcasecmp(e, test->escaped); + assert_int_equal(cmp, 0); + assert_string_not_equal(e, test->escaped); + } else { + assert_string_not_equal(e, test->escaped); + } + free_test(test); + } +} + + +static void gen_spectrum(void) +{ + int i, j = 0; + const char *lut = "0123456789ABCDEF"; + for (i = 1; i < 256; i++) { + spectrum[i - 1] = i; + if (isalnum(i) || + i == '-' || + i == '.' || + i == '_' || + i == '-' || + i == '~') { + spectrum_escaped[j] = i; + j++; + } else { + spectrum_escaped[j] = '%'; + spectrum_escaped[j + 1] = lut[i >> 4]; + spectrum_escaped[j + 2] = lut[i & 15]; + j += 3; + } + } + spectrum[i - 1] = '\0'; + spectrum_escaped[j] = '\0'; +} + +int main(int argc, const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_escape), + cmocka_unit_test(test_unescape), + }; + + gen_spectrum(); + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/lib/util/tests/str.c b/lib/util/tests/str.c new file mode 100644 index 0000000..41a2836 --- /dev/null +++ b/lib/util/tests/str.c @@ -0,0 +1,180 @@ +/* + Unix SMB/CIFS implementation. + + util_str testing + + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "torture/local/proto.h" + +static bool test_string_sub_simple(struct torture_context *tctx) +{ + char tmp[100]; + strlcpy(tmp, "foobar", sizeof(tmp)); + string_sub(tmp, "foo", "bar", sizeof(tmp)); + torture_assert_str_equal(tctx, tmp, "barbar", "invalid sub"); + return true; +} + +static bool test_string_sub_multiple(struct torture_context *tctx) +{ + char tmp[100]; + strlcpy(tmp, "fooblafoo", sizeof(tmp)); + string_sub(tmp, "foo", "bar", sizeof(tmp)); + torture_assert_str_equal(tctx, tmp, "barblabar", "invalid sub"); + return true; +} + +static bool test_string_sub_longer(struct torture_context *tctx) +{ + char tmp[100]; + strlcpy(tmp, "foobla", sizeof(tmp)); + string_sub(tmp, "foo", "blie", sizeof(tmp)); + torture_assert_str_equal(tctx, tmp, "bliebla", "invalid sub"); + return true; +} + +static bool test_string_sub_shorter(struct torture_context *tctx) +{ + char tmp[100]; + strlcpy(tmp, "foobla", sizeof(tmp)); + string_sub(tmp, "foo", "bl", sizeof(tmp)); + torture_assert_str_equal(tctx, tmp, "blbla", "invalid sub"); + return true; +} + +static bool test_string_sub_special_char(struct torture_context *tctx) +{ + char tmp[100]; + strlcpy(tmp, "foobla", sizeof(tmp)); + string_sub(tmp, "foo", "%b;l", sizeof(tmp)); + torture_assert_str_equal(tctx, tmp, "_b_lbla", "invalid sub"); + return true; +} + +static bool test_talloc_string_sub_simple(struct torture_context *tctx) +{ + char *t; + + t = talloc_string_sub(tctx, "foobla", "foo", "bl"); + + torture_assert_str_equal(tctx, t, "blbla", "invalid sub"); + + return true; +} + +static bool test_talloc_string_sub_multiple(struct torture_context *tctx) +{ + char *t; + + t = talloc_string_sub(tctx, "fooblafoo", "foo", "aapnootmies"); + + torture_assert_str_equal(tctx, t, "aapnootmiesblaaapnootmies", + "invalid sub"); + + return true; +} + +/* + * with these next three tests, the failure is that the pattern looks like + * "+++" because the \x.. bytes encode a zero byte in UTF-8. If we are not + * careful with these strings we will see crashes instead of failures. + */ + +static bool test_talloc_string_sub_tricky_utf8_4(struct torture_context *tctx) +{ + const char string[] = "++++--\xD8\xBB"; + const char pattern[] = "+++\xF0\x80\x80\x80++"; + const char replace[] = "..."; + + char *t = talloc_string_sub(tctx, string, pattern, replace); + torture_assert_str_equal(tctx, t, string, + "should reject 4 byte NUL char"); + talloc_free(t); + return true; +} + +static bool test_talloc_string_sub_tricky_utf8_3(struct torture_context *tctx) +{ + const char string[] = "++++--\xD8\xBB"; + const char pattern[] = "+++\xE0\x80\x80++"; + const char replace[] = "..."; + + char *t = talloc_string_sub(tctx, string, pattern, replace); + torture_assert_str_equal(tctx, t, string, + "should reject 3 byte NUL char"); + talloc_free(t); + return true; +} + +static bool test_talloc_string_sub_tricky_utf8_2(struct torture_context *tctx) +{ + const char string[] = "++++--\xD8\xBB"; + const char pattern[] = "+++\xC0\x80++"; + const char replace[] = "..."; + + char *t = talloc_string_sub(tctx, string, pattern, replace); + torture_assert_str_equal(tctx, t, string, + "should reject 2 byte NUL char"); + talloc_free(t); + return true; +} + + + + +struct torture_suite *torture_local_util_str(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "str"); + + torture_suite_add_simple_test(suite, "string_sub_simple", + test_string_sub_simple); + + torture_suite_add_simple_test(suite, "string_sub_multiple", + test_string_sub_multiple); + + torture_suite_add_simple_test(suite, "string_sub_shorter", + test_string_sub_shorter); + + torture_suite_add_simple_test(suite, "string_sub_longer", + test_string_sub_longer); + + torture_suite_add_simple_test(suite, "string_sub_special_chars", + test_string_sub_special_char); + + torture_suite_add_simple_test(suite, "talloc_string_sub_simple", + test_talloc_string_sub_simple); + + torture_suite_add_simple_test(suite, "string_sub_talloc_multiple", + test_talloc_string_sub_multiple); + + torture_suite_add_simple_test(suite, + "test_talloc_string_sub_tricky_utf8_4", + test_talloc_string_sub_tricky_utf8_4); + + torture_suite_add_simple_test(suite, + "test_talloc_string_sub_tricky_utf8_3", + test_talloc_string_sub_tricky_utf8_3); + + torture_suite_add_simple_test(suite, + "test_talloc_string_sub_tricky_utf8_2", + test_talloc_string_sub_tricky_utf8_2); + + return suite; +} diff --git a/lib/util/tests/strlist.c b/lib/util/tests/strlist.c new file mode 100644 index 0000000..a9306b8 --- /dev/null +++ b/lib/util/tests/strlist.c @@ -0,0 +1,558 @@ +/* + Unix SMB/CIFS implementation. + + util_strlist testing + + Copyright (C) Jelmer Vernooij 2005 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "torture/local/proto.h" +#include "param/param.h" + +struct test_list_element { + const char *list_as_string; + const char *separators; + const char *list[5]; +}; + +const struct test_list_element test_lists_strings[] = { + { + .list_as_string = "", + .list = { NULL } + }, + { + .list_as_string = "foo", + .list = { "foo", NULL } + }, + { + .list_as_string = "foo bar", + .list = { "foo", "bar", NULL } + }, + { + .list_as_string = "foo bar", + .list = { "foo bar", NULL }, + .separators = ";" + }, + { + .list_as_string = "\"foo bar\"", + .list = { "\"foo", "bar\"", NULL } + }, + { + .list_as_string = "\"foo bar\",comma\ttab", + .list = { "\"foo", "bar\"", "comma", "tab", NULL } + }, + { + .list_as_string = "\"foo bar\",comma;semicolon", + .list = { "\"foo bar\",comma", "semicolon", NULL }, + .separators = ";" + } +}; + +const struct test_list_element test_lists_shell_strings[] = { + { + .list_as_string = "", + .list = { NULL } + }, + { + .list_as_string = "foo", + .list = { "foo", NULL } + }, + { + .list_as_string = "foo bar", + .list = { "foo", "bar", NULL } + }, + { + .list_as_string = "foo bar", + .list = { "foo bar", NULL }, + .separators = ";" + }, + { + .list_as_string = "\"foo bar\"", + .list = { "foo bar", NULL } + }, + { + .list_as_string = "foo bar \"bla \"", + .list = { "foo", "bar", "bla ", NULL } + }, + { + .list_as_string = "foo \"\" bla", + .list = { "foo", "", "bla", NULL }, + }, + { + .list_as_string = "bla \"\"\"\" blie", + .list = { "bla", "", "", "blie", NULL }, + } +}; + +static bool test_lists_shell(struct torture_context *tctx, const void *data) +{ + const struct test_list_element *element = data; + + char **ret1, **ret2, *tmp; + bool match = true; + TALLOC_CTX *mem_ctx = tctx; + + ret1 = str_list_make_shell(mem_ctx, element->list_as_string, element->separators); + + torture_assert(tctx, ret1, "str_list_make_shell() must not return NULL"); + tmp = str_list_join_shell(mem_ctx, discard_const_p(const char *, ret1), + element->separators ? *element->separators : ' '); + ret2 = str_list_make_shell(mem_ctx, tmp, element->separators); + + if ((ret1 == NULL || ret2 == NULL) && ret2 != ret1) { + match = false; + } else { + int j; + for (j = 0; ret1[j] && ret2[j]; j++) { + if (strcmp(ret1[j], ret2[j]) != 0) { + match = false; + break; + } + } + + if (ret1[j] || ret2[j]) + match = false; + } + + torture_assert(tctx, match, talloc_asprintf(tctx, + "str_list_{make,join}_shell: Error double parsing, first run:\n%s\nSecond run: \n%s", element->list_as_string, tmp)); + torture_assert(tctx, str_list_equal((const char * const *) ret1, + element->list), + talloc_asprintf(tctx, + "str_list_make_shell(%s) failed to create correct list", + element->list_as_string)); + + return true; +} + +static bool test_list_make(struct torture_context *tctx, const void *data) +{ + const struct test_list_element *element = data; + + char **result; + result = str_list_make(tctx, element->list_as_string, element->separators); + torture_assert(tctx, result, "str_list_make() must not return NULL"); + torture_assert(tctx, str_list_equal((const char * const *) result, + element->list), + talloc_asprintf(tctx, + "str_list_make(%s) failed to create correct list", + element->list_as_string)); + return true; +} + +static bool test_list_copy(struct torture_context *tctx) +{ + const char **result; + const char *list[] = { "foo", "bar", NULL }; + const char *empty_list[] = { NULL }; + const char **null_list = NULL; + char **l; + + l = str_list_copy(tctx, list); + result = discard_const_p(const char *, l); + torture_assert_int_equal(tctx, str_list_length(result), 2, "list length"); + torture_assert_str_equal(tctx, result[0], "foo", "element 0"); + torture_assert_str_equal(tctx, result[1], "bar", "element 1"); + torture_assert_str_equal(tctx, result[2], NULL, "element 2"); + + l = str_list_copy(tctx, empty_list); + result = discard_const_p(const char *, l); + torture_assert_int_equal(tctx, str_list_length(result), 0, "list length"); + torture_assert_str_equal(tctx, result[0], NULL, "element 0"); + + l = str_list_copy(tctx, null_list); + result = discard_const_p(const char *, l); + torture_assert(tctx, result == NULL, "result NULL"); + + return true; +} + +static bool test_list_make_empty(struct torture_context *tctx) +{ + char **result; + + result = str_list_make_empty(tctx); + torture_assert(tctx, result, "str_list_make_empty() must not return NULL"); + torture_assert(tctx, result[0] == NULL, "first element in str_list_make_empty() result must be NULL"); + + result = str_list_make(tctx, NULL, NULL); + torture_assert(tctx, result, "str_list_make() must not return NULL"); + torture_assert(tctx, result[0] == NULL, "first element in str_list_make(ctx, NULL, NULL) result must be NULL"); + + result = str_list_make(tctx, "", NULL); + torture_assert(tctx, result, "str_list_make() must not return NULL"); + torture_assert(tctx, result[0] == NULL, "first element in str_list_make(ctx, "", NULL) result must be NULL"); + + return true; +} + +static bool test_list_make_single(struct torture_context *tctx) +{ + char **result; + + result = str_list_make_single(tctx, "foo"); + + torture_assert(tctx, result, "str_list_make_single() must not return NULL"); + torture_assert_str_equal(tctx, result[0], "foo", "element 0"); + torture_assert(tctx, result[1] == NULL, "second element in result must be NULL"); + + return true; +} + +static bool test_list_copy_const(struct torture_context *tctx) +{ + const char **result; + const char *list[] = { + "element_0", + "element_1", + "element_2", + "element_3", + NULL + }; + result = str_list_copy_const(tctx, list); + torture_assert(tctx, result, "str_list_copy() must not return NULL"); + torture_assert(tctx, str_list_equal(result, list), + "str_list_copy() failed"); + + return true; +} + +static bool test_list_length(struct torture_context *tctx) +{ + const char *list[] = { + "element_0", + "element_1", + "element_2", + "element_3", + NULL + }; + const char *list2[] = { + NULL + }; + torture_assert_int_equal(tctx, str_list_length(list), 4, + "str_list_length() failed"); + + torture_assert_int_equal(tctx, str_list_length(list2), 0, + "str_list_length() failed"); + + torture_assert_int_equal(tctx, str_list_length(NULL), 0, + "str_list_length() failed"); + + return true; +} + +static bool test_list_add(struct torture_context *tctx) +{ + const char **result, **result2; + const char *list[] = { + "element_0", + "element_1", + "element_2", + "element_3", + NULL + }; + char **l; + + l = str_list_make(tctx, "element_0, element_1, element_2", NULL); + result = discard_const_p(const char *, l); + torture_assert(tctx, result, "str_list_make() must not return NULL"); + result2 = str_list_add(result, "element_3"); + torture_assert(tctx, result2, "str_list_add() must not return NULL"); + torture_assert(tctx, str_list_equal(result2, list), + "str_list_add() failed"); + + return true; +} + +static bool test_list_add_const(struct torture_context *tctx) +{ + const char **result, **result2; + const char *list[] = { + "element_0", + "element_1", + "element_2", + "element_3", + NULL + }; + char **l; + + l = str_list_make(tctx, "element_0, element_1, element_2", NULL); + result = discard_const_p(const char *, l); + torture_assert(tctx, result, "str_list_make() must not return NULL"); + result2 = str_list_add_const(result, "element_3"); + torture_assert(tctx, result2, "str_list_add_const() must not return NULL"); + torture_assert(tctx, str_list_equal(result2, list), + "str_list_add() failed"); + + return true; +} + +static bool test_list_remove(struct torture_context *tctx) +{ + const char **result; + const char *list[] = { + "element_0", + "element_1", + "element_3", + NULL + }; + char **l; + + l = str_list_make(tctx, "element_0, element_1, element_2, element_3", NULL); + result = discard_const_p(const char *, l); + torture_assert(tctx, result, "str_list_make() must not return NULL"); + str_list_remove(result, "element_2"); + torture_assert(tctx, str_list_equal(result, list), + "str_list_remove() failed"); + + return true; +} + +static bool test_list_check(struct torture_context *tctx) +{ + const char *list[] = { + "element_0", + "element_1", + "element_2", + NULL + }; + torture_assert(tctx, str_list_check(list, "element_1"), + "str_list_check() failed"); + + return true; +} + +static bool test_list_check_ci(struct torture_context *tctx) +{ + const char *list[] = { + "element_0", + "element_1", + "element_2", + NULL + }; + torture_assert(tctx, str_list_check_ci(list, "ELEMENT_1"), + "str_list_check_ci() failed"); + + return true; +} + +static bool test_list_unique(struct torture_context *tctx) +{ + const char **result; + const char *list[] = { + "element_0", + "element_1", + "element_2", + NULL + }; + const char *list_dup[] = { + "element_0", + "element_1", + "element_2", + "element_0", + "element_2", + "element_1", + "element_1", + "element_2", + NULL + }; + char **l; + + l = str_list_copy(tctx, list_dup); + result = discard_const_p(const char *, l); + /* We must copy the list, as str_list_unique does a talloc_realloc() on it's parameter */ + result = str_list_unique(result); + torture_assert(tctx, result, "str_list_unique() must not return NULL"); + + torture_assert(tctx, str_list_equal(list, result), + "str_list_unique() failed"); + + return true; +} + +static bool test_list_unique_2(struct torture_context *tctx) +{ + int i; + int count, num_dups; + const char **result; + char **l1 = str_list_make_empty(tctx); + char **l2 = str_list_make_empty(tctx); + const char **list = discard_const_p(const char *, l1); + const char **list_dup = discard_const_p(const char *, l2); + char **l; + + count = lpcfg_parm_int(tctx->lp_ctx, NULL, "list_unique", "count", 9); + num_dups = lpcfg_parm_int(tctx->lp_ctx, NULL, "list_unique", "dups", 7); + torture_comment(tctx, "test_list_unique_2() with %d elements and %d dups\n", count, num_dups); + + for (i = 0; i < count; i++) { + list = str_list_add_const(list, (const char *)talloc_asprintf(tctx, "element_%03d", i)); + } + + for (i = 0; i < num_dups; i++) { + list_dup = str_list_append(list_dup, list); + } + + l = str_list_copy(tctx, list_dup); + result = discard_const_p(const char *, l); + /* We must copy the list, as str_list_unique does a talloc_realloc() on it's parameter */ + result = str_list_unique(result); + torture_assert(tctx, result, "str_list_unique() must not return NULL"); + + torture_assert(tctx, str_list_equal(list, result), + "str_list_unique() failed"); + + return true; +} + +static bool test_list_append(struct torture_context *tctx) +{ + const char **result; + const char *list[] = { + "element_0", + "element_1", + "element_2", + NULL + }; + const char *list2[] = { + "element_3", + "element_4", + "element_5", + NULL + }; + const char *list_combined[] = { + "element_0", + "element_1", + "element_2", + "element_3", + "element_4", + "element_5", + NULL + }; + char **l; + l = str_list_copy(tctx, list); + result = discard_const_p(const char *, l); + torture_assert(tctx, result, "str_list_copy() must not return NULL"); + result = str_list_append(result, list2); + torture_assert(tctx, result, "str_list_append() must not return NULL"); + torture_assert(tctx, str_list_equal(list_combined, result), + "str_list_unique() failed"); + + return true; +} + +static bool test_list_append_const(struct torture_context *tctx) +{ + const char **result; + const char *list[] = { + "element_0", + "element_1", + "element_2", + NULL + }; + const char *list2[] = { + "element_3", + "element_4", + "element_5", + NULL + }; + const char *list_combined[] = { + "element_0", + "element_1", + "element_2", + "element_3", + "element_4", + "element_5", + NULL + }; + char **l; + l = str_list_copy(tctx, list); + result = discard_const_p(const char *, l); + torture_assert(tctx, result, "str_list_copy() must not return NULL"); + result = str_list_append_const(result, list2); + torture_assert(tctx, result, "str_list_append_const() must not return NULL"); + torture_assert(tctx, str_list_equal(list_combined, result), + "str_list_unique() failed"); + + return true; +} + +static bool test_list_add_printf_NULL(struct torture_context *tctx) +{ + char **list = NULL; + str_list_add_printf(&list, "x=%d", 1); + torture_assert(tctx, list==NULL, "str_list_add_printf must keep NULL"); + return true; +} + +static bool test_list_add_printf(struct torture_context *tctx) +{ + const char *list2[] = { "foo", "bar=baz", NULL }; + char **list = str_list_make_empty(tctx); + str_list_add_printf(&list, "foo"); + str_list_add_printf(&list, "bar=%s", "baz"); + torture_assert( + tctx, + str_list_equal((const char * const *)list, list2), + "str_list_add_printf failed"); + TALLOC_FREE(list); + return true; +} + +struct torture_suite *torture_local_util_strlist(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "strlist"); + size_t i; + + for (i = 0; i < ARRAY_SIZE(test_lists_shell_strings); i++) { + char *name; + name = talloc_asprintf(suite, "lists_shell(%s)", + test_lists_shell_strings[i].list_as_string); + torture_suite_add_simple_tcase_const(suite, name, + test_lists_shell, &test_lists_shell_strings[i]); + } + + for (i = 0; i < ARRAY_SIZE(test_lists_strings); i++) { + char *name; + name = talloc_asprintf(suite, "list_make(%s)", + test_lists_strings[i].list_as_string); + torture_suite_add_simple_tcase_const(suite, name, + test_list_make, &test_lists_strings[i]); + } + + torture_suite_add_simple_test(suite, "list_copy", test_list_copy); + torture_suite_add_simple_test(suite, "make_empty", test_list_make_empty); + torture_suite_add_simple_test(suite, "make_single", test_list_make_single); + torture_suite_add_simple_test(suite, "list_copy_const", test_list_copy_const); + torture_suite_add_simple_test(suite, "list_length", test_list_length); + torture_suite_add_simple_test(suite, "list_add", test_list_add); + torture_suite_add_simple_test(suite, "list_add_const", test_list_add_const); + torture_suite_add_simple_test(suite, "list_remove", test_list_remove); + torture_suite_add_simple_test(suite, "list_check", test_list_check); + torture_suite_add_simple_test(suite, "list_check_ci", test_list_check_ci); + torture_suite_add_simple_test(suite, "list_unique", test_list_unique); + torture_suite_add_simple_test(suite, "list_unique_2", test_list_unique_2); + torture_suite_add_simple_test(suite, "list_append", test_list_append); + torture_suite_add_simple_test(suite, "list_append_const", test_list_append_const); + torture_suite_add_simple_test( + suite, "list_add_printf_NULL", test_list_add_printf_NULL); + torture_suite_add_simple_test( + suite, "list_add_printf", test_list_add_printf); + return suite; +} diff --git a/lib/util/tests/strv.c b/lib/util/tests/strv.c new file mode 100644 index 0000000..c79ed5c --- /dev/null +++ b/lib/util/tests/strv.c @@ -0,0 +1,201 @@ +/* + * Tests for strv + * + * Copyright Martin Schwenke <martin@meltin.net> 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include <talloc.h> + +#include "replace.h" + +#include "libcli/util/ntstatus.h" +#include "torture/torture.h" +#include "lib/util/data_blob.h" +#include "torture/local/proto.h" + +#include "lib/util/strv.h" + +static bool test_strv_empty(struct torture_context *tctx) +{ + /* NULL strv contains 0 entries */ + torture_assert_int_equal(tctx, + strv_count(NULL), + 0, + "strv_count() on NULL failed"); + + /* NULL strv has no next entry */ + torture_assert(tctx, + strv_next(NULL, NULL) == NULL, + "strv_next() on NULL failed"); + + return true; +} + +static bool test_strv_single(struct torture_context *tctx) +{ + const char *data = "foo"; + char *strv = NULL; + char *t; + int ret; + + /* Add an item */ + ret = strv_add(tctx, &strv, data); + torture_assert(tctx, ret == 0, "strv_add() failed"); + + /* Is there 1 item? */ + torture_assert_int_equal(tctx, + strv_count(strv), 1, + "strv_count() failed"); + + /* Is the expected item the first one? */ + t = strv_next(strv, NULL); + torture_assert(tctx, + strcmp(t, data) == 0, + "strv_next() failed"); + + /* Can the expected item be found? */ + t = strv_find(strv, data); + torture_assert(tctx, + strcmp(t, data) == 0, + "strv_next() failed"); + + /* Delete it */ + strv_delete(&strv, t); + + /* Should have no items */ + torture_assert_int_equal(tctx, + strv_count(strv), 0, + "strv_count() failed"); + return true; +} + +static bool test_strv_multi(struct torture_context *tctx) +{ + const char *data[] = { "foo", "bar", "", "samba", "x"}; + char *strv = NULL; + char *t; + int i, ret; + const int num = ARRAY_SIZE(data); + + /* Add items */ + for (i = 0; i < num; i++) { + ret = strv_add(tctx, &strv, data[i]); + torture_assert(tctx, ret == 0, "strv_add() failed"); + } + + torture_assert_int_equal(tctx, + strv_count(strv), num, + "strv_count() failed"); + + /* Check that strv_next() finds the expected values */ + t = NULL; + for (i = 0; i < num; i++) { + t = strv_next(strv, t); + torture_assert(tctx, + strcmp(t, data[i]) == 0, + "strv_next() failed"); + } + + + /* Check that strv_next() finds the expected values */ + t = NULL; + for (i = 0; i < num; i++) { + t = strv_next(strv, t); + torture_assert(tctx, + strcmp(t, data[i]) == 0, + "strv_next() failed"); + } + + /* Find each item, delete it, check count */ + for (i = 0; i < num; i++) { + t = strv_find(strv, data[i]); + torture_assert(tctx, + strcmp(t, data[i]) == 0, + "strv_next() failed"); + strv_delete(&strv, t); + torture_assert_int_equal(tctx, + strv_count(strv), num - i - 1, + "strv_delete() failed"); + } + + /* Add items */ + for (i = 0; i < num; i++) { + ret = strv_add(tctx, &strv, data[i]); + torture_assert(tctx, ret == 0, "strv_add() failed"); + } + + torture_assert_int_equal(tctx, + strv_count(strv), num, + "strv_count() failed"); + + /* Find items in reverse, delete, check count */ + for (i = num - 1; i >= 0; i--) { + t = strv_find(strv, data[i]); + torture_assert(tctx, + strcmp(t, data[i]) == 0, + "strv_next() failed"); + strv_delete(&strv, t); + torture_assert_int_equal(tctx, + strv_count(strv), i, + "strv_delete() failed"); + } + + return true; +} + +/* Similar to above but only add/check first 2 chars of each string */ +static bool test_strv_addn(struct torture_context *tctx) +{ + const char *data[] = { "foo", "bar", "samba" }; + char *strv = NULL; + char *t; + int i, ret; + const int num = ARRAY_SIZE(data); + + /* Add first 2 chars of each item */ + for (i = 0; i < num; i++) { + ret = strv_addn(tctx, &strv, data[i], 2); + torture_assert(tctx, ret == 0, "strv_add() failed"); + } + + torture_assert_int_equal(tctx, + strv_count(strv), num, + "strv_count() failed"); + + /* Check that strv_next() finds the expected values */ + t = NULL; + for (i = 0; i < num; i++) { + t = strv_next(strv, t); + torture_assert(tctx, + strncmp(t, data[i], 2) == 0, + "strv_next() failed"); + } + + return true; +} + +struct torture_suite *torture_local_util_strv(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "strv"); + + torture_suite_add_simple_test(suite, "strv_empty", test_strv_empty); + torture_suite_add_simple_test(suite, "strv_single", test_strv_single); + torture_suite_add_simple_test(suite, "strv_multi", test_strv_multi); + torture_suite_add_simple_test(suite, "strv_addn", test_strv_addn); + + return suite; +} diff --git a/lib/util/tests/strv_util.c b/lib/util/tests/strv_util.c new file mode 100644 index 0000000..b1496c7 --- /dev/null +++ b/lib/util/tests/strv_util.c @@ -0,0 +1,150 @@ +/* + * Tests for strv_util + * + * Copyright Martin Schwenke <martin@meltin.net> 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <talloc.h> + +#include "replace.h" + +#include "libcli/util/ntstatus.h" +#include "torture/torture.h" +#include "lib/util/data_blob.h" +#include "torture/local/proto.h" + +#include "lib/util/strv.h" +#include "lib/util/strv_util.h" + +static bool test_strv_split_none(struct torture_context *tctx) +{ + char *strv = NULL; + int ret; + + /* NULL has 0 entries */ + ret = strv_split(tctx, &strv, NULL, " "); + torture_assert(tctx, ret == 0, "strv_split() on NULL failed"); + torture_assert_int_equal(tctx, + strv_count(strv), + 0, + "strv_split() on NULL failed"); + TALLOC_FREE(strv); + + /* Empty string has 0 entries */ + ret = strv_split(tctx, &strv, "", " "); + torture_assert(tctx, ret == 0, "strv_split() on NULL failed"); + torture_assert_int_equal(tctx, + strv_count(strv), + 0, + "strv_split() on \"\" failed"); + TALLOC_FREE(strv); + + /* String containing only separators has 0 entries */ + ret = strv_split(tctx, &strv, "abcabcabc", "cba "); + torture_assert(tctx, ret == 0, "strv_split() on NULL failed"); + torture_assert_int_equal(tctx, + strv_count(strv), + 0, + "strv_split() on seps-only failed"); + TALLOC_FREE(strv); + + return true; +} + +struct test_str_split_data { + const char *in; + const char *sep; + const char *out[10]; /* Hardcoded maximum! */ +}; + +static bool test_strv_split_some(struct torture_context *tctx) +{ + const struct test_str_split_data data[] = { + { + /* Single string */ + .in = "foo", + .sep = " \t", + .out = { "foo" } + }, + { + /* Single string, single leading separator */ + .in = " foo", + .sep = " \t", + .out = { "foo" } + }, + { + /* Single string, single trailing separator */ + .in = " foo", + .sep = " \t", + .out = { "foo" } + }, + { + /* Single string, lots of separators */ + .in = " \t foo\t ", + .sep = " \t", + .out = { "foo" } + }, + { + /* Multiple strings, many separators */ + .in = " \t foo bar\t\tx\t samba\t ", + .sep = " \t", + .out = { "foo", "bar", "x", "samba" } + }, + }; + const char *t; + char *strv = NULL; + size_t j; + + for (j = 0; j < ARRAY_SIZE(data); j++) { + size_t i, num; + int ret; + const struct test_str_split_data *d = &data[j]; + + num = 0; + while (num < ARRAY_SIZE(d->out) && d->out[num] != NULL) { + num++; + } + ret = strv_split(tctx, &strv, d->in, d->sep); + torture_assert(tctx, ret == 0, "strv_split() on NULL failed"); + torture_assert_int_equal(tctx, + strv_count(strv), + num, + "strv_split() failed"); + t = NULL; + for (i = 0; i < num; i++) { + t = strv_next(strv, t); + torture_assert(tctx, + strcmp(t, d->out[i]) == 0, + "strv_split() failed"); + } + TALLOC_FREE(strv); + } + return true; +} + +struct torture_suite *torture_local_util_strv_util(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = + torture_suite_create(mem_ctx, "strv_util"); + + torture_suite_add_simple_test(suite, + "strv_split_none", + test_strv_split_none); + torture_suite_add_simple_test(suite, + "strv_split_some", + test_strv_split_some); + return suite; +} diff --git a/lib/util/tests/test_bytearray.c b/lib/util/tests/test_bytearray.c new file mode 100644 index 0000000..fcf63d8 --- /dev/null +++ b/lib/util/tests/test_bytearray.c @@ -0,0 +1,435 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2018-2019 Andreas Schneider <asn@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <setjmp.h> +#include <cmocka.h> + +#include "lib/replace/replace.h" +#include "lib/util/bytearray.h" + +static void torture_pull_le_u8(void **state) +{ + uint8_t data[2] = {0}; + uint8_t result; + + (void)state; + + result = PULL_LE_U8(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x2a; + result = PULL_LE_U8(data, 0); + assert_int_equal(result, 42); + + + data[0] = 0xf; + result = PULL_LE_U8(data, 0); + assert_int_equal(result, 0xf); + + data[0] = 0xff; + result = PULL_LE_U8(data, 0); + assert_int_equal(result, 0xff); + + data[1] = 0x2a; + result = PULL_LE_U8(data, 1); + assert_int_equal(result, 42); +} + +static void torture_pull_le_u16(void **state) +{ + uint8_t data[2] = {0, 0}; + uint16_t result; + + (void)state; + + result = PULL_LE_U16(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x2a; + data[1] = 0x00; + result = PULL_LE_U16(data, 0); + assert_int_equal(result, 42); + + data[0] = 0xff; + data[1] = 0x00; + result = PULL_LE_U16(data, 0); + assert_int_equal(result, 0x00ff); + + data[0] = 0x00; + data[1] = 0xff; + result = PULL_LE_U16(data, 0); + assert_int_equal(result, 0xff00); + + data[0] = 0xff; + data[1] = 0xff; + result = PULL_LE_U16(data, 0); + assert_int_equal(result, 0xffff); +} + +static void torture_pull_le_u32(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint32_t result; + + (void)state; + + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x2a; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0x00; + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 42); + + data[0] = 0xff; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0x00; + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 0x00ff); + + data[0] = 0x00; + data[1] = 0xff; + data[2] = 0x00; + data[3] = 0x00; + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 0xff00); + + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0xff; + data[3] = 0x00; + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 0xff0000); + + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0xff; + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 0xff000000); + + data[0] = 0xff; + data[1] = 0xff; + data[2] = 0xff; + data[3] = 0xff; + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 0xffffffff); +} + +static void torture_push_le_u8(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint8_t data2[4] = {42, 42, 42, 42}; + + (void)state; + + PUSH_LE_U8(data, 0, 42); + PUSH_LE_U8(data, 1, 42); + PUSH_LE_U8(data, 2, 42); + PUSH_LE_U8(data, 3, 42); + assert_memory_equal(data, data2, sizeof(data)); +} + +static void torture_push_le_u16(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint8_t data2[4] = {0xa6, 0x7f, 0x2a, 0x00}; + uint16_t result; + + (void)state; + + PUSH_LE_U16(data, 0, 32678); + PUSH_LE_U16(data, 2, 42); + assert_memory_equal(data, data2, sizeof(data)); + + result = PULL_LE_U16(data, 2); + assert_int_equal(result, 42); + + result = PULL_LE_U16(data, 0); + assert_int_equal(result, 32678); +} + +static void torture_push_le_u32(void **state) +{ + uint8_t data[8] = {0}; + uint8_t data2[8] = {0xa6, 0x7f, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00}; + uint32_t result; + + (void)state; + + PUSH_LE_U32(data, 0, 32678); + PUSH_LE_U32(data, 4, 42); + assert_memory_equal(data, data2, sizeof(data)); + + result = PULL_LE_U32(data, 4); + assert_int_equal(result, 42); + + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 32678); + + PUSH_LE_U32(data, 0, 0xfffefffe); + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 0xfffefffe); +} + +static void torture_push_le_u64(void **state) +{ + uint8_t data[16] = {0}; + uint64_t result; + + (void)state; + + PUSH_LE_U64(data, 0, 32678); + + result = PULL_LE_U64(data, 0); + assert_int_equal(result, 32678); + + PUSH_LE_U64(data, 0, 0xfffefffefffefffeUL); + + result = PULL_LE_U64(data, 0); + assert_int_equal(result, 0xfffefffefffefffeUL); +} + +/****************** BIG ENDIAN ********************/ + +static void torture_pull_be_u8(void **state) +{ + uint8_t data[2] = {0}; + uint8_t result; + + (void)state; + + result = PULL_BE_U8(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x2a; + result = PULL_BE_U8(data, 0); + assert_int_equal(result, 42); + + + data[0] = 0xf; + result = PULL_BE_U8(data, 0); + assert_int_equal(result, 0xf); + + data[0] = 0xff; + result = PULL_BE_U8(data, 0); + assert_int_equal(result, 0xff); + + data[1] = 0x2a; + result = PULL_BE_U8(data, 1); + assert_int_equal(result, 42); +} + +static void torture_pull_be_u16(void **state) +{ + uint8_t data[2] = {0, 0}; + uint16_t result; + + (void)state; + + result = PULL_BE_U16(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x00; + data[1] = 0x2a; + result = PULL_BE_U16(data, 0); + assert_int_equal(result, 42); + + data[0] = 0x00; + data[1] = 0xff; + result = PULL_BE_U16(data, 0); + assert_int_equal(result, 0x00ff); + + data[0] = 0xff; + data[1] = 0x00; + result = PULL_BE_U16(data, 0); + assert_int_equal(result, 0xff00); + + data[0] = 0xff; + data[1] = 0xff; + result = PULL_BE_U16(data, 0); + assert_int_equal(result, 0xffff); +} + +static void torture_pull_be_u32(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint32_t result; + + (void)state; + + result = PULL_BE_U32(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0x2a; + result = PULL_BE_U32(data, 0); + assert_int_equal(result, 42); + + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0xff; + result = PULL_BE_U32(data, 0); + assert_int_equal(result, 0x00ff); + + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0xff; + data[3] = 0x00; + result = PULL_BE_U32(data, 0); + assert_int_equal(result, 0xff00); + + data[0] = 0x00; + data[1] = 0xff; + data[2] = 0x00; + data[3] = 0x00; + result = PULL_BE_U32(data, 0); + assert_int_equal(result, 0xff0000); + + data[0] = 0xff; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0x00; + result = PULL_BE_U32(data, 0); + assert_int_equal(result, 0xff000000); + + data[0] = 0xff; + data[1] = 0xff; + data[2] = 0xff; + data[3] = 0xff; + result = PULL_BE_U32(data, 0); + assert_int_equal(result, 0xffffffff); +} + +static void torture_push_be_u8(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint8_t data2[4] = {42, 42, 42, 42}; + + (void)state; + + PUSH_BE_U8(data, 0, 42); + PUSH_BE_U8(data, 1, 42); + PUSH_BE_U8(data, 2, 42); + PUSH_BE_U8(data, 3, 42); + assert_memory_equal(data, data2, sizeof(data)); +} + +static void torture_push_be_u16(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint8_t data2[4] = {0x7f, 0xa6, 0x00, 0x2a}; + uint16_t result; + + (void)state; + + PUSH_BE_U16(data, 0, 32678); + PUSH_BE_U16(data, 2, 42); + assert_memory_equal(data, data2, sizeof(data)); + + result = PULL_BE_U16(data, 2); + assert_int_equal(result, 42); + + result = PULL_BE_U16(data, 0); + assert_int_equal(result, 32678); +} + +static void torture_push_be_u32(void **state) +{ + uint8_t data[8] = {0}; + uint8_t data2[8] = {0x00, 0x00, 0x7f, 0xa6, 0x00, 0x00, 0x00, 0x2a}; + uint32_t result; + + (void)state; + + PUSH_BE_U32(data, 0, 32678); + PUSH_BE_U32(data, 4, 42); + assert_memory_equal(data, data2, sizeof(data)); + + result = PULL_BE_U32(data, 4); + assert_int_equal(result, 42); + + result = PULL_BE_U32(data, 0); + assert_int_equal(result, 32678); + + PUSH_BE_U32(data, 0, 0xfffefffe); + result = PULL_BE_U32(data, 0); + assert_int_equal(result, 0xfffefffe); +} + +static void torture_push_be_u64(void **state) +{ + uint8_t data[16] = {0}; + uint64_t result; + + (void)state; + + PUSH_BE_U64(data, 0, 32678); + + result = PULL_BE_U64(data, 0); + assert_int_equal(result, 32678); + + PUSH_LE_U64(data, 8, 0xfffefffe); + + result = PULL_LE_U64(data, 8); + assert_int_equal(result, 0xfffefffe); +} + +int main(int argc, char *argv[]) +{ + int rc; + const struct CMUnitTest tests[] = { + cmocka_unit_test(torture_pull_le_u8), + cmocka_unit_test(torture_pull_le_u16), + cmocka_unit_test(torture_pull_le_u32), + + cmocka_unit_test(torture_push_le_u8), + cmocka_unit_test(torture_push_le_u16), + cmocka_unit_test(torture_push_le_u32), + cmocka_unit_test(torture_push_le_u64), + + /* BIG ENDIAN */ + cmocka_unit_test(torture_pull_be_u8), + cmocka_unit_test(torture_pull_be_u16), + cmocka_unit_test(torture_pull_be_u32), + + cmocka_unit_test(torture_push_be_u8), + cmocka_unit_test(torture_push_be_u16), + cmocka_unit_test(torture_push_be_u32), + cmocka_unit_test(torture_push_be_u64), + }; + + if (argc == 2) { + cmocka_set_test_filter(argv[1]); + } + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + rc = cmocka_run_group_tests(tests, NULL, NULL); + + return rc; +} diff --git a/lib/util/tests/test_byteorder.c b/lib/util/tests/test_byteorder.c new file mode 100644 index 0000000..9faa038 --- /dev/null +++ b/lib/util/tests/test_byteorder.c @@ -0,0 +1,435 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2018-2019 Andreas Schneider <asn@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <setjmp.h> +#include <cmocka.h> + +#include "lib/replace/replace.h" +#include "lib/util/byteorder.h" + +static void torture_pull_le_u8(void **state) +{ + uint8_t data[2] = {0}; + uint8_t result; + + (void)state; + + result = CVAL(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x2a; + result = CVAL(data, 0); + assert_int_equal(result, 42); + + + data[0] = 0xf; + result = CVAL(data, 0); + assert_int_equal(result, 0xf); + + data[0] = 0xff; + result = CVAL(data, 0); + assert_int_equal(result, 0xff); + + data[1] = 0x2a; + result = CVAL(data, 1); + assert_int_equal(result, 42); +} + +static void torture_pull_le_u16(void **state) +{ + uint8_t data[2] = {0, 0}; + uint16_t result; + + (void)state; + + result = SVAL(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x2a; + data[1] = 0x00; + result = SVAL(data, 0); + assert_int_equal(result, 42); + + data[0] = 0xff; + data[1] = 0x00; + result = SVAL(data, 0); + assert_int_equal(result, 0x00ff); + + data[0] = 0x00; + data[1] = 0xff; + result = SVAL(data, 0); + assert_int_equal(result, 0xff00); + + data[0] = 0xff; + data[1] = 0xff; + result = SVAL(data, 0); + assert_int_equal(result, 0xffff); +} + +static void torture_pull_le_u32(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint32_t result; + + (void)state; + + result = IVAL(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x2a; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0x00; + result = IVAL(data, 0); + assert_int_equal(result, 42); + + data[0] = 0xff; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0x00; + result = IVAL(data, 0); + assert_int_equal(result, 0x00ff); + + data[0] = 0x00; + data[1] = 0xff; + data[2] = 0x00; + data[3] = 0x00; + result = IVAL(data, 0); + assert_int_equal(result, 0xff00); + + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0xff; + data[3] = 0x00; + result = IVAL(data, 0); + assert_int_equal(result, 0xff0000); + + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0xff; + result = IVAL(data, 0); + assert_int_equal(result, 0xff000000); + + data[0] = 0xff; + data[1] = 0xff; + data[2] = 0xff; + data[3] = 0xff; + result = IVAL(data, 0); + assert_int_equal(result, 0xffffffff); +} + +static void torture_push_le_u8(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint8_t data2[4] = {42, 42, 42, 42}; + + (void)state; + + SCVAL(data, 0, 42); + SCVAL(data, 1, 42); + SCVAL(data, 2, 42); + SCVAL(data, 3, 42); + assert_memory_equal(data, data2, sizeof(data)); +} + +static void torture_push_le_u16(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint8_t data2[4] = {0xa6, 0x7f, 0x2a, 0x00}; + uint16_t result; + + (void)state; + + SSVALX(data, 0, 32678); + SSVALX(data, 2, 42); + assert_memory_equal(data, data2, sizeof(data)); + + result = SVAL(data, 2); + assert_int_equal(result, 42); + + result = SVAL(data, 0); + assert_int_equal(result, 32678); +} + +static void torture_push_le_u32(void **state) +{ + uint8_t data[8] = {0}; + uint8_t data2[8] = {0xa6, 0x7f, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00}; + uint32_t result; + + (void)state; + + SIVALX(data, 0, 32678); + SIVALX(data, 4, 42); + assert_memory_equal(data, data2, sizeof(data)); + + result = IVAL(data, 4); + assert_int_equal(result, 42); + + result = IVAL(data, 0); + assert_int_equal(result, 32678); + + SIVALX(data, 0, 0xfffefffe); + result = IVAL(data, 0); + assert_int_equal(result, 0xfffefffe); +} + +static void torture_push_le_u64(void **state) +{ + uint8_t data[16] = {0}; + uint64_t result; + + (void)state; + + SBVAL(data, 0, 32678); + + result = BVAL(data, 0); + assert_int_equal(result, 32678); + + SBVAL(data, 0, 0xfffefffefffefffeUL); + + result = BVAL(data, 0); + assert_int_equal(result, 0xfffefffefffefffeUL); +} + +/****************** BIG ENDIAN ********************/ + +static void torture_pull_be_u8(void **state) +{ + uint8_t data[2] = {0}; + uint8_t result; + + (void)state; + + result = CVAL(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x2a; + result = CVAL(data, 0); + assert_int_equal(result, 42); + + + data[0] = 0xf; + result = CVAL(data, 0); + assert_int_equal(result, 0xf); + + data[0] = 0xff; + result = CVAL(data, 0); + assert_int_equal(result, 0xff); + + data[1] = 0x2a; + result = CVAL(data, 1); + assert_int_equal(result, 42); +} + +static void torture_pull_be_u16(void **state) +{ + uint8_t data[2] = {0, 0}; + uint16_t result; + + (void)state; + + result = RSVAL(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x00; + data[1] = 0x2a; + result = RSVAL(data, 0); + assert_int_equal(result, 42); + + data[0] = 0x00; + data[1] = 0xff; + result = RSVAL(data, 0); + assert_int_equal(result, 0x00ff); + + data[0] = 0xff; + data[1] = 0x00; + result = RSVAL(data, 0); + assert_int_equal(result, 0xff00); + + data[0] = 0xff; + data[1] = 0xff; + result = RSVAL(data, 0); + assert_int_equal(result, 0xffff); +} + +static void torture_pull_be_u32(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint32_t result; + + (void)state; + + result = RIVAL(data, 0); + assert_int_equal(result, 0); + + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0x2a; + result = RIVAL(data, 0); + assert_int_equal(result, 42); + + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0xff; + result = RIVAL(data, 0); + assert_int_equal(result, 0x00ff); + + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0xff; + data[3] = 0x00; + result = RIVAL(data, 0); + assert_int_equal(result, 0xff00); + + data[0] = 0x00; + data[1] = 0xff; + data[2] = 0x00; + data[3] = 0x00; + result = RIVAL(data, 0); + assert_int_equal(result, 0xff0000); + + data[0] = 0xff; + data[1] = 0x00; + data[2] = 0x00; + data[3] = 0x00; + result = RIVAL(data, 0); + assert_int_equal(result, 0xff000000); + + data[0] = 0xff; + data[1] = 0xff; + data[2] = 0xff; + data[3] = 0xff; + result = RIVAL(data, 0); + assert_int_equal(result, 0xffffffff); +} + +static void torture_push_be_u8(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint8_t data2[4] = {42, 42, 42, 42}; + + (void)state; + + SCVAL(data, 0, 42); + SCVAL(data, 1, 42); + SCVAL(data, 2, 42); + SCVAL(data, 3, 42); + assert_memory_equal(data, data2, sizeof(data)); +} + +static void torture_push_be_u16(void **state) +{ + uint8_t data[4] = {0, 0, 0, 0}; + uint8_t data2[4] = {0x7f, 0xa6, 0x00, 0x2a}; + uint16_t result; + + (void)state; + + RSSVALS(data, 0, 32678); + RSSVALS(data, 2, 42); + assert_memory_equal(data, data2, sizeof(data)); + + result = RSVAL(data, 2); + assert_int_equal(result, 42); + + result = RSVAL(data, 0); + assert_int_equal(result, 32678); +} + +static void torture_push_be_u32(void **state) +{ + uint8_t data[8] = {0}; + uint8_t data2[8] = {0x00, 0x00, 0x7f, 0xa6, 0x00, 0x00, 0x00, 0x2a}; + uint32_t result; + + (void)state; + + RSIVALS(data, 0, 32678); + RSIVALS(data, 4, 42); + assert_memory_equal(data, data2, sizeof(data)); + + result = RIVAL(data, 4); + assert_int_equal(result, 42); + + result = RIVAL(data, 0); + assert_int_equal(result, 32678); + + RSIVALS(data, 0, 0xfffefffe); + result = RIVAL(data, 0); + assert_int_equal(result, 0xfffefffe); +} + +static void torture_push_be_u64(void **state) +{ + uint8_t data[16] = {0}; + uint64_t result; + + (void)state; + + RSBVALS(data, 0, 32678); + + result = RBVAL(data, 0); + assert_int_equal(result, 32678); + + SBVAL(data, 8, 0xfffefffe); + + result = BVAL(data, 8); + assert_int_equal(result, 0xfffefffe); +} + +int main(int argc, char *argv[]) +{ + int rc; + const struct CMUnitTest tests[] = { + cmocka_unit_test(torture_pull_le_u8), + cmocka_unit_test(torture_pull_le_u16), + cmocka_unit_test(torture_pull_le_u32), + + cmocka_unit_test(torture_push_le_u8), + cmocka_unit_test(torture_push_le_u16), + cmocka_unit_test(torture_push_le_u32), + cmocka_unit_test(torture_push_le_u64), + + /* BIG ENDIAN */ + cmocka_unit_test(torture_pull_be_u8), + cmocka_unit_test(torture_pull_be_u16), + cmocka_unit_test(torture_pull_be_u32), + + cmocka_unit_test(torture_push_be_u8), + cmocka_unit_test(torture_push_be_u16), + cmocka_unit_test(torture_push_be_u32), + cmocka_unit_test(torture_push_be_u64), + }; + + if (argc == 2) { + cmocka_set_test_filter(argv[1]); + } + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + rc = cmocka_run_group_tests(tests, NULL, NULL); + + return rc; +} diff --git a/lib/util/tests/test_byteorder_verify.c b/lib/util/tests/test_byteorder_verify.c new file mode 100644 index 0000000..a18ddad --- /dev/null +++ b/lib/util/tests/test_byteorder_verify.c @@ -0,0 +1,273 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2018-2019 Andreas Schneider <asn@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <setjmp.h> +#include <cmocka.h> + +#include "lib/replace/replace.h" +#include "lib/util/bytearray.h" +#include "lib/util/byteorder.h" + +static void torture_le_u8(void **state) +{ + uint8_t data[2] = {0}; + uint8_t result; + + (void)state; + + /* Test CVAL and SCVAL */ + PUSH_LE_U8(data, 0, 23); + PUSH_LE_U8(data, 1, 42); + + result = CVAL(data, 0); + assert_int_equal(result, 23); + + result = CVAL(data, 1); + assert_int_equal(result, 42); + + /* Test CVAL_NC and PVAL */ + PUSH_LE_U8(data, 0, 23); + PUSH_LE_U8(data, 1, 42); + + result = CVAL_NC(data, 0); + assert_int_equal(result, 23); + + result = PVAL(data, 1); + assert_int_equal(result, 42); + + /* Test SCVAL */ + SCVAL(data, 0, 42); + SCVAL(data, 1, 23); + + result = PULL_LE_U8(data, 0); + assert_int_equal(result, 42); + + result = PULL_LE_U8(data, 1); + assert_int_equal(result, 23); +} + +static void torture_le_u16(void **state) +{ + uint8_t data[2] = {0}; + uint16_t result; + + (void)state; + + /* Test SVAL */ + PUSH_LE_U16(data, 0, 0xff00); + result = SVAL(data, 0); + assert_int_equal(result, 0xff00); + + /* Test SSVAL */ + SSVAL(data, 0, 0x00ff); + result = PULL_LE_U16(data, 0); + assert_int_equal(result, 0x00ff); + + /* Test SSVALX */ + SSVALX(data, 0, 0x00fa); + result = PULL_LE_U16(data, 0); + assert_int_equal(result, 0x00fa); + + /* Test SSVALS */ + SSVALS(data, 0, 0x00fb); + result = PULL_LE_U16(data, 0); + assert_int_equal(result, 0x00fb); +} + +static void torture_le_u32(void **state) +{ + uint8_t data[4] = {0}; + uint32_t result; + + (void)state; + + /* Test IVAL */ + PUSH_LE_U32(data, 0, 0xff000000); + result = IVAL(data, 0); + assert_int_equal(result, 0xff000000); + + /* Test SIVAL */ + SIVAL(data, 0, 0xffaabbcc); + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 0xffaabbcc); + + /* Test SIVALX */ + SIVALX(data, 0, 0xffbbccdd); + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 0xffbbccdd); + + /* Test SIVALS */ + SIVALS(data, 0, 0xffccddee); + result = PULL_LE_U32(data, 0); + assert_int_equal(result, 0xffccddee); +} + +static void torture_le_u64(void **state) +{ + uint8_t data[8] = {0}; + uint64_t result; + + (void)state; + + PUSH_LE_U64(data, 0, 0xfffefffefffefffeUL); + result = BVAL(data, 0); + assert_int_equal(result, 0xfffefffefffefffeUL); + + SBVAL(data, 0, 0xfffafffafffafffaUL); + result = PULL_LE_U64(data, 0); + assert_int_equal(result, 0xfffafffafffafffaUL); +} + +static void torture_be_u8(void **state) +{ + uint8_t data[2] = {0}; + uint8_t result; + + (void)state; + + PUSH_BE_U8(data, 0, 23); + PUSH_BE_U8(data, 1, 42); + + result = CVAL(data, 0); + assert_int_equal(result, 23); + + result = CVAL(data, 1); + assert_int_equal(result, 42); + + SCVAL(data, 0, 42); + SCVAL(data, 1, 23); + + result = PULL_BE_U8(data, 0); + assert_int_equal(result, 42); + + result = PULL_BE_U8(data, 1); + assert_int_equal(result, 23); +} + +static void torture_be_u16(void **state) +{ + uint8_t data[2] = {0}; + uint16_t result; + + (void)state; + + /* Test RSVAL */ + PUSH_BE_U16(data, 0, 0xff00); + result = RSVAL(data, 0); + assert_int_equal(result, 0xff00); + + /* Test RSVALS */ + PUSH_BE_U16(data, 0, 0xffaa); + result = RSVALS(data, 0); + assert_int_equal(result, 0xffaa); + + /* Test RSSVAL */ + RSSVAL(data, 0, 0x00ff); + result = PULL_BE_U16(data, 0); + assert_int_equal(result, 0x00ff); + + /* Test RSSVALS */ + RSSVALS(data, 0, 0x00fa); + result = PULL_BE_U16(data, 0); + assert_int_equal(result, 0x00fa); +} + +static void torture_be_u32(void **state) +{ + uint8_t data[4] = {0}; + uint32_t result; + + (void)state; + + /* Test RIVAL */ + PUSH_BE_U32(data, 0, 0xff000000); + result = RIVAL(data, 0); + assert_int_equal(result, 0xff000000); + + /* Test RIVALS */ + PUSH_BE_U32(data, 0, 0xff0000aa); + result = RIVALS(data, 0); + assert_int_equal(result, 0xff0000aa); + + /* Test RSIVAL */ + RSIVAL(data, 0, 0xffeeddcc); + result = PULL_BE_U32(data, 0); + assert_int_equal(result, 0xffeeddcc); + + /* Test RSIVALS */ + RSIVALS(data, 0, 0xffaaddcc); + result = PULL_BE_U32(data, 0); + assert_int_equal(result, 0xffaaddcc); +} + +static void torture_be_u64(void **state) +{ + uint8_t data[8] = {0}; + uint64_t result; + + (void)state; + + /* Test RBVAL */ + PUSH_BE_U64(data, 0, 0xfffefffefffefffeUL); + result = RBVAL(data, 0); + assert_int_equal(result, 0xfffefffefffefffeUL); + + /* Test RBVALS */ + PUSH_BE_U64(data, 0, 0xfffafffafffafffaUL); + result = RBVALS(data, 0); + assert_int_equal(result, 0xfffafffafffafffaUL); + + /* Test RSBVAL */ + RSBVAL(data, 0, 0xfffbfffbfffbfffbUL); + result = PULL_BE_U64(data, 0); + assert_int_equal(result, 0xfffbfffbfffbfffbUL); + + /* Test RSBVALS */ + RSBVALS(data, 0, 0xfffcfffcfffcfffcUL); + result = PULL_BE_U64(data, 0); + assert_int_equal(result, 0xfffcfffcfffcfffcUL); +} + +int main(int argc, char *argv[]) +{ + int rc; + const struct CMUnitTest tests[] = { + cmocka_unit_test(torture_le_u8), + cmocka_unit_test(torture_le_u16), + cmocka_unit_test(torture_le_u32), + cmocka_unit_test(torture_le_u64), + + cmocka_unit_test(torture_be_u8), + cmocka_unit_test(torture_be_u16), + cmocka_unit_test(torture_be_u32), + cmocka_unit_test(torture_be_u64), + }; + + if (argc == 2) { + cmocka_set_test_filter(argv[1]); + } + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + rc = cmocka_run_group_tests(tests, NULL, NULL); + + return rc; +} diff --git a/lib/util/tests/test_logging.c b/lib/util/tests/test_logging.c new file mode 100644 index 0000000..9b13b05 --- /dev/null +++ b/lib/util/tests/test_logging.c @@ -0,0 +1,146 @@ +/* + Unix SMB/CIFS implementation. + + A test server that only does logging. + + Copyright (C) Andrew Tridgell 1992-2005 + Copyright (C) Martin Pool 2002 + Copyright (C) Jelmer Vernooij 2002 + Copyright (C) James J Myers 2003 <myersjj@samba.org> + Copyright (C) Douglas Bagnall 2022 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "lib/cmdline/cmdline.h" + +#ifdef USING_CMDLINE_S3 +#include "lib/util/debug_s3.h" +#endif + +#define BINARY_NAME "test_s4_logging" + +static int log_level = 1; + + +#include "lib/util/debug-classes/debug-classname-table.c" + +static int log_all_classes(int level) +{ + size_t i; + const char *name = NULL; + for (i = 0; i < ARRAY_SIZE(default_classname_table); i++) { + name = default_classname_table[i]; + DEBUGC(i, level, + ("logging for '%s' [%zu], at level %d\n", + name, i, level)); + + /* + * That's it for the tests *here*. The invoker of this + * process will have set up an smb.conf that directs the + * output in particular ways, and will be looking to see that + * happens correctly. + */ + } + return 0; +} + + +static int init_daemon(TALLOC_CTX *mem_ctx, + int argc, + const char *argv[], + const char **error) +{ + poptContext pc; + int opt; + bool ok; + struct poptOption long_options[] = { + POPT_AUTOHELP + { + .longName = "level", + .shortName = 'L', + .argInfo = POPT_ARG_INT, + .arg = &log_level, + .descrip = "log at this level", + .argDescrip = "LEVEL", + }, + POPT_COMMON_SAMBA + POPT_COMMON_DAEMON + POPT_COMMON_VERSION + POPT_TABLEEND + }; + + setproctitle(BINARY_NAME); + + ok = samba_cmdline_init(mem_ctx, + SAMBA_CMDLINE_CONFIG_SERVER, + true /* require_smbconf */); + if (!ok) { + *error = "Failed to init cmdline parser!\n"; + return EINVAL; + } + + pc = samba_popt_get_context(BINARY_NAME, + argc, + argv, + long_options, + 0); + if (pc == NULL) { + *error = "Failed to setup popt context!\n"; + return ENOTRECOVERABLE; + } + + while((opt = poptGetNextOpt(pc)) != -1) { + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + return 1; + } + + poptFreeContext(pc); + +#ifdef USING_CMDLINE_S3 + reopen_logs(); +#endif + return 0; +} + + +int main(int argc, const char *argv[]) +{ + int rc; + const char *error = NULL; + TALLOC_CTX *mem_ctx = talloc_stackframe(); + if (mem_ctx == NULL) { + exit(ENOMEM); + } + + setproctitle_init(argc, discard_const(argv), environ); + + rc = init_daemon(mem_ctx, argc, argv, &error); + if (rc != 0) { + fprintf(stderr, "error [%d]: %s\n", rc, error); + exit_daemon(error, rc); + } + + rc = log_all_classes(log_level); + if (rc != 0) { + fprintf(stderr, "error in log_all_classes [%d]\n", rc); + exit_daemon("logging error", rc); + } + + TALLOC_FREE(mem_ctx); + return rc; +} diff --git a/lib/util/tests/test_memcache.c b/lib/util/tests/test_memcache.c new file mode 100644 index 0000000..8a39978 --- /dev/null +++ b/lib/util/tests/test_memcache.c @@ -0,0 +1,161 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2021 Andreas Schneider <asn@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <setjmp.h> +#include <cmocka.h> + +#include "lib/replace/replace.h" +#include "lib/util/talloc_stack.h" +#include "lib/util/memcache.h" + +static int setup_talloc_context(void **state) +{ + TALLOC_CTX *frame = talloc_stackframe(); + + *state = frame; + return 0; +} + +static int teardown_talloc_context(void **state) +{ + TALLOC_CTX *frame = *state; + TALLOC_FREE(frame); + return 0; +} + +static void torture_memcache_init(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + struct memcache *cache = NULL; + + cache = memcache_init(mem_ctx, 0); + assert_non_null(cache); + + TALLOC_FREE(cache); + + cache = memcache_init(mem_ctx, 10); + assert_non_null(cache); + + TALLOC_FREE(cache); +} + +static void torture_memcache_add_lookup_delete(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + struct memcache *cache = NULL; + DATA_BLOB key1, key2; + char *path1 = NULL, *path2 = NULL; + + cache = memcache_init(mem_ctx, 0); + assert_non_null(cache); + + key1 = data_blob_const("key1", 4); + path1 = talloc_strdup(mem_ctx, "/tmp/one"); + assert_non_null(path1); + + key2 = data_blob_const("key2", 4); + path2 = talloc_strdup(mem_ctx, "/tmp/two"); + assert_non_null(path1); + + memcache_add_talloc(cache, GETWD_CACHE, key1, &path1); + assert_null(path1); + + memcache_add_talloc(cache, GETWD_CACHE, key2, &path2); + assert_null(path2); + + path1 = memcache_lookup_talloc(cache, GETWD_CACHE, key1); + assert_non_null(path1); + assert_string_equal(path1, "/tmp/one"); + + path2 = memcache_lookup_talloc(cache, GETWD_CACHE, key2); + assert_non_null(path2); + assert_string_equal(path2, "/tmp/two"); + + memcache_delete(cache, GETWD_CACHE, key1); + path1 = memcache_lookup_talloc(cache, GETWD_CACHE, key1); + assert_null(path1); + + memcache_flush(cache, GETWD_CACHE); + path2 = memcache_lookup_talloc(cache, GETWD_CACHE, key2); + assert_null(path2); + + TALLOC_FREE(path1); + TALLOC_FREE(path2); + TALLOC_FREE(cache); +} + +static void torture_memcache_add_oversize(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + struct memcache *cache = NULL; + DATA_BLOB key1, key2; + char *path1 = NULL, *path2 = NULL; + + cache = memcache_init(mem_ctx, 10); + assert_non_null(cache); + + key1 = data_blob_const("key1", 4); + path1 = talloc_strdup(mem_ctx, "/tmp/one"); + assert_non_null(path1); + + key2 = data_blob_const("key2", 4); + path2 = talloc_strdup(mem_ctx, "/tmp/two"); + assert_non_null(path1); + + memcache_add_talloc(cache, GETWD_CACHE, key1, &path1); + assert_null(path1); + + memcache_add_talloc(cache, GETWD_CACHE, key2, &path2); + assert_null(path2); + + path1 = memcache_lookup_talloc(cache, GETWD_CACHE, key1); + assert_null(path1); + + path2 = memcache_lookup_talloc(cache, GETWD_CACHE, key2); + assert_non_null(path2); + assert_string_equal(path2, "/tmp/two"); + + TALLOC_FREE(path1); + TALLOC_FREE(path2); + TALLOC_FREE(cache); +} + +int main(int argc, char *argv[]) +{ + int rc; + const struct CMUnitTest tests[] = { + cmocka_unit_test(torture_memcache_init), + cmocka_unit_test(torture_memcache_add_lookup_delete), + cmocka_unit_test(torture_memcache_add_oversize), + }; + + if (argc == 2) { + cmocka_set_test_filter(argv[1]); + } + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + rc = cmocka_run_group_tests(tests, + setup_talloc_context, + teardown_talloc_context); + + return rc; +} diff --git a/lib/util/tests/test_ms_fnmatch.c b/lib/util/tests/test_ms_fnmatch.c new file mode 100644 index 0000000..d11c7be --- /dev/null +++ b/lib/util/tests/test_ms_fnmatch.c @@ -0,0 +1,114 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2018 David Disseldorp <ddiss@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <setjmp.h> +#include <cmocka.h> + +#include <errno.h> + +#include "lib/replace/replace.h" +#include "lib/util/samba_util.h" +#include "libcli/smb/smb_constants.h" + +static void test_ms_fn_match_protocol_no_wildcard(void **state) +{ + int cmp; + + /* no wildcards in pattern, a simple strcasecmp_m */ + cmp = ms_fnmatch_protocol("pattern", "string", PROTOCOL_COREPLUS, + true); /* case sensitive */ + assert_int_equal(cmp, -3); +} + +static void test_ms_fn_match_protocol_pattern_upgraded(void **state) +{ + int cmp; + + /* protocol < PROTOCOL_NT1 pattern is "upgraded" */ + cmp = ms_fnmatch_protocol("??????", "string", PROTOCOL_COREPLUS, + false); + assert_int_equal(cmp, 0); +} + +static void test_ms_fn_match_protocol_match_zero_or_more(void **state) +{ + int cmp; + + /* '*' matches zero or more characters. handled via recursive calls */ + cmp = ms_fnmatch_protocol("********", "string", PROTOCOL_COREPLUS, + true); + assert_int_equal(cmp, 0); +} + +static void test_ms_fn_match_protocol_mapped_char(void **state) +{ + int cmp; + + /* '?' is mapped to '>', which matches any char or a '\0' */ + cmp = ms_fnmatch_protocol("???????", "string", PROTOCOL_COREPLUS, + false); + assert_int_equal(cmp, 0); +} + +static void test_ms_fn_match_protocol_nt1_any_char(void **state) +{ + int cmp; + + /* PROTOCOL_NT1 '?' matches any char, '\0' is not included */ + cmp = ms_fnmatch_protocol("???????", "string", PROTOCOL_NT1, + false); + assert_int_equal(cmp, -1); +} + +static void test_ms_fn_match_protocol_nt1_case_sensitive(void **state) +{ + int cmp; + + cmp = ms_fnmatch_protocol("StRinG", "string", PROTOCOL_NT1, + true); /* case sensitive */ + assert_int_equal(cmp, 0); + + cmp = ms_fnmatch_protocol("StRin?", "string", PROTOCOL_NT1, + true); /* case sensitive */ + assert_int_equal(cmp, -1); + + cmp = ms_fnmatch_protocol("StRin?", "string", PROTOCOL_NT1, + false); + assert_int_equal(cmp, 0); + cmp = ms_fnmatch_protocol("strin?", "string", PROTOCOL_NT1, + true); /* case sensitive */ + assert_int_equal(cmp, 0); +} + +int main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_ms_fn_match_protocol_no_wildcard), + cmocka_unit_test(test_ms_fn_match_protocol_pattern_upgraded), + cmocka_unit_test(test_ms_fn_match_protocol_match_zero_or_more), + cmocka_unit_test(test_ms_fn_match_protocol_mapped_char), + cmocka_unit_test(test_ms_fn_match_protocol_nt1_any_char), + cmocka_unit_test(test_ms_fn_match_protocol_nt1_case_sensitive), + }; + + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/lib/util/tests/test_stable_sort.c b/lib/util/tests/test_stable_sort.c new file mode 100644 index 0000000..ae4b1f3 --- /dev/null +++ b/lib/util/tests/test_stable_sort.c @@ -0,0 +1,317 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2018 Andreas Schneider <asn@samba.org> + * Copyright (C) 2022 Douglas Bagnall <dbagnall@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#include <stdbool.h> +#include "replace.h" +#include <talloc.h> + +#include "../stable_sort.h" + + +static int cmp_integer(int *a, int *b) +{ + if (a == NULL || b == NULL) { + return 0; + } + + if (*a > *b) { + return 1; + } + + if (*a < *b) { + return -1; + } + + return 0; +} + +static void test_stable_sort(void **state) +{ + int a[6] = { 6, 3, 2, 7, 9, 4 }; + int tmp[6]; + bool ok; + ok = stable_sort(a, tmp, + 6, sizeof(int), (samba_compare_fn_t)cmp_integer); + + assert_true(ok); + assert_int_equal(a[0], 2); + assert_int_equal(a[1], 3); + assert_int_equal(a[2], 4); + assert_int_equal(a[3], 6); + assert_int_equal(a[4], 7); + assert_int_equal(a[5], 9); +} + +static void test_stable_sort_talloc_short(void **state) +{ + int a[6] = { 6, 3, 2, 7, 9, 4 }; + int ret; + ret = stable_sort_talloc(NULL, a, 6, sizeof(int), + (samba_compare_fn_t)cmp_integer); + assert_true(ret); + + assert_int_equal(a[0], 2); + assert_int_equal(a[1], 3); + assert_int_equal(a[2], 4); + assert_int_equal(a[3], 6); + assert_int_equal(a[4], 7); + assert_int_equal(a[5], 9); +} + +static void test_stable_sort_talloc_long(void **state) +{ + int i, ret; + size_t n = 1500; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + int *a = talloc_array(mem_ctx, int, n); + for (i = 0; i < n; i++) { + a[i] = n - i; + } + + ret = stable_sort_talloc(mem_ctx, a, n, sizeof(int), + (samba_compare_fn_t)cmp_integer); + assert_true(ret); + + for (i = 0; i < n; i++) { + assert_int_equal(a[i], 1 + i); + } +} + + +/* + * Sort an array of structs with: + * - unwieldy uneven size + * - sort key not at the start + * - comparison depends on context + * + * which are things we sometimes do. + */ + +struct contrived_struct { + char padding_1[13]; + int key[3]; + char padding_2[18]; + size_t *index; +}; + + +static int cmp_contrived_struct(struct contrived_struct *as, + struct contrived_struct *bs) +{ + int i = *as->index; + int a = as->key[i]; + int b = bs->key[i]; + return a - b; +} + +static int cmp_contrived_struct_rev(struct contrived_struct *as, + struct contrived_struct *bs) +{ + /* will sort in reverseo order */ + int i = *as->index; + int a = as->key[i]; + int b = bs->key[i]; + return b - a; +} + + +static void test_stable_sort_talloc_contrived_struct(void **state) +{ + int i, ret, prev; + size_t n = 800000; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + size_t key_index = 0; + + struct contrived_struct *a = talloc_zero_array(mem_ctx, + struct contrived_struct, + n); + + /* we don't really want a good RNG, we want mess and repeated values. */ + uint32_t x = 89, y = (uint32_t)-6, z = 11; + for (i = 0; i < n; i++) { + a[i].index = &key_index; + a[i].key[0] = (x & 0xffff) - 0x8000; + a[i].key[1] = z & 255; + /* key[2] is original order, useful for checking stability */ + a[i].key[2] = i; + x += z ^ y; + y *= z + (x + 0x5555); + z -= x ^ i; + } + + /* 1. sort by key[0] */ + ret = stable_sort_talloc(mem_ctx, a, n, + sizeof(struct contrived_struct), + (samba_compare_fn_t)cmp_contrived_struct); + assert_true(ret); + prev = a[0].key[0]; + for (i = 1; i < n; i++) { + int value = a[i].key[0]; + assert_true(value >= prev); + if (value == prev) { + /* we can test the stability by comparing key[2] */ + assert_true(a[i].key[2] >= a[i - 1].key[2]); + } + prev = value; + } + + /* 2. sort by key[1]. key[0] now indicates stability. */ + key_index = 1; + ret = stable_sort_talloc(mem_ctx, a, n, + sizeof(struct contrived_struct), + (samba_compare_fn_t)cmp_contrived_struct); + assert_true(ret); + prev = a[0].key[1]; + for (i = 1; i < n; i++) { + int value = a[i].key[1]; + assert_true(value >= prev); + if (value == prev) { + assert_true(a[i].key[0] >= a[i - 1].key[0]); + } + prev = value; + } + + /* + * 3. sort by key[2]. key[1] would now indicate stability, but we know + * that key[2] has no duplicates, so stability is moot. + */ + key_index = 2; + ret = stable_sort_talloc(mem_ctx, a, n, + sizeof(struct contrived_struct), + (samba_compare_fn_t)cmp_contrived_struct); + assert_true(ret); + prev = a[0].key[2]; + for (i = 1; i < n; i++) { + int value = a[i].key[2]; + assert_true(value > prev); + prev = value; + } + + /* + * 4. sort by key[0] again, using descending sort order. key[2] should + * still be in ascending order where there are duplicate key[0] values. + */ + key_index = 0; + ret = stable_sort_talloc(mem_ctx, a, n, + sizeof(struct contrived_struct), + (samba_compare_fn_t)cmp_contrived_struct_rev); + assert_true(ret); + prev = a[0].key[0]; + for (i = 1; i < n; i++) { + int value = a[i].key[0]; + assert_true(value <= prev); + if (value == prev) { + assert_true(a[i].key[2] >= a[i - 1].key[2]); + } + prev = value; + } +} + + + +static int cmp_integer_xor_blob(int *_a, int *_b, int *opaque) +{ + int a = *_a ^ *opaque; + int b = *_b ^ *opaque; + + if (a > b) { + return 1; + } + + if (a < b) { + return -1; + } + + return 0; +} + +static void test_stable_sort_talloc_r(void **state) +{ + int i; + size_t n = 1500; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + int opaque = 42; + bool ok; + int *a = talloc_array(mem_ctx, int, n); + for (i = 0; i < n; i++) { + a[i] = (i * 7) & 255; + } + + ok = stable_sort_talloc_r(mem_ctx, a, n, sizeof(int), + (samba_compare_with_context_fn_t)cmp_integer_xor_blob, + &opaque); + assert_true(ok); + + for (i = 1; i < n; i++) { + assert_true((a[i - 1] ^ opaque) <= (a[i] ^ opaque)); + } +} + + +static void test_stable_sort_silly_size(void **state) +{ + bool ok; + int a[33] = {0}; + int b[33] = {0}; + + ok = stable_sort(a, + b, + (SIZE_MAX / 2) + 2, + (SIZE_MAX / 2) + 2, + (samba_compare_fn_t)cmp_integer); + assert_false(ok); +} + +static void test_stable_sort_null_array(void **state) +{ + bool ok; + int a[33] = {0}; + + ok = stable_sort(a, + NULL, + 33, + sizeof(int), + (samba_compare_fn_t)cmp_integer); + assert_false(ok); +} + + + + + +int main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_stable_sort), + cmocka_unit_test(test_stable_sort_talloc_short), + cmocka_unit_test(test_stable_sort_talloc_long), + cmocka_unit_test(test_stable_sort_talloc_contrived_struct), + cmocka_unit_test(test_stable_sort_talloc_r), + cmocka_unit_test(test_stable_sort_silly_size), + cmocka_unit_test(test_stable_sort_null_array), + }; + if (!isatty(1)) { + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + } + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/lib/util/tests/test_sys_rw.c b/lib/util/tests/test_sys_rw.c new file mode 100644 index 0000000..22688fb --- /dev/null +++ b/lib/util/tests/test_sys_rw.c @@ -0,0 +1,178 @@ +/* + * Unix SMB/CIFS implementation. + * + * Unit test for sys_rw.c + * + * Copyright (C) Ralph Böhme 2021 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <setjmp.h> +#include <cmocka.h> + +#include "lib/replace/replace.h" +#include "system/dir.h" + +#include "lib/util/sys_rw.c" + +static void test_sys_io_ranges_overlap(void **state) +{ + bool overlap; + + /* + * sys_io_ranges_overlap() args are: + * + * src size, src offset, dst size, dst offset + */ + + /* src and dst size 0 => no overlap */ + overlap = sys_io_ranges_overlap(0, 0, 0, 0); + assert_false(overlap); + + /* dst size 0 => no overlap */ + overlap = sys_io_ranges_overlap(1, 0, 0, 0); + assert_false(overlap); + + /* src size 0 => no overlap */ + overlap = sys_io_ranges_overlap(0, 0, 1, 0); + assert_false(overlap); + + /* same range => overlap */ + overlap = sys_io_ranges_overlap(1, 0, 1, 0); + assert_true(overlap); + + /* + * |.| + * |.| + * src before dst => no overlap + */ + overlap = sys_io_ranges_overlap(1, 0, 1, 1); + assert_false(overlap); + + /* + * |..| + * |..| + * src into dst => overlap + */ + overlap = sys_io_ranges_overlap(2, 0, 2, 1); + assert_true(overlap); + + /* + * |....| + * |..| + * src encompasses dst => overlap + */ + overlap = sys_io_ranges_overlap(4, 0, 1, 2); + assert_true(overlap); + + + /* + * |..| + * |..| + * dst into src => overlap + */ + overlap = sys_io_ranges_overlap(2, 1, 2, 0); + assert_true(overlap); + + /* + * |..| + * |....| + * dst encompasses src => overlap + */ + overlap = sys_io_ranges_overlap(2, 1, 4, 0); + assert_true(overlap); +} + +static void test_sys_block_align(void **state) +{ + int asize; + + asize = sys_block_align(0, 2); + assert_int_equal(asize, 0); + asize = sys_block_align(1, 2); + assert_int_equal(asize, 2); + asize = sys_block_align(2, 2); + assert_int_equal(asize, 2); + asize = sys_block_align(3, 2); + assert_int_equal(asize, 4); + + asize = sys_block_align(0, 4); + assert_int_equal(asize, 0); + asize = sys_block_align(1, 4); + assert_int_equal(asize, 4); + asize = sys_block_align(3, 4); + assert_int_equal(asize, 4); + asize = sys_block_align(4, 4); + assert_int_equal(asize, 4); + asize = sys_block_align(5, 4); + assert_int_equal(asize, 8); + asize = sys_block_align(7, 4); + assert_int_equal(asize, 8); + asize = sys_block_align(8, 4); + assert_int_equal(asize, 8); + asize = sys_block_align(9, 4); + assert_int_equal(asize, 12); +} + +static void test_sys_block_align_truncate(void **state) +{ + int asize; + + asize = sys_block_align_truncate(0, 2); + assert_int_equal(asize, 0); + asize = sys_block_align_truncate(1, 2); + assert_int_equal(asize, 0); + asize = sys_block_align_truncate(2, 2); + assert_int_equal(asize, 2); + asize = sys_block_align_truncate(3, 2); + assert_int_equal(asize, 2); + asize = sys_block_align_truncate(4, 2); + assert_int_equal(asize, 4); + asize = sys_block_align_truncate(5, 2); + assert_int_equal(asize, 4); + + asize = sys_block_align_truncate(0, 4); + assert_int_equal(asize, 0); + asize = sys_block_align_truncate(1, 4); + assert_int_equal(asize, 0); + asize = sys_block_align_truncate(3, 4); + assert_int_equal(asize, 0); + asize = sys_block_align_truncate(4, 4); + assert_int_equal(asize, 4); + asize = sys_block_align_truncate(5, 4); + assert_int_equal(asize, 4); + asize = sys_block_align_truncate(7, 4); + assert_int_equal(asize, 4); + asize = sys_block_align_truncate(8, 4); + assert_int_equal(asize, 8); + asize = sys_block_align_truncate(9, 4); + assert_int_equal(asize, 8); +} + +int main(int argc, char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_sys_io_ranges_overlap), + cmocka_unit_test(test_sys_block_align), + cmocka_unit_test(test_sys_block_align_truncate), + }; + + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/lib/util/tests/test_talloc_keep_secret.c b/lib/util/tests/test_talloc_keep_secret.c new file mode 100644 index 0000000..1462dab --- /dev/null +++ b/lib/util/tests/test_talloc_keep_secret.c @@ -0,0 +1,94 @@ +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <setjmp.h> +#include <cmocka.h> + +#include <string.h> +#include <talloc.h> +#include "lib/util/talloc_keep_secret.h" + +int rep_memset_s(void *dest, size_t destsz, int ch, size_t count); + +int rep_memset_s(void *dest, size_t destsz, int ch, size_t count) +{ + check_expected_ptr(dest); + check_expected(destsz); + check_expected(ch); + check_expected(count); + + return 0; +} + +static void test_talloc_keep_secret(void ** state) +{ + TALLOC_CTX *pool = NULL; + char *ptr1 = NULL; + char *ptr2 = NULL; + const char *ptr1_talloc_name = NULL; + size_t ptr1_size; + size_t i; + + pool = talloc_pool(NULL, 256); + assert_non_null(pool); + + ptr1 = talloc_strdup(pool, "secret"); + assert_non_null(ptr1); + assert_string_equal(ptr1, "secret"); + + talloc_keep_secret(ptr1); + + ptr1_talloc_name = talloc_get_name(ptr1); + assert_string_equal(ptr1_talloc_name, "ptr1"); + + ptr1_size = talloc_get_size(ptr1); + assert_int_equal(ptr1_size, strlen(ptr1) + 1); + + expect_string(rep_memset_s, dest, "secret"); + expect_value(rep_memset_s, destsz, strlen(ptr1) + 1); + expect_value(rep_memset_s, ch, (int)'\0'); + expect_value(rep_memset_s, count, strlen(ptr1) + 1); + + talloc_free(ptr1); + + ptr2 = talloc_size(pool, ptr1_size); + assert_ptr_equal(ptr1, ptr2); + + for (i = 1; i < ptr1_size; i++) { + assert_int_not_equal(ptr2[0], ptr2[i]); + } + + talloc_free(pool); +} + +static void test_talloc_keep_secret_validate_memset(void **state) +{ + TALLOC_CTX *mem_ctx = NULL; + char *password = NULL; + + mem_ctx = talloc_new(NULL); + assert_non_null(mem_ctx); + + password = talloc_strdup(mem_ctx, "secret"); + assert_non_null(password); + talloc_keep_secret(password); + + expect_string(rep_memset_s, dest, "secret"); + expect_value(rep_memset_s, destsz, strlen(password) + 1); + expect_value(rep_memset_s, ch, (int)'\0'); + expect_value(rep_memset_s, count, strlen(password) + 1); + + talloc_free(mem_ctx); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_talloc_keep_secret), + cmocka_unit_test(test_talloc_keep_secret_validate_memset), + }; + + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/lib/util/tests/test_util.c b/lib/util/tests/test_util.c new file mode 100644 index 0000000..62f10ed --- /dev/null +++ b/lib/util/tests/test_util.c @@ -0,0 +1,344 @@ +/* + * Unix SMB/CIFS implementation. + * + * Unit test for util.c + * + * Copyright (C) Christof Schmitt 2020 + * Copyright (C) Andreas Schneider 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <setjmp.h> +#include <cmocka.h> + +#include "lib/replace/replace.h" +#include "system/dir.h" + +#include "lib/util/util.c" + +struct test_paths { + char testdir[PATH_MAX]; + char none[PATH_MAX]; + char dir[PATH_MAX]; + char dir_recursive[PATH_MAX]; + mode_t dir_mode; + char file[PATH_MAX]; + mode_t file_mode; + char symlink_none[PATH_MAX]; + char symlink_dir[PATH_MAX]; + char symlink_file[PATH_MAX]; +}; + +static int group_setup(void **state) +{ + struct test_paths *paths = NULL; + char *testdir = NULL; + int ret, fd; + + umask(0); + + paths = malloc(sizeof(struct test_paths)); + assert_non_null(paths); + + strlcpy(paths->testdir, tmpdir(), sizeof(paths->testdir)); + strlcat(paths->testdir, "/test_util_XXXXXX", sizeof(paths->testdir)); + testdir = mkdtemp(paths->testdir); + assert_non_null(testdir); + + strlcpy(paths->none, testdir, sizeof(paths->none)); + strlcat(paths->none, "/none", sizeof(paths->none)); + + strlcpy(paths->dir, testdir, sizeof(paths->dir)); + strlcat(paths->dir, "/dir", sizeof(paths->dir)); + paths->dir_mode = 0750; + ret = mkdir(paths->dir, paths->dir_mode); + assert_return_code(ret, errno); + + strlcpy(paths->dir_recursive, testdir, sizeof(paths->dir)); + strlcat(paths->dir_recursive, "/dir_recursive", sizeof(paths->dir)); + paths->dir_mode = 0750; + ret = mkdir(paths->dir_recursive, paths->dir_mode); + assert_return_code(ret, errno); + + strlcpy(paths->file, testdir, sizeof(paths->file)); + strlcat(paths->file, "/file", sizeof(paths->file)); + paths->file_mode = 0640; + fd = creat(paths->file, paths->file_mode); + assert_return_code(fd, errno); + ret = close(fd); + assert_return_code(ret, errno); + + strlcpy(paths->symlink_none, testdir, sizeof(paths->symlink_none)); + strlcat(paths->symlink_none, "/symlink_none", + sizeof(paths->symlink_none)); + ret = symlink("/none", paths->symlink_none); + assert_return_code(ret, errno); + + strlcpy(paths->symlink_dir, testdir, sizeof(paths->symlink_dir)); + strlcat(paths->symlink_dir, "/symlink_dir", sizeof(paths->symlink_dir)); + ret = symlink(paths->dir, paths->symlink_dir); + assert_return_code(ret, errno); + + strlcpy(paths->symlink_file, testdir, sizeof(paths->symlink_file)); + strlcat(paths->symlink_file, "/symlink_file", + sizeof(paths->symlink_file)); + ret = symlink(paths->file, paths->symlink_file); + assert_return_code(ret, errno); + + *state = paths; + + return 0; +} + +static int torture_rmdirs(const char *path) +{ + DIR *d; + struct dirent *dp; + struct stat sb; + char *fname; + + if ((d = opendir(path)) != NULL) { + while(stat(path, &sb) == 0) { + /* if we can remove the directory we're done */ + if (rmdir(path) == 0) { + break; + } + switch (errno) { + case ENOTEMPTY: + case EEXIST: + case EBADF: + break; /* continue */ + default: + closedir(d); + return 0; + } + + while ((dp = readdir(d)) != NULL) { + size_t len; + /* skip '.' and '..' */ + if (dp->d_name[0] == '.' && + (dp->d_name[1] == '\0' || + (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) { + continue; + } + + len = strlen(path) + strlen(dp->d_name) + 2; + fname = malloc(len); + if (fname == NULL) { + closedir(d); + return -1; + } + snprintf(fname, len, "%s/%s", path, dp->d_name); + + /* stat the file */ + if (lstat(fname, &sb) != -1) { + if (S_ISDIR(sb.st_mode) && !S_ISLNK(sb.st_mode)) { + if (rmdir(fname) < 0) { /* can't be deleted */ + if (errno == EACCES) { + closedir(d); + SAFE_FREE(fname); + return -1; + } + torture_rmdirs(fname); + } + } else { + unlink(fname); + } + } /* lstat */ + SAFE_FREE(fname); + } /* readdir */ + + rewinddir(d); + } + } else { + return -1; + } + + closedir(d); + return 0; +} + +static int group_teardown(void **state) +{ + struct test_paths *paths = *state; + int ret; + + ret = unlink(paths->file); + assert_return_code(ret, errno); + + ret = unlink(paths->symlink_none); + assert_return_code(ret, errno); + + ret = unlink(paths->symlink_dir); + assert_return_code(ret, errno); + + ret = unlink(paths->symlink_file); + assert_return_code(ret, errno); + + ret = torture_rmdirs(paths->testdir); + assert_return_code(ret, errno); + + free(paths); + return 0; +} + +static void test_directory_create_or_exists_none(void **state) +{ + struct test_paths *paths = *state; + bool b; + struct stat sbuf; + int ret; + + b = directory_create_or_exist(paths->none, 0775); + assert_true(b); + + ret = lstat(paths->none, &sbuf); + assert_return_code(ret, errno); + assert_int_equal(sbuf.st_mode & 0777, 0775); + assert_true(S_ISDIR(sbuf.st_mode)); +} + +static int teardown_none_directory(void **state) +{ + struct test_paths *paths = *state; + + rmdir(paths->none); + return 0; +} + +static void test_directory_create_or_exists_dir(void **state) +{ + struct test_paths *paths = *state; + bool b; + struct stat sbuf; + int ret; + + b = directory_create_or_exist(paths->dir, 770); + assert_true(b); + + ret = lstat(paths->dir, &sbuf); + assert_return_code(ret, errno); + assert_int_equal(sbuf.st_mode & 0777, paths->dir_mode); + assert_true(S_ISDIR(sbuf.st_mode)); +} + +static void test_directory_create_or_exists_file(void **state) +{ + struct test_paths *paths = *state; + bool b; + struct stat sbuf; + int ret; + + b = directory_create_or_exist(paths->file, 770); + assert_false(b); + + ret = lstat(paths->file, &sbuf); + assert_return_code(ret, errno); + assert_int_equal(sbuf.st_mode & 0777, paths->file_mode); + assert_true(S_ISREG(sbuf.st_mode)); +} + +static void test_directory_create_or_exists_symlink_none(void **state) +{ + struct test_paths *paths = *state; + bool b; + struct stat sbuf; + int ret; + + b = directory_create_or_exist(paths->symlink_none, 770); + assert_false(b); + + ret = lstat(paths->symlink_none, &sbuf); + assert_return_code(ret, errno); + assert_int_equal(sbuf.st_mode & 0777, 0777); + assert_true(S_ISLNK(sbuf.st_mode)); +} + +static void test_directory_create_or_exists_symlink_dir(void **state) +{ + struct test_paths *paths = *state; + bool b; + struct stat sbuf; + int ret; + + b = directory_create_or_exist(paths->symlink_dir, 770); + assert_true(b); + + ret = lstat(paths->symlink_dir, &sbuf); + assert_return_code(ret, errno); + assert_int_equal(sbuf.st_mode & 0777, 0777); + assert_true(S_ISLNK(sbuf.st_mode)); +} + +static void test_directory_create_or_exists_symlink_file(void **state) +{ + struct test_paths *paths = *state; + bool b; + struct stat sbuf; + int ret; + + b = directory_create_or_exist(paths->symlink_file, 770); + assert_false(b); + + ret = lstat(paths->symlink_file, &sbuf); + assert_return_code(ret, errno); + assert_int_equal(sbuf.st_mode & 0777, 0777); + assert_true(S_ISLNK(sbuf.st_mode)); +} + +static void test_directory_create_or_exists_recursive(void **state) +{ + struct test_paths *paths = *state; + char recursive_testdir[PATH_MAX] = {0}; + struct stat sbuf = {0}; + bool ok; + int ret; + + ret = snprintf(recursive_testdir, + sizeof(recursive_testdir), + "%s/wurst/brot", + paths->dir_recursive); + assert_int_not_equal(ret, -1); + + ok = directory_create_or_exists_recursive(recursive_testdir, + 0700); + assert_true(ok); + + ret = lstat(recursive_testdir, &sbuf); + assert_return_code(ret, errno); + assert_int_equal(sbuf.st_mode & 0777, 0700); + assert_true(S_ISDIR(sbuf.st_mode)); +} + +int main(int argc, char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_teardown(test_directory_create_or_exists_none, + teardown_none_directory), + cmocka_unit_test(test_directory_create_or_exists_dir), + cmocka_unit_test(test_directory_create_or_exists_file), + cmocka_unit_test(test_directory_create_or_exists_symlink_none), + cmocka_unit_test(test_directory_create_or_exists_symlink_dir), + cmocka_unit_test(test_directory_create_or_exists_symlink_file), + cmocka_unit_test(test_directory_create_or_exists_recursive), + }; + + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + return cmocka_run_group_tests(tests, group_setup, group_teardown); +} diff --git a/lib/util/tests/test_util_paths.c b/lib/util/tests/test_util_paths.c new file mode 100644 index 0000000..4dfe11c --- /dev/null +++ b/lib/util/tests/test_util_paths.c @@ -0,0 +1,127 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2020 Andreas Schneider <asn@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <setjmp.h> +#include <cmocka.h> + +#include "lib/replace/replace.h" +#include <talloc.h> + +#include "lib/util/util_paths.c" + +static int setup(void **state) +{ + TALLOC_CTX *mem_ctx = talloc_new(NULL); + + assert_non_null(mem_ctx); + *state = mem_ctx; + + return 0; +} + +static int teardown(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + TALLOC_FREE(mem_ctx); + + return 0; +} + +static void test_get_user_home_dir(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + struct passwd *pwd = getpwuid(getuid()); + char *user; + + user = get_user_home_dir(mem_ctx); + assert_non_null(user); + assert_string_equal(user, pwd->pw_dir); + + TALLOC_FREE(user); +} + +static void test_path_expand_tilde(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + char h[256] = {0}; + char *d = NULL; + const char *user = NULL; + char *home = NULL; + + user = getenv("USER"); + if (user == NULL){ + user = getenv("LOGNAME"); + } + + /* In certain CIs there no such variables */ + if (user == NULL) { + struct passwd *pw = getpwuid(getuid()); + if (pw){ + user = pw->pw_name; + } + } + + home = getenv("HOME"); + assert_non_null(home); + snprintf(h, sizeof(h), "%s/.cache", home); + + d = path_expand_tilde(mem_ctx, "~/.cache"); + assert_non_null(d); + assert_string_equal(d, h); + TALLOC_FREE(d); + + snprintf(h, sizeof(h), "%s/.cache/X~", home); + d = path_expand_tilde(mem_ctx, "~/.cache/X~"); + assert_string_equal(d, h); + TALLOC_FREE(d); + + d = path_expand_tilde(mem_ctx, "/guru/meditation"); + assert_non_null(d); + assert_string_equal(d, "/guru/meditation"); + TALLOC_FREE(d); + + snprintf(h, sizeof(h), "~%s/.cache", user); + d = path_expand_tilde(mem_ctx, h); + assert_non_null(d); + + snprintf(h, sizeof(h), "%s/.cache", home); + assert_string_equal(d, h); + TALLOC_FREE(d); +} + +int main(int argc, char *argv[]) +{ + int rc; + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_get_user_home_dir), + cmocka_unit_test(test_path_expand_tilde), + }; + + if (argc == 2) { + cmocka_set_test_filter(argv[1]); + } + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + rc = cmocka_run_group_tests(tests, setup, teardown); + + return rc; +} diff --git a/lib/util/tests/tfork-drd.supp b/lib/util/tests/tfork-drd.supp new file mode 100644 index 0000000..7d0544b --- /dev/null +++ b/lib/util/tests/tfork-drd.supp @@ -0,0 +1,14 @@ +{ + tfork_pthread_cond_init + drd:CondErr + fun:pthread_cond_init_intercept + fun:pthread_cond_init@* + fun:tfork_atfork_child + fun:fork + fun:tfork_start_waiter_and_worker + fun:tfork_create + fun:tfork_thread + fun:vgDrd_thread_wrapper + fun:start_thread + fun:clone +} diff --git a/lib/util/tests/tfork-helgrind.supp b/lib/util/tests/tfork-helgrind.supp new file mode 100644 index 0000000..4b62b2a --- /dev/null +++ b/lib/util/tests/tfork-helgrind.supp @@ -0,0 +1,32 @@ +{ + tfork_atexit_unknown1 + Helgrind:Misc + fun:mutex_destroy_WRK + fun:pthread_mutex_destroy + obj:/usr/lib64/libp11-kit.so.0.3.0 + fun:_dl_fini + fun:__run_exit_handlers + fun:exit + fun:(below main) +} + +{ + tfork_atexit_unknown2 + Helgrind:Misc + fun:mutex_destroy_WRK + fun:pthread_mutex_destroy + fun:_dl_fini + fun:__run_exit_handlers + fun:exit + fun:(below main) +} +{ + tfork_pthread_get_specific + Helgrind:Race + fun:tfork_global_get + fun:tfork_create + fun:tfork_thread + fun:mythread_wrapper + fun:start_thread + fun:clone +} diff --git a/lib/util/tests/tfork.c b/lib/util/tests/tfork.c new file mode 100644 index 0000000..70ae975 --- /dev/null +++ b/lib/util/tests/tfork.c @@ -0,0 +1,855 @@ +/* + * Tests for tfork + * + * Copyright Ralph Boehme <slow@samba.org> 2017 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include <talloc.h> +#include <tevent.h> +#include "system/filesys.h" +#include "system/wait.h" +#include "system/select.h" +#include "libcli/util/ntstatus.h" +#include "torture/torture.h" +#include "lib/util/data_blob.h" +#include "torture/local/proto.h" +#include "lib/util/tfork.h" +#include "lib/util/samba_util.h" +#include "lib/util/sys_rw.h" +#ifdef HAVE_PTHREAD +#include <pthread.h> +#endif + +static bool test_tfork_simple(struct torture_context *tctx) +{ + pid_t parent = getpid(); + struct tfork *t = NULL; + pid_t child; + int ret; + + t = tfork_create(); + if (t == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + child = tfork_child_pid(t); + if (child == 0) { + torture_comment(tctx, "my parent pid is %d\n", parent); + torture_assert(tctx, getpid() != parent, "tfork failed\n"); + _exit(0); + } + + ret = tfork_destroy(&t); + torture_assert(tctx, ret == 0, "tfork_destroy failed\n"); + + return true; +} + +static bool test_tfork_status(struct torture_context *tctx) +{ + struct tfork *t = NULL; + int status; + pid_t child; + bool ok = true; + + t = tfork_create(); + if (t == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + child = tfork_child_pid(t); + if (child == 0) { + _exit(123); + } + + status = tfork_status(&t, true); + if (status == -1) { + torture_fail(tctx, "tfork_status failed\n"); + } + + torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done, + "tfork failed\n"); + torture_assert_goto(tctx, WEXITSTATUS(status) == 123, ok, done, + "tfork failed\n"); + + torture_comment(tctx, "exit status [%d]\n", WEXITSTATUS(status)); + +done: + return ok; +} + +static bool test_tfork_sigign(struct torture_context *tctx) +{ + struct tfork *t = NULL; + struct sigaction act; + pid_t child; + int status; + bool ok = true; + int ret; + + act = (struct sigaction) { + .sa_flags = SA_NOCLDWAIT, + .sa_handler = SIG_IGN, + }; + + ret = sigaction(SIGCHLD, &act, NULL); + torture_assert_goto(tctx, ret == 0, ok, done, "sigaction failed\n"); + + t = tfork_create(); + if (t == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + child = tfork_child_pid(t); + if (child == 0) { + sleep(1); + _exit(123); + } + + child = fork(); + if (child == -1) { + torture_fail(tctx, "fork failed\n"); + return false; + } + if (child == 0) { + _exit(0); + } + + status = tfork_status(&t, true); + if (status == -1) { + torture_fail(tctx, "tfork_status failed\n"); + } + + torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done, + "tfork failed\n"); + torture_assert_goto(tctx, WEXITSTATUS(status) == 123, ok, done, + "tfork failed\n"); + torture_comment(tctx, "exit status [%d]\n", WEXITSTATUS(status)); + +done: + return ok; +} + +static void sigchld_handler1(int signum, siginfo_t *si, void *u) +{ + pid_t pid; + int status; + + if (signum != SIGCHLD) { + abort(); + } + + pid = waitpid(si->si_pid, &status, 0); + if (pid != si->si_pid) { + abort(); + } +} + +static bool test_tfork_sighandler(struct torture_context *tctx) +{ + struct tfork *t = NULL; + struct sigaction act; + struct sigaction oldact; + pid_t child; + int status; + bool ok = true; + int ret; + + act = (struct sigaction) { + .sa_flags = SA_SIGINFO, + .sa_sigaction = sigchld_handler1, + }; + + ret = sigaction(SIGCHLD, &act, &oldact); + torture_assert_goto(tctx, ret == 0, ok, done, "sigaction failed\n"); + + t = tfork_create(); + if (t == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + child = tfork_child_pid(t); + if (child == 0) { + sleep(1); + _exit(123); + } + + child = fork(); + if (child == -1) { + torture_fail(tctx, "fork failed\n"); + return false; + } + if (child == 0) { + _exit(0); + } + + status = tfork_status(&t, true); + if (status == -1) { + torture_fail(tctx, "tfork_status failed\n"); + } + + torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done, + "tfork failed\n"); + torture_assert_goto(tctx, WEXITSTATUS(status) == 123, ok, done, + "tfork failed\n"); + torture_comment(tctx, "exit status [%d]\n", WEXITSTATUS(status)); + +done: + sigaction(SIGCHLD, &oldact, NULL); + + return ok; +} + +static bool test_tfork_process_hierarchy(struct torture_context *tctx) +{ + struct tfork *t = NULL; + pid_t pid = getpid(); + pid_t child; + pid_t pgid = getpgid(0); + pid_t sid = getsid(0); + char *procpath = NULL; + int status; + struct stat st; + int ret; + bool ok = true; + + procpath = talloc_asprintf(tctx, "/proc/%d/status", getpid()); + torture_assert_not_null(tctx, procpath, "talloc_asprintf failed\n"); + + ret = stat(procpath, &st); + TALLOC_FREE(procpath); + if (ret != 0) { + if (errno == ENOENT) { + torture_skip(tctx, "/proc missing\n"); + } + torture_fail(tctx, "stat failed\n"); + } + + t = tfork_create(); + if (t == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + child = tfork_child_pid(t); + if (child == 0) { + char *cmd = NULL; + FILE *fp = NULL; + char line[64]; + char *p; + pid_t ppid; + + torture_assert_goto(tctx, pgid == getpgid(0), ok, child_fail, "tfork failed\n"); + torture_assert_goto(tctx, sid == getsid(0), ok, child_fail, "tfork failed\n"); + + cmd = talloc_asprintf(tctx, "cat /proc/%d/status | awk '/^PPid:/ {print $2}'", getppid()); + torture_assert_goto(tctx, cmd != NULL, ok, child_fail, "talloc_asprintf failed\n"); + + fp = popen(cmd, "r"); + torture_assert_goto(tctx, fp != NULL, ok, child_fail, "popen failed\n"); + + p = fgets(line, sizeof(line) - 1, fp); + pclose(fp); + torture_assert_goto(tctx, p != NULL, ok, child_fail, "popen failed\n"); + + ret = sscanf(line, "%d", &ppid); + torture_assert_goto(tctx, ret == 1, ok, child_fail, "sscanf failed\n"); + torture_assert_goto(tctx, ppid == pid, ok, child_fail, "process hierarchy not rooted at caller\n"); + + _exit(0); + + child_fail: + _exit(1); + } + + status = tfork_status(&t, true); + if (status == -1) { + torture_fail(tctx, "tfork_status failed\n"); + } + + torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done, + "tfork failed\n"); + torture_assert_goto(tctx, WEXITSTATUS(status) == 0, ok, done, + "tfork failed\n"); + torture_comment(tctx, "exit status [%d]\n", WEXITSTATUS(status)); + +done: + return ok; +} + +static bool test_tfork_pipe(struct torture_context *tctx) +{ + struct tfork *t = NULL; + int status; + pid_t child; + int up[2]; + int down[2]; + char c; + int ret; + bool ok = true; + + ret = pipe(&up[0]); + torture_assert(tctx, ret == 0, "pipe failed\n"); + + ret = pipe(&down[0]); + torture_assert(tctx, ret == 0, "pipe failed\n"); + + t = tfork_create(); + if (t == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + child = tfork_child_pid(t); + if (child == 0) { + close(up[0]); + close(down[1]); + + ret = read(down[0], &c, 1); + torture_assert_goto(tctx, ret == 1, ok, child_fail, "read failed\n"); + torture_assert_goto(tctx, c == 1, ok, child_fail, "read failed\n"); + + ret = write(up[1], &(char){2}, 1); + torture_assert_goto(tctx, ret == 1, ok, child_fail, "write failed\n"); + + _exit(0); + + child_fail: + _exit(1); + } + + close(up[1]); + close(down[0]); + + ret = write(down[1], &(char){1}, 1); + torture_assert(tctx, ret == 1, "read failed\n"); + + ret = read(up[0], &c, 1); + torture_assert(tctx, ret == 1, "read failed\n"); + torture_assert(tctx, c == 2, "read failed\n"); + + status = tfork_status(&t, true); + if (status == -1) { + torture_fail(tctx, "tfork_status failed\n"); + } + + torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done, + "tfork failed\n"); + torture_assert_goto(tctx, WEXITSTATUS(status) == 0, ok, done, + "tfork failed\n"); +done: + return ok; +} + +static bool test_tfork_twice(struct torture_context *tctx) +{ + struct tfork *t = NULL; + int status; + pid_t child; + pid_t pid; + int up[2]; + int ret; + bool ok = true; + + ret = pipe(&up[0]); + torture_assert(tctx, ret == 0, "pipe failed\n"); + + t = tfork_create(); + if (t == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + child = tfork_child_pid(t); + if (child == 0) { + close(up[0]); + + t = tfork_create(); + if (t == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + child = tfork_child_pid(t); + if (child == 0) { + sleep(1); + pid = getpid(); + ret = write(up[1], &pid, sizeof(pid_t)); + torture_assert_goto(tctx, ret == sizeof(pid_t), ok, child_fail, "write failed\n"); + + _exit(0); + + child_fail: + _exit(1); + } + + _exit(0); + } + + close(up[1]); + + ret = read(up[0], &pid, sizeof(pid_t)); + torture_assert(tctx, ret == sizeof(pid_t), "read failed\n"); + + status = tfork_status(&t, true); + torture_assert_goto(tctx, status != -1, ok, done, "tfork_status failed\n"); + + torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done, + "tfork failed\n"); + torture_assert_goto(tctx, WEXITSTATUS(status) == 0, ok, done, + "tfork failed\n"); +done: + return ok; +} + +static void *tfork_thread(void *p) +{ + struct tfork *t = NULL; + int status; + pid_t child; + uint64_t tid = (uint64_t)pthread_self(); + uint64_t *result = NULL; + int up[2]; + ssize_t nread; + int ret; + + ret = pipe(up); + if (ret != 0) { + pthread_exit(NULL); + } + + t = tfork_create(); + if (t == NULL) { + pthread_exit(NULL); + } + child = tfork_child_pid(t); + if (child == 0) { + ssize_t nwritten; + + close(up[0]); + tid++; + nwritten = sys_write(up[1], &tid, sizeof(uint64_t)); + if (nwritten != sizeof(uint64_t)) { + _exit(1); + } + _exit(0); + } + close(up[1]); + + result = malloc(sizeof(uint64_t)); + if (result == NULL) { + pthread_exit(NULL); + } + + nread = sys_read(up[0], result, sizeof(uint64_t)); + if (nread != sizeof(uint64_t)) { + pthread_exit(NULL); + } + + status = tfork_status(&t, true); + if (status == -1) { + pthread_exit(NULL); + } + + pthread_exit(result); +} + +static bool test_tfork_threads(struct torture_context *tctx) +{ + int ret; + bool ok = true; + const int num_threads = 64; + pthread_t threads[num_threads]; + sigset_t set; + int i; + +#ifndef HAVE_PTHREAD + torture_skip(tctx, "no pthread support\n"); +#endif + + /* + * Be nasty and taste for the worst case: ensure all threads start with + * SIGCHLD unblocked so we have the most fun with SIGCHLD being + * delivered to a random thread. :) + */ + sigemptyset(&set); + sigaddset(&set, SIGCHLD); +#ifdef HAVE_PTHREAD + ret = pthread_sigmask(SIG_UNBLOCK, &set, NULL); +#else + ret = sigprocmask(SIG_UNBLOCK, &set, NULL); +#endif + if (ret != 0) { + return false; + } + + for (i = 0; i < num_threads; i++) { + ret = pthread_create(&threads[i], NULL, tfork_thread, NULL); + torture_assert_goto(tctx, ret == 0, ok, done, + "pthread_create failed\n"); + } + + for (i = 0; i < num_threads; i++) { + void *p; + uint64_t *result; + + ret = pthread_join(threads[i], &p); + torture_assert_goto(tctx, ret == 0, ok, done, + "pthread_join failed\n"); + result = (uint64_t *)p; + torture_assert_goto(tctx, *result == (uint64_t)threads[i] + 1, + ok, done, "thread failed\n"); + free(p); + } + +done: + return ok; +} + +static bool test_tfork_cmd_send(struct torture_context *tctx) +{ + struct tevent_context *ev = NULL; + struct tevent_req *req = NULL; + const char *cmd[2] = { NULL, NULL }; + bool ok = true; + + ev = tevent_context_init(tctx); + torture_assert_goto(tctx, ev != NULL, ok, done, + "tevent_context_init failed\n"); + + cmd[0] = talloc_asprintf(tctx, "%s/testprogs/blackbox/tfork.sh", SRCDIR); + torture_assert_goto(tctx, cmd[0] != NULL, ok, done, + "talloc_asprintf failed\n"); + + req = samba_runcmd_send(tctx, ev, timeval_zero(), 0, 0, + cmd, "foo", NULL); + torture_assert_goto(tctx, req != NULL, ok, done, + "samba_runcmd_send failed\n"); + + ok = tevent_req_poll(req, ev); + torture_assert_goto(tctx, ok, ok, done, "tevent_req_poll failed\n"); + + torture_comment(tctx, "samba_runcmd_send test finished\n"); + +done: + TALLOC_FREE(ev); + + return ok; +} + +/* + * Test to ensure that the event_fd becomes readable after + * a tfork_process terminates. + */ +static bool test_tfork_event_file_handle(struct torture_context *tctx) +{ + bool ok = true; + + struct tfork *t1 = NULL; + pid_t child1; + struct pollfd poll1[] = { + { + .fd = -1, + .events = POLLIN, + }, + }; + + struct tfork *t2 = NULL; + pid_t child2; + struct pollfd poll2[] = { + { + .fd = -1, + .events = POLLIN, + }, + }; + + + t1 = tfork_create(); + if (t1 == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + + child1 = tfork_child_pid(t1); + if (child1 == 0) { + /* + * Parent process will kill this with a SIGTERM + * so 10 seconds should be plenty + */ + sleep(10); + exit(1); + } + poll1[0].fd = tfork_event_fd(t1); + + t2 = tfork_create(); + if (t2 == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + child2 = tfork_child_pid(t2); + if (child2 == 0) { + /* + * Parent process will kill this with a SIGTERM + * so 10 seconds should be plenty + */ + sleep(10); + exit(2); + } + poll2[0].fd = tfork_event_fd(t2); + + /* + * Have forked two process and are in the master process + * Expect that both event_fds are unreadable + */ + poll(poll1, 1, 0); + ok = !(poll1[0].revents & POLLIN); + torture_assert_goto(tctx, ok, ok, done, + "tfork process 1 event fd readable\n"); + poll(poll2, 1, 0); + ok = !(poll2[0].revents & POLLIN); + torture_assert_goto(tctx, ok, ok, done, + "tfork process 1 event fd readable\n"); + + /* Kill the first child process */ + kill(child1, SIGKILL); + sleep(1); + + /* + * Have killed the first child, so expect it's event_fd to have gone + * readable. + * + */ + poll(poll1, 1, 0); + ok = (poll1[0].revents & POLLIN); + torture_assert_goto(tctx, ok, ok, done, + "tfork process 1 event fd not readable\n"); + poll(poll2, 1, 0); + ok = !(poll2[0].revents & POLLIN); + torture_assert_goto(tctx, ok, ok, done, + "tfork process 2 event fd readable\n"); + + /* Kill the secind child process */ + kill(child2, SIGKILL); + sleep(1); + /* + * Have killed the children, so expect their event_fd's to have gone + * readable. + * + */ + poll(poll1, 1, 0); + ok = (poll1[0].revents & POLLIN); + torture_assert_goto(tctx, ok, ok, done, + "tfork process 1 event fd not readable\n"); + poll(poll2, 1, 0); + ok = (poll2[0].revents & POLLIN); + torture_assert_goto(tctx, ok, ok, done, + "tfork process 2 event fd not readable\n"); + +done: + free(t1); + free(t2); + + return ok; +} + +/* + * Test to ensure that the status calls behave as expected after a process + * terminates. + * + * As the parent process owns the status fd's they get passed to all + * subsequent children after a tfork. So it's possible for another + * child process to hold the status pipe open. + * + * The event fd needs to be left open by tfork, as a close in the status + * code can cause issues in tevent code. + * + */ +static bool test_tfork_status_handle(struct torture_context *tctx) +{ + bool ok = true; + + struct tfork *t1 = NULL; + pid_t child1; + + struct tfork *t2 = NULL; + pid_t child2; + + int status; + int fd; + int ev1_fd; + int ev2_fd; + + + t1 = tfork_create(); + if (t1 == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + + child1 = tfork_child_pid(t1); + if (child1 == 0) { + /* + * Parent process will kill this with a SIGTERM + * so 10 seconds should be plenty + */ + sleep(10); + exit(1); + } + ev1_fd = tfork_event_fd(t1); + + t2 = tfork_create(); + if (t2 == NULL) { + torture_fail(tctx, "tfork failed\n"); + return false; + } + child2 = tfork_child_pid(t2); + if (child2 == 0) { + /* + * Parent process will kill this with a SIGTERM + * so 10 seconds should be plenty + */ + sleep(10); + exit(2); + } + ev2_fd = tfork_event_fd(t2); + + /* + * Have forked two process and are in the master process + * expect that the status call will block, and hence return -1 + * as the processes are still running + * The event fd's should be open. + */ + status = tfork_status(&t1, false); + ok = status == -1; + torture_assert_goto(tctx, ok, ok, done, + "tfork status available for non terminated " + "process 1\n"); + /* Is the event fd open? */ + fd = dup(ev1_fd); + ok = fd != -1; + torture_assert_goto(tctx, ok, ok, done, + "tfork process 1 event fd is not open"); + + status = tfork_status(&t2, false); + ok = status == -1; + torture_assert_goto(tctx, ok, ok, done, + "tfork status available for non terminated " + "process 2\n"); + /* Is the event fd open? */ + fd = dup(ev2_fd); + ok = fd != -1; + torture_assert_goto(tctx, ok, ok, done, + "tfork process 2 event fd is not open"); + + /* + * Kill the first process, it's status should be readable + * and it's event_fd should be open + * The second process's status should be unreadable. + */ + kill(child1, SIGTERM); + sleep(1); + status = tfork_status(&t1, false); + ok = status != -1; + torture_assert_goto(tctx, ok, ok, done, + "tfork status for child 1 not available after " + "termination\n"); + /* Is the event fd open? */ + fd = dup(ev2_fd); + ok = fd != -1; + torture_assert_goto(tctx, ok, ok, done, + "tfork process 1 event fd is not open"); + + status = tfork_status(&t2, false); + ok = status == -1; + torture_assert_goto(tctx, ok, ok, done, + "tfork status available for child 2 after " + "termination of child 1\n"); + + /* + * Kill the second process, it's status should be readable + */ + kill(child2, SIGTERM); + sleep(1); + status = tfork_status(&t2, false); + ok = status != -1; + torture_assert_goto(tctx, ok, ok, done, + "tfork status for child 2 not available after " + "termination\n"); + + /* Check that the event fd's are still open */ + /* Is the event fd open? */ + fd = dup(ev1_fd); + ok = fd != -1; + torture_assert_goto(tctx, ok, ok, done, + "tfork process 1 event fd is not open"); + /* Is the event fd open? */ + fd = dup(ev2_fd); + ok = fd != -1; + torture_assert_goto(tctx, ok, ok, done, + "tfork process 2 event fd is not open"); + +done: + return ok; +} + +struct torture_suite *torture_local_tfork(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = + torture_suite_create(mem_ctx, "tfork"); + + torture_suite_add_simple_test(suite, + "tfork_simple", + test_tfork_simple); + + torture_suite_add_simple_test(suite, + "tfork_status", + test_tfork_status); + + torture_suite_add_simple_test(suite, + "tfork_sigign", + test_tfork_sigign); + + torture_suite_add_simple_test(suite, + "tfork_sighandler", + test_tfork_sighandler); + + torture_suite_add_simple_test(suite, + "tfork_process_hierarchy", + test_tfork_process_hierarchy); + + torture_suite_add_simple_test(suite, + "tfork_pipe", + test_tfork_pipe); + + torture_suite_add_simple_test(suite, + "tfork_twice", + test_tfork_twice); + + torture_suite_add_simple_test(suite, + "tfork_threads", + test_tfork_threads); + + torture_suite_add_simple_test(suite, + "tfork_cmd_send", + test_tfork_cmd_send); + + torture_suite_add_simple_test(suite, + "tfork_event_file_handle", + test_tfork_event_file_handle); + + torture_suite_add_simple_test(suite, + "tfork_status_handle", + test_tfork_status_handle); + + return suite; +} diff --git a/lib/util/tests/time.c b/lib/util/tests/time.c new file mode 100644 index 0000000..ec27f56 --- /dev/null +++ b/lib/util/tests/time.c @@ -0,0 +1,151 @@ +/* + Unix SMB/CIFS implementation. + + util time testing + + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "torture/local/proto.h" + +static bool test_null_time(struct torture_context *tctx) +{ + torture_assert(tctx, null_time(0), "0"); + torture_assert(tctx, null_time(0xFFFFFFFF), "0xFFFFFFFF"); + torture_assert(tctx, null_time(-1), "-1"); + torture_assert(tctx, !null_time(42), "42"); + return true; +} + +static bool test_null_nttime(struct torture_context *tctx) +{ + torture_assert(tctx, null_nttime(0), "0"); + torture_assert(tctx, !null_nttime(NTTIME_FREEZE), "-1"); + torture_assert(tctx, !null_nttime(NTTIME_THAW), "-2"); + torture_assert(tctx, !null_nttime(42), "42"); + return true; +} + + +static bool test_http_timestring(struct torture_context *tctx) +{ + const char *start = "Thu, 01 Jan 1970"; + char *result; + /* + * Correct test for negative UTC offset. Without the correction, the + * test fails when run on hosts with negative UTC offsets, as the date + * returned is back in 1969 (pre-epoch). + */ + time_t now = time(NULL); + struct tm local = *localtime(&now); + struct tm gmt = *gmtime(&now); + time_t utc_offset = mktime(&local) - mktime(&gmt); + + result = http_timestring(tctx, 42 - (utc_offset < 0 ? utc_offset : 0)); + torture_assert(tctx, !strncmp(start, result, + strlen(start)), result); + torture_assert_str_equal(tctx, "never", + http_timestring(tctx, get_time_t_max()), "42"); + return true; +} + +static bool test_timestring(struct torture_context *tctx) +{ + const char *start = "Thu Jan 1"; + char *result; + /* + * Correct test for negative UTC offset. Without the correction, the + * test fails when run on hosts with negative UTC offsets, as the date + * returned is back in 1969 (pre-epoch). + */ + time_t now = time(NULL); + struct tm local = *localtime(&now); + struct tm gmt = *gmtime(&now); + time_t utc_offset = mktime(&local) - mktime(&gmt); + + result = timestring(tctx, 42 - (utc_offset < 0 ? utc_offset : 0)); + torture_assert(tctx, !strncmp(start, result, strlen(start)), result); + return true; +} + +static bool test_normalize_timespec(struct torture_context *tctx) +{ + const struct { + time_t in_s; long in_ns; + time_t out_s; long out_ns; + } data [] = { + { 0, 0, 0, 0 } + , { 1, 0, 1, 0 } + , { -1, 0, -1, 0 } + , { 0, 1000000000, 1, 0 } + , { 0, 2000000000, 2, 0 } + , { 0, 1000000001, 1, 1 } + , { 0, 2000000001, 2, 1 } + , { 0, -1000000000, -1, 0 } + , { 0, -2000000000, -2, 0 } + , { 0, -1000000001, -2, 999999999 } + , { 0, -2000000001, -3, 999999999 } + , { 0, -1, -1, 999999999 } + , { 1, -1, 0, 999999999 } + , { -1, -1, -2, 999999999 } + , { 0, 999999999, 0, 999999999 } + , { 0, 1999999999, 1, 999999999 } + , { 0, 2999999999, 2, 999999999 } + , { 0, -999999999, -1, 1 } + , { 0, -1999999999, -2, 1 } + , { 0, -2999999999, -3, 1 } + , { LONG_MAX, 1000000001, LONG_MAX, 999999999 } /* overflow */ + , { LONG_MAX, 999999999, LONG_MAX, 999999999 } /* harmless */ + , { LONG_MAX, -1, LONG_MAX-1, 999999999 } /* -1 */ + , { LONG_MIN, -1000000001, LONG_MIN, 0 } /* overflow */ + , { LONG_MIN, 0, LONG_MIN, 0 } /* harmless */ + , { LONG_MIN, 1000000000, LONG_MIN+1, 0 } /* +1 */ + }; + int i; + + for (i = 0; i < sizeof(data) / sizeof(data[0]); ++i) { + struct timespec ts = (struct timespec) + { .tv_sec = data[i].in_s + , .tv_nsec = data[i].in_ns }; + + normalize_timespec(&ts); + + torture_assert_int_equal(tctx, ts.tv_sec, data[i].out_s, + "mismatch in tv_sec"); + torture_assert_int_equal(tctx, ts.tv_nsec, data[i].out_ns, + "mismatch in tv_nsec"); + } + + return true; +} + +struct torture_suite *torture_local_util_time(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "time"); + + torture_suite_add_simple_test(suite, "null_time", test_null_time); + torture_suite_add_simple_test(suite, "null_nttime", test_null_nttime); + torture_suite_add_simple_test(suite, "http_timestring", + test_http_timestring); + torture_suite_add_simple_test(suite, "timestring", + test_timestring); + torture_suite_add_simple_test(suite, "normalize_timespec", + test_normalize_timespec); + + return suite; +} diff --git a/lib/util/tests/util.c b/lib/util/tests/util.c new file mode 100644 index 0000000..0b69e21 --- /dev/null +++ b/lib/util/tests/util.c @@ -0,0 +1,652 @@ +/* + * Tests for strv_util + * + * Copyright Martin Schwenke <martin@meltin.net> 2016 + * Copyright Christof Schmitt <cs@samba.org> 2018 + * Copyright Swen Schillig <swen@linux.ibm.com> 2019 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <talloc.h> + +#include "replace.h" +#include "system/filesys.h" + +#include "libcli/util/ntstatus.h" +#include "torture/torture.h" +#include "lib/util/data_blob.h" +#include "torture/local/proto.h" + +#include "lib/util/samba_util.h" +#include "lib/util/smb_strtox.h" + +#include "limits.h" +#include "string.h" + +struct test_trim_string_data { + const char *desc; + const char *in; + const char *front; + const char *back; + const char *out; + bool ret; +}; + +static const struct test_trim_string_data test_trim_string_data[] = { + { + .desc = "All NULL", + .in = NULL, + .front = NULL, + .back = NULL, + .out = NULL, + .ret = false, + }, + { + .desc = "Input NULL", + .in = NULL, + .front = "abc", + .back = "123", + .out = NULL, + .ret = false, + }, + { + .desc = "Trim NULL", + .in = "abc", + .front = NULL, + .back = NULL, + .out = "abc", + .ret = false, + }, + { + .desc = "Trim empty", + .in = "abc", + .front = "", + .back = "", + .out = "abc", + .ret = false, + }, + { + .desc = "Trim front, non-matching", + .in = "abc", + .front = "x", + .back = "", + .out = "abc", + .ret = false, + }, + { + .desc = "Trim front, matches back", + .in = "abc", + .front = "c", + .back = "", + .out = "abc", + .ret = false, + }, + { + .desc = "Trim front, partial-match", + .in = "abc", + .front = "ac", + .back = "", + .out = "abc", + .ret = false, + }, + { + .desc = "Trim front, too long", + .in = "aaa", + .front = "aaaa", + .back = "", + .out = "aaa", + .ret = false, + }, + { + .desc = "Trim front, 1 char, 1x", + .in = "abc", + .front = "a", + .back = "", + .out = "bc", + .ret = true, + }, + { + .desc = "Trim front, 1 char, 2x", + .in = "aabc", + .front = "a", + .back = "", + .out = "bc", + .ret = true, + }, + { + .desc = "Trim front, 1 char, 3x", + .in = "aaabc", + .front = "a", + .back = "", + .out = "bc", + .ret = true, + }, + { + .desc = "Trim front, 1 char, matches all", + .in = "aaa", + .front = "a", + .back = "", + .out = "", + .ret = true, + }, + { + .desc = "Trim front, 2 chars, 1x", + .in = "abc", + .front = "ab", + .back = "", + .out = "c", + .ret = true, + }, + { + .desc = "Trim front, 2 chars, 2x", + .in = "ababc", + .front = "ab", + .back = "", + .out = "c", + .ret = true, + }, + { + .desc = "Trim front, 3 chars, matches all", + .in = "abc", + .front = "abc", + .back = "", + .out = "", + .ret = true, + }, + { + .desc = "Trim back, non-matching", + .in = "abc", + .front = "", + .back = "x", + .out = "abc", + .ret = false, + }, + { + .desc = "Trim back, matches front", + .in = "abc", + .front = "", + .back = "a", + .out = "abc", + .ret = false, + }, + { + .desc = "Trim back, partial-match", + .in = "abc", + .front = "", + .back = "xc", + .out = "abc", + .ret = false, + }, + { + .desc = "Trim back, too long", + .in = "aaa", + .front = "", + .back = "aaaa", + .out = "aaa", + .ret = false, + }, + { + .desc = "Trim back, 1 char, 1x", + .in = "abc", + .front = "", + .back = "c", + .out = "ab", + .ret = true, + }, + { + .desc = "Trim back, 1 char, 2x", + .in = "abcc", + .front = "", + .back = "c", + .out = "ab", + .ret = true, + }, + { + .desc = "Trim back, 1 char, 3x", + .in = "abccc", + .front = "", + .back = "c", + .out = "ab", + .ret = true, + }, + { + .desc = "Trim back, 1 char, matches all", + .in = "aaa", + .front = "", + .back = "a", + .out = "", + .ret = true, + }, + { + .desc = "Trim back, 2 chars, 1x", + .in = "abc", + .front = "", + .back = "bc", + .out = "a", + .ret = true, + }, + { + .desc = "Trim back, 2 chars, 2x", + .in = "abcbc", + .front = "", + .back = "bc", + .out = "a", + .ret = true, + }, + { + .desc = "Trim back, 3 chars, matches all", + .in = "abc", + .front = "", + .back = "abc", + .out = "", + .ret = true, + }, + { + .desc = "Trim both, non-matching", + .in = "abc", + .front = "x", + .back = "y", + .out = "abc", + .ret = false, + }, + { + .desc = "Trim both, reversed", + .in = "abc", + .front = "c", + .back = "a", + .out = "abc", + .ret = false, + }, + { + .desc = "Trim both, 1 char, 1x", + .in = "abc", + .front = "a", + .back = "c", + .out = "b", + .ret = true, + }, + { + .desc = "Trim both, 1 char, 2x", + .in = "aabcc", + .front = "a", + .back = "c", + .out = "b", + .ret = true, + }, + { + .desc = "Trim both, 1 char, 3x", + .in = "aaabccc", + .front = "a", + .back = "c", + .out = "b", + .ret = true, + }, + { + .desc = "Trim both, 1 char, matches all", + .in = "aaabbb", + .front = "a", + .back = "b", + .out = "", + .ret = true, + }, + { + .desc = "Trim both, 2 chars, 1x", + .in = "abxbc", + .front = "ab", + .back = "bc", + .out = "x", + .ret = true, + }, + { + .desc = "Trim both, 2 chars, 2x", + .in = "ababxyzbcbc", + .front = "ab", + .back = "bc", + .out = "xyz", + .ret = true, + }, + { + .desc = "Trim both, 2 chars, front matches, back doesn't", + .in = "abcde", + .front = "ab", + .back = "xy", + .out = "cde", + .ret = true, + }, + { + .desc = "Trim both, 2 chars, back matches, front doesn't", + .in = "abcde", + .front = "xy", + .back = "de", + .out = "abc", + .ret = true, + }, + { + .desc = "Trim back, 3 chars, matches all", + .in = "abcxyz", + .front = "abc", + .back = "xyz", + .out = "", + .ret = true, + }, +}; + +static bool test_trim_string(struct torture_context *tctx) +{ + int j; + for (j = 0; j < ARRAY_SIZE(test_trim_string_data); j++) { + bool ret; + const struct test_trim_string_data *d = + &test_trim_string_data[j]; + char *str = talloc_strdup(tctx, d->in); + torture_assert(tctx, d->in == NULL || str != NULL, + "Out of memory"); + + torture_comment(tctx, "%s\n", d->desc); + ret = trim_string(str, d->front, d->back); + torture_assert(tctx, ret == d->ret, + "Incorrect return from trim_string()"); + if (d->out == NULL) { + torture_assert(tctx, str == NULL, "Expected NULL"); + } else { + torture_assert(tctx, str != NULL, "Expected non-NULL"); + torture_assert_str_equal(tctx, str, d->out, + "Incorrect output"); + } + TALLOC_FREE(str); + } + + return true; +} + +static bool test_directory_create_or_exist(struct torture_context *tctx) +{ + char *path = NULL, *new_path = NULL, *file_path = NULL; + bool ret = true, b = true; + int fd; + NTSTATUS status; + const mode_t perms = 0741; + + status = torture_temp_dir(tctx, "util_dir", &path);; + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "Creating test directory failed.\n"); + + b = directory_create_or_exist(path, perms); + torture_assert_goto(tctx, b == true, ret, done, + "directory_create_or_exist on " + "existing directory failed.\n"); + + new_path = talloc_asprintf(tctx, "%s/%s", path, "dir"); + torture_assert_goto(tctx, new_path != NULL, ret, done, + "Could not allocate memory for directory path\n"); + + b = directory_exist(new_path); + torture_assert_goto(tctx, b == false, ret, done, + "Check for non-existing directory failed.\n"); + + b = directory_create_or_exist(new_path, perms); + torture_assert_goto(tctx, b == true, ret, done, + "directory_create_or_exist for " + "new directory failed.\n"); + + b = directory_exist(new_path); + torture_assert_goto(tctx, b == true, ret, done, + "Check for existing directory failed.\n"); + + b = file_check_permissions(new_path, geteuid(), perms, NULL); + torture_assert_goto(tctx, b == true, ret, done, + "Permission check for directory failed.\n"); + + file_path = talloc_asprintf(tctx, "%s/%s", path, "file"); + torture_assert_goto(tctx, file_path != NULL, ret, done, + "Could not allocate memory for file path\n"); + fd = creat(file_path, perms); + torture_assert_goto(tctx, fd != -1, ret, done, + "Creating file failed.\n"); + close(fd); + + b = directory_create_or_exist(file_path, perms); + torture_assert_goto(tctx, b == false, ret, done, + "directory_create_or_exist for " + "existing file failed.\n"); + +done: + return ret; +} + +static bool test_mem_equal_const_time(struct torture_context *tctx) +{ + const char *test_string = "abcdabcd"; + + torture_assert(tctx, mem_equal_const_time("", "", 0), + "zero-length comparison failed"); + + torture_assert(tctx, mem_equal_const_time(test_string, test_string, 8), + "comparison with equal pointers failed"); + + torture_assert(tctx, mem_equal_const_time(test_string, test_string + 4, 4), + "comparison with non-equal pointers failed"); + + torture_assert(tctx, !mem_equal_const_time("abcd", "efgh", 4), + "comparison with different values failed"); + + return true; +} + +static bool test_smb_strtoul_errno_check(struct torture_context *tctx) +{ + const char *number = "123"; + unsigned long int val = 0; + unsigned long long int vall = 0; + int err; + + /* select an error code which is not set by the smb_strtoul routines */ + errno = EAGAIN; + err = EAGAIN; + val = smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD); + torture_assert(tctx, errno == EAGAIN, "smb_strtoul: Expected EAGAIN"); + torture_assert(tctx, err == 0, "smb_strtoul: Expected err = 0"); + torture_assert(tctx, val == 123, "smb_strtoul: Expected value 123"); + + /* set err to an impossible value again before continuing */ + err = EAGAIN; + vall = smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD); + torture_assert(tctx, errno == EAGAIN, "smb_strtoull: Expected EAGAIN"); + torture_assert(tctx, err == 0, "smb_strtoul: Expected err = 0"); + torture_assert(tctx, vall == 123, "smb_strtoul: Expected value 123"); + + return true; +} + +static bool test_smb_strtoul_negative(struct torture_context *tctx) +{ + const char *number = "-132"; + const char *number2 = "132-"; + unsigned long int val = 0; + unsigned long long int vall = 0; + int err; + + err = 0; + smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD); + torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL"); + + err = 0; + smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD); + torture_assert(tctx, err == EINVAL, "smb_strtoull: Expected EINVAL"); + + /* it is allowed to have a "-" sign after a number, + * e.g. as part of a formular, however, it is not supposed to + * have an effect on the converted value. + */ + + err = 0; + val = smb_strtoul(number2, NULL, 0, &err, SMB_STR_STANDARD); + torture_assert(tctx, err == 0, "smb_strtoul: Expected no error"); + torture_assert(tctx, val == 132, "smb_strtoul: Wrong value"); + + err = 0; + vall = smb_strtoull(number2, NULL, 0, &err, SMB_STR_STANDARD); + torture_assert(tctx, err == 0, "smb_strtoull: Expected no error"); + torture_assert(tctx, vall == 132, "smb_strtoull: Wrong value"); + + return true; +} + +static bool test_smb_strtoul_no_number(struct torture_context *tctx) +{ + const char *number = "ghijk"; + const char *blank = ""; + int err; + + err = 0; + smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD); + torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL"); + + err = 0; + smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD); + torture_assert(tctx, err == EINVAL, "smb_strtoull: Expected EINVAL"); + + err = 0; + smb_strtoul(blank, NULL, 0, &err, SMB_STR_STANDARD); + torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL"); + + err = 0; + smb_strtoull(blank, NULL, 0, &err, SMB_STR_STANDARD); + torture_assert(tctx, err == EINVAL, "smb_strtoull: Expected EINVAL"); + + return true; +} + +static bool test_smb_strtoul_allow_negative(struct torture_context *tctx) +{ + const char *number = "-1"; + const char *number2 = "-1-1"; + unsigned long res = 0; + unsigned long long res2 = 0; + char *end_ptr = NULL; + int err; + + err = 0; + res = smb_strtoul(number, NULL, 0, &err, SMB_STR_ALLOW_NEGATIVE); + torture_assert(tctx, err == 0, "strtoul_err: Unexpected error"); + torture_assert(tctx, res == ULONG_MAX, "strtoul_err: Unexpected value"); + + err = 0; + res2 = smb_strtoull(number, NULL, 0, &err, SMB_STR_ALLOW_NEGATIVE); + torture_assert(tctx, err == 0, "strtoull_err: Unexpected error"); + torture_assert(tctx, res2 == ULLONG_MAX, "strtoull_err: Unexpected value"); + + err = 0; + smb_strtoul(number2, &end_ptr, 0, &err, SMB_STR_ALLOW_NEGATIVE); + torture_assert(tctx, err == 0, "strtoul_err: Unexpected error"); + torture_assert(tctx, end_ptr[0] == '-', "strtoul_err: Unexpected end pointer"); + + err = 0; + smb_strtoull(number2, &end_ptr, 0, &err, SMB_STR_ALLOW_NEGATIVE); + torture_assert(tctx, err == 0, "strtoull_err: Unexpected error"); + torture_assert(tctx, end_ptr[0] == '-', "strtoull_err: Unexpected end pointer"); + + return true; +} + +static bool test_smb_strtoul_full_string(struct torture_context *tctx) +{ + const char *number = "123 "; + const char *number2 = "123"; + int err; + + err = 0; + smb_strtoul(number, NULL, 0, &err, SMB_STR_FULL_STR_CONV); + torture_assert(tctx, err == EINVAL, "strtoul_err: Expected EINVAL"); + + err = 0; + smb_strtoull(number, NULL, 0, &err, SMB_STR_FULL_STR_CONV); + torture_assert(tctx, err == EINVAL, "strtoull_err: Expected EINVAL"); + + err = 0; + smb_strtoul(number2, NULL, 0, &err, SMB_STR_FULL_STR_CONV); + torture_assert(tctx, err == 0, "strtoul_err: Unexpected error"); + + err = 0; + smb_strtoull(number2, NULL, 0, &err, SMB_STR_FULL_STR_CONV); + torture_assert(tctx, err == 0, "strtoull_err: Unexpected error"); + + return true; +} + +static bool test_smb_strtoul_allow_no_conversion(struct torture_context *tctx) +{ + const char *number = ""; + const char *number2 = "xyz"; + unsigned long int n1 = 0; + unsigned long long int n2 = 0; + int err; + + err = 0; + smb_strtoul(number, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION); + torture_assert(tctx, err == 0, "strtoul_err: Unexpected error"); + torture_assert(tctx, n1 == 0, "strtoul_err: Unexpected value"); + + err = 0; + smb_strtoull(number, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION); + torture_assert(tctx, err == 0, "strtoull_err: Unexpected error"); + torture_assert(tctx, n2 == 0, "strtoull_err: Unexpected value"); + + err = 0; + smb_strtoul(number2, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION); + torture_assert(tctx, err == 0, "strtoul_err: Unexpected error"); + torture_assert(tctx, n1 == 0, "strtoul_err: Unexpected value"); + + err = 0; + smb_strtoull(number2, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION); + torture_assert(tctx, err == 0, "strtoull_err: Unexpected error"); + torture_assert(tctx, n2 == 0, "strtoull_err: Unexpected value"); + + return true; +} +struct torture_suite *torture_local_util(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = + torture_suite_create(mem_ctx, "util"); + + torture_suite_add_simple_test(suite, + "trim_string", + test_trim_string); + torture_suite_add_simple_test(suite, + "directory_create_or_exist", + test_directory_create_or_exist); + torture_suite_add_simple_test(suite, + "mem_equal_const_time", + test_mem_equal_const_time); + torture_suite_add_simple_test(suite, + "smb_strtoul(l) errno", + test_smb_strtoul_errno_check); + torture_suite_add_simple_test(suite, + "smb_strtoul(l) negative", + test_smb_strtoul_negative); + torture_suite_add_simple_test(suite, + "smb_strtoul(l) no number", + test_smb_strtoul_no_number); + torture_suite_add_simple_test(suite, + "smb_strtoul(l) allow_negative", + test_smb_strtoul_allow_negative); + torture_suite_add_simple_test(suite, + "smb_strtoul(l) full string conversion", + test_smb_strtoul_full_string); + torture_suite_add_simple_test(suite, + "smb_strtoul(l) allow no conversion", + test_smb_strtoul_allow_no_conversion); + return suite; +} diff --git a/lib/util/tests/util_str_escape.c b/lib/util/tests/util_str_escape.c new file mode 100644 index 0000000..82e2209 --- /dev/null +++ b/lib/util/tests/util_str_escape.c @@ -0,0 +1,90 @@ +/* + + util_str_escape testing + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "torture/local/proto.h" +#include "lib/util/util_str_escape.h" + +static bool test_log_escape_empty_string(struct torture_context *tctx) +{ + char *result = log_escape( tctx, ""); + torture_assert_str_equal(tctx, result, "", "Empty string handling"); + return true; +} + +static bool test_log_escape_null_string(struct torture_context *tctx) +{ + char *result = log_escape( tctx, NULL); + torture_assert(tctx, (result == NULL), "Empty string handling"); + return true; +} + +static bool test_log_escape_plain_string(struct torture_context *tctx) +{ + const char *input = "a plain string with no escapable characters"; + const char *expected = "a plain string with no escapable characters"; + + char *result = log_escape( tctx, input); + torture_assert_str_equal(tctx, result, expected, + "Plain string handling"); + return true; +} + +static bool test_log_escape_string(struct torture_context *tctx) +{ + const char *input = "\a\b\f\n\r\t\v\\\x01"; + const char *expected = "\\a\\b\\f\\n\\r\\t\\v\\\\\\x01"; + + char *result = log_escape( tctx, input); + torture_assert_str_equal(tctx, result, expected, + "Escapable characters in string"); + return true; +} + +static bool test_log_escape_hex_string(struct torture_context *tctx) +{ + const char *input = "\x01\x1F "; + const char *expected = "\\x01\\x1F "; + + char *result = log_escape( tctx, input); + torture_assert_str_equal(tctx, result, expected, + "hex escaping"); + return true; +} +struct torture_suite *torture_local_util_str_escape(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, + "util_str_escape"); + + torture_suite_add_simple_test(suite, "log_escape_empty_string", + test_log_escape_empty_string); + torture_suite_add_simple_test(suite, "log_escape_null_string", + test_log_escape_null_string); + torture_suite_add_simple_test(suite, "log_escape_plain_string", + test_log_escape_plain_string); + torture_suite_add_simple_test(suite, "log_escape_string", + test_log_escape_string); + torture_suite_add_simple_test(suite, "log_escape_hex_string", + test_log_escape_hex_string); + + + return suite; +} diff --git a/lib/util/tevent_debug.c b/lib/util/tevent_debug.c new file mode 100644 index 0000000..4ec9057 --- /dev/null +++ b/lib/util/tevent_debug.c @@ -0,0 +1,116 @@ +/* + Unix SMB/CIFS implementation. + Copyright (C) Andrew Tridgell 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include <tevent.h> + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_TEVENT + +static void samba_tevent_debug(void *context, + enum tevent_debug_level level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0); + +static void samba_tevent_debug(void *context, + enum tevent_debug_level level, + const char *fmt, + va_list ap) +{ + int samba_level = -1; + + switch (level) { + case TEVENT_DEBUG_FATAL: + samba_level = 0; + break; + case TEVENT_DEBUG_ERROR: + samba_level = 1; + break; + case TEVENT_DEBUG_WARNING: + samba_level = 2; + break; + case TEVENT_DEBUG_TRACE: + samba_level = 50; + break; + }; + + if (CHECK_DEBUGLVL(samba_level)) { + const char *name = (const char *)context; + char *message = NULL; + int ret; + + ret = vasprintf(&message, fmt, ap); + if (ret == -1) { + return; + } + + if (name == NULL) { + name = "samba_tevent"; + } + + DEBUG(samba_level, ("%s: %s", name, message)); + free(message); + } +} + +static void samba_tevent_abort_fn(const char *reason) +{ + smb_panic(reason); +} + +static void samba_tevent_setup_abort_fn(void) +{ + static bool abort_fn_done; + + if (!abort_fn_done) { + tevent_set_abort_fn(samba_tevent_abort_fn); + abort_fn_done = true; + } +} + +void samba_tevent_set_debug(struct tevent_context *ev, const char *name) +{ + void *p = discard_const(name); + samba_tevent_setup_abort_fn(); + tevent_set_debug(ev, samba_tevent_debug, p); + + /* these values should match samba_tevent_debug() */ + if (CHECK_DEBUGLVL(50)) { + tevent_set_max_debug_level(ev, TEVENT_DEBUG_TRACE); + } else if (CHECK_DEBUGLVL(2)) { + tevent_set_max_debug_level(ev, TEVENT_DEBUG_WARNING); + } else if (CHECK_DEBUGLVL(1)) { + tevent_set_max_debug_level(ev, TEVENT_DEBUG_ERROR); + } else { + tevent_set_max_debug_level(ev, TEVENT_DEBUG_FATAL); + } +} + +struct tevent_context *samba_tevent_context_init(TALLOC_CTX *mem_ctx) +{ + struct tevent_context *ev; + + samba_tevent_setup_abort_fn(); + + ev = tevent_context_init(mem_ctx); + if (ev) { + samba_tevent_set_debug(ev, NULL); + } + + return ev; +} diff --git a/lib/util/tevent_ntstatus.c b/lib/util/tevent_ntstatus.c new file mode 100644 index 0000000..7659f15 --- /dev/null +++ b/lib/util/tevent_ntstatus.c @@ -0,0 +1,114 @@ +/* + Unix SMB/CIFS implementation. + Wrap unix errno around tevent_req + Copyright (C) Volker Lendecke 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "../replace/replace.h" +#include "tevent_ntstatus.h" +#include "libcli/util/error.h" + +#define TEVENT_NTERROR_MAGIC (0x917b5acd) + +bool _tevent_req_nterror(struct tevent_req *req, + NTSTATUS status, + const char *location) +{ + uint64_t err; + + if (NT_STATUS_IS_OK(status)) { + return false; + } + + /* + * I've put this variable here, because I'm not 100% certain + * how to correctly assign a 64-bit constant and left-shift it + * by 32 bits in a single expression. If anyone knows, feel + * free :-) + */ + err = TEVENT_NTERROR_MAGIC; + err <<= 32; + err |= NT_STATUS_V(status); + + return _tevent_req_error(req, err, location); +} + +bool tevent_req_is_nterror(struct tevent_req *req, NTSTATUS *status) +{ + enum tevent_req_state state; + uint64_t err; + + if (!tevent_req_is_error(req, &state, &err)) { + return false; + } + switch (state) { + case TEVENT_REQ_TIMED_OUT: + *status = NT_STATUS_IO_TIMEOUT; + break; + case TEVENT_REQ_NO_MEMORY: + *status = NT_STATUS_NO_MEMORY; + break; + case TEVENT_REQ_USER_ERROR: + if ((err >> 32) != TEVENT_NTERROR_MAGIC) { + abort(); + } + *status = NT_STATUS(err & 0xffffffff); + break; + default: + *status = NT_STATUS_INTERNAL_ERROR; + break; + } + return true; +} + +NTSTATUS tevent_req_simple_recv_ntstatus(struct tevent_req *req) +{ + NTSTATUS status = NT_STATUS_OK; + + /* + * Ignore result of tevent_req_is_nterror, we're only interested in + * the status + */ + tevent_req_is_nterror(req, &status); + tevent_req_received(req); + return status; +} + +void tevent_req_simple_finish_ntstatus(struct tevent_req *subreq, + NTSTATUS subreq_status) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + + TALLOC_FREE(subreq); + + if (!NT_STATUS_IS_OK(subreq_status)) { + tevent_req_nterror(req, subreq_status); + return; + } + tevent_req_done(req); +} + +bool tevent_req_poll_ntstatus(struct tevent_req *req, + struct tevent_context *ev, + NTSTATUS *status) +{ + bool ret = tevent_req_poll(req, ev); + if (!ret) { + *status = map_nt_error_from_unix_common(errno); + } + return ret; +} diff --git a/lib/util/tevent_ntstatus.h b/lib/util/tevent_ntstatus.h new file mode 100644 index 0000000..570b6f9 --- /dev/null +++ b/lib/util/tevent_ntstatus.h @@ -0,0 +1,47 @@ +/* + Unix SMB/CIFS implementation. + Wrap unix errno around tevent_req + Copyright (C) Volker Lendecke 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _TEVENT_NTSTATUS_H +#define _TEVENT_NTSTATUS_H + +#include <stdint.h> +#include <stdbool.h> +#include "../libcli/util/ntstatus.h" +#include <tevent.h> + +bool _tevent_req_nterror(struct tevent_req *req, + NTSTATUS status, + const char *location); +#define tevent_req_nterror(req, status) \ + _tevent_req_nterror(req, status, __location__) +bool tevent_req_is_nterror(struct tevent_req *req, NTSTATUS *pstatus); +NTSTATUS tevent_req_simple_recv_ntstatus(struct tevent_req *req); + +/* + * Helper routine to pass the subreq_ntstatus to the req embedded in + * tevent_req_callback_data(subreq), which will be freed. + */ +void tevent_req_simple_finish_ntstatus(struct tevent_req *subreq, + NTSTATUS subreq_status); + +bool tevent_req_poll_ntstatus(struct tevent_req *req, + struct tevent_context *ev, + NTSTATUS *status); + +#endif diff --git a/lib/util/tevent_req_profile.c b/lib/util/tevent_req_profile.c new file mode 100644 index 0000000..2d280f7 --- /dev/null +++ b/lib/util/tevent_req_profile.c @@ -0,0 +1,506 @@ +/* + * Unix SMB/CIFS implementation. + * + * Helpers around tevent_req_profile + * + * Copyright (C) Volker Lendecke 2018 + * + * ** NOTE! The following LGPL license applies to the tevent + * ** library. This does NOT imply that all of Samba is released + * ** under the LGPL + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include <tevent.h> +#include "lib/util/tevent_req_profile.h" +#include "lib/util/time_basic.h" +#include "lib/util/memory.h" + +static bool tevent_req_profile_string_internal( + const struct tevent_req_profile *profile, + unsigned indent, + unsigned max_indent, + char **string) +{ + struct timeval start, stop, diff; + struct timeval_buf start_buf, stop_buf; + const char *req_name = NULL; + const char *start_location = NULL; + const char *stop_location = NULL; + pid_t pid; + enum tevent_req_state state; + const char *state_buf = NULL; + uint64_t user_error; + const struct tevent_req_profile *sub = NULL; + char *result; + + tevent_req_profile_get_name(profile, &req_name); + + tevent_req_profile_get_start(profile, &start_location, &start); + timeval_str_buf(&start, false, true, &start_buf); + + tevent_req_profile_get_stop(profile, &stop_location, &stop); + timeval_str_buf(&stop, false, true, &stop_buf); + + diff = tevent_timeval_until(&start, &stop); + + tevent_req_profile_get_status(profile, &pid, &state, &user_error); + + switch(state) { + case TEVENT_REQ_INIT: + state_buf = "TEVENT_REQ_INIT"; + break; + case TEVENT_REQ_IN_PROGRESS: + state_buf = "TEVENT_REQ_IN_PROGRESS"; + break; + case TEVENT_REQ_DONE: + state_buf = "TEVENT_REQ_DONE"; + break; + case TEVENT_REQ_USER_ERROR: + state_buf = "TEVENT_REQ_USER_ERROR"; + break; + case TEVENT_REQ_TIMED_OUT: + state_buf = "TEVENT_REQ_TIMED_OUT"; + break; + case TEVENT_REQ_NO_MEMORY: + state_buf = "TEVENT_REQ_NO_MEMORY"; + break; + case TEVENT_REQ_RECEIVED: + state_buf = "TEVENT_REQ_RECEIVED"; + break; + default: + state_buf = "unknown"; + break; + } + + result = talloc_asprintf_append_buffer( + *string, + "%*s[%s] %s [%s] %s [%s] [%ju.%.6ju] -> %s (%d %"PRIu64"))\n", + indent, + "", + req_name, + start_location, + start_buf.buf, + stop_location, + stop_buf.buf, + (uintmax_t)diff.tv_sec, + (uintmax_t)diff.tv_usec, + state_buf, + (int)state, + user_error); + if (result == NULL) { + return false; + } + *string = result; + + indent += 1; + + if (indent >= max_indent) { + return true; + } + + for (sub = tevent_req_profile_get_subprofiles(profile); + sub != NULL; + sub = tevent_req_profile_next(sub)) { + bool ret; + + ret = tevent_req_profile_string_internal( + sub, + indent, + max_indent, + string); + if (!ret) { + return false; + } + } + + return true; +} + +char *tevent_req_profile_string(TALLOC_CTX *mem_ctx, + const struct tevent_req_profile *profile, + unsigned indent, + unsigned max_indent) +{ + char *result; + bool ret; + + result = talloc_strdup(mem_ctx, ""); + if (result == NULL) { + return NULL; + } + + ret = tevent_req_profile_string_internal( + profile, + indent, + max_indent, + &result); + if (!ret) { + TALLOC_FREE(result); + return NULL; + } + + return result; +} + +static ssize_t tevent_req_profile_pack_one( + const struct tevent_req_profile *profile, + uint8_t *buf, + size_t buflen) +{ + const char *req_name = NULL; + const char *start_location = NULL; + const char *stop_location = NULL; + struct timeval start_time, stop_time; + pid_t pid; + enum tevent_req_state state; + uint64_t user_error; + size_t pack_len, len; + int ret; + + tevent_req_profile_get_name(profile, &req_name); + tevent_req_profile_get_start(profile, &start_location, &start_time); + tevent_req_profile_get_stop(profile, &stop_location, &stop_time); + tevent_req_profile_get_status(profile, &pid, &state, &user_error); + + len = strlen(req_name)+1; + if (buflen >= len) { + memcpy(buf, req_name, len); + buf += len; + buflen -= len; + } + + pack_len = len; + + len = strlen(start_location)+1; + pack_len += len; + if (pack_len < len) { + return -1; /* overflow */ + } + + if (buflen >= len) { + memcpy(buf, start_location, len); + buf += len; + buflen -= len; + } + + len = strlen(stop_location)+1; + pack_len += len; + if (pack_len < len) { + return -1; /* overflow */ + } + + if (buflen >= len) { + memcpy(buf, stop_location, len); + buf += len; + buflen -= len; + } + + ret = snprintf((char *)buf, + buflen, + "%ju %ju %ju %ju %d %d %"PRIu64"", + (uintmax_t)start_time.tv_sec, + (uintmax_t)start_time.tv_usec, + (uintmax_t)stop_time.tv_sec, + (uintmax_t)stop_time.tv_usec, + (int)pid, + (int)state, + user_error); + if (ret < 0) { + return -1; + } + + /* + * Take care of the trailing 0. No overflow check, this would + * be a VERY small number of bits for "int". + */ + ret += 1; + + pack_len += ret; + + return pack_len; +} + +ssize_t tevent_req_profile_pack( + const struct tevent_req_profile *profile, + uint8_t *buf, + size_t buflen) +{ + const struct tevent_req_profile *sub = NULL; + size_t num_sub; + ssize_t pack_len, profile_len; + int ret; + + num_sub = 0; + pack_len = 0; + + for (sub = tevent_req_profile_get_subprofiles(profile); + sub != NULL; + sub = tevent_req_profile_next(sub)) { + num_sub += 1; + } + + ret = snprintf((char *)buf, buflen, "%zu ", num_sub); + if (ret < 0) { + return -1; + } + + if (buflen > (size_t)ret) { + buf += ret; + buflen -= ret; + } + + pack_len = ret; + + profile_len = tevent_req_profile_pack_one(profile, buf, buflen); + if (profile_len == -1) { + return -1; + } + + if (buflen >= (size_t)profile_len) { + buf += profile_len; + buflen -= profile_len; + } + + pack_len += profile_len; + if (pack_len < profile_len) { + return -1; /* overflow */ + } + + for (sub = tevent_req_profile_get_subprofiles(profile); + sub != NULL; + sub = tevent_req_profile_next(sub)) { + + profile_len = tevent_req_profile_pack(sub, buf, buflen); + if (profile_len == -1) { + return -1; + } + + if (buflen >= (size_t)profile_len) { + buf += profile_len; + buflen -= profile_len; + } + + pack_len += profile_len; + if (pack_len < profile_len) { + return -1; /* overflow */ + } + } + + return pack_len; +} + +static bool parse_uintmax(const char *buf, + char delimiter, + uintmax_t *presult, + char **p_endptr) +{ + uintmax_t result; + char *endptr; + + result = strtoumax(buf, &endptr, 10); + if ((result == UINTMAX_MAX) && (errno == ERANGE)) { + return false; + } + if (*endptr != delimiter) { + return false; + } + + *presult = result; + *p_endptr = endptr+1; + + return true; +} + +static ssize_t tevent_req_profile_unpack_one( + const uint8_t *buf, + size_t buflen, + struct tevent_req_profile *profile) +{ + const char *orig_buf = (const char *)buf; + const char *req_name = NULL; + const char *start_location = NULL; + const char *stop_location = NULL; + uintmax_t start_sec, start_usec, stop_sec, stop_usec, pid, state; + uintmax_t user_error; + char *next = NULL; + size_t len; + bool ok; + + if (buflen == 0) { + return -1; + } + if (buf[buflen-1] != '\0') { + return -1; + } + + req_name = (const char *)buf; + len = strlen(req_name)+1; + + buf += len; + buflen -= len; + if (buflen == 0) { + return -1; + } + + start_location = (const char *)buf; + len = strlen(start_location)+1; + + buf += len; + buflen -= len; + if (buflen == 0) { + return -1; + } + + stop_location = (const char *)buf; + len = strlen(stop_location)+1; + + buf += len; + buflen -= len; + if (buflen == 0) { + return -1; + } + + ok = parse_uintmax((const char *)buf, ' ', &start_sec, &next); + if (!ok) { + return -1; + } + + ok = parse_uintmax(next, ' ', &start_usec, &next); + if (!ok) { + return -1; + } + + ok = parse_uintmax(next, ' ', &stop_sec, &next); + if (!ok) { + return -1; + } + + ok = parse_uintmax(next, ' ', &stop_usec, &next); + if (!ok) { + return -1; + } + + ok = parse_uintmax(next, ' ', &pid, &next); + if (!ok) { + return -1; + } + + ok = parse_uintmax(next, ' ', &state, &next); + if (!ok) { + return -1; + } + + ok = parse_uintmax(next, '\0', &user_error, &next); + if (!ok) { + return -1; + } + + ok = tevent_req_profile_set_name(profile, req_name); + if (!ok) { + return -1; + } + + ok = tevent_req_profile_set_start( + profile, + start_location, + (struct timeval){ .tv_sec=start_sec, .tv_usec=start_usec }); + if (!ok) { + return -1; + } + + ok = tevent_req_profile_set_stop( + profile, + stop_location, + (struct timeval){ .tv_sec=stop_sec, .tv_usec=stop_usec }); + if (!ok) { + return -1; + } + + tevent_req_profile_set_status( + profile, + pid, + (enum tevent_req_state)state, + user_error); + + return next - orig_buf; +} + +ssize_t tevent_req_profile_unpack( + const uint8_t *buf, + size_t buflen, + TALLOC_CTX *mem_ctx, + struct tevent_req_profile **p_profile) +{ + const uint8_t *orig_buf = buf; + struct tevent_req_profile *profile = NULL; + uintmax_t i, num_subprofiles; + char *next = NULL; + bool ok; + ssize_t len; + + errno = 0; + + if (buf[buflen-1] != '\0') { + return -1; + } + + ok = parse_uintmax((const char *)buf, ' ', &num_subprofiles, &next); + if (!ok) { + return -1; + } + + len = (next - (const char *)buf); + + buf += len; + buflen -= len; + + profile = tevent_req_profile_create(mem_ctx); + if (profile == NULL) { + return -1; + } + + len = tevent_req_profile_unpack_one(buf, buflen, profile); + if (len == -1) { + TALLOC_FREE(profile); + return -1; + } + + buf += len; + buflen -= len; + + for (i=0; i<num_subprofiles; i++) { + struct tevent_req_profile *subprofile; + + len = tevent_req_profile_unpack( + buf, + buflen, + profile, + &subprofile); + if (len == -1) { + TALLOC_FREE(profile); + return -1; + } + buf += len; + buflen -= len; + + tevent_req_profile_append_sub(profile, &subprofile); + } + + *p_profile = profile; + + return buf - orig_buf; +} diff --git a/lib/util/tevent_req_profile.h b/lib/util/tevent_req_profile.h new file mode 100644 index 0000000..3bcdbc1 --- /dev/null +++ b/lib/util/tevent_req_profile.h @@ -0,0 +1,46 @@ +/* + * Unix SMB/CIFS implementation. + * + * Helpers around tevent_req_profile + * + * Copyright (C) Volker Lendecke 2018 + * + * ** NOTE! The following LGPL license applies to the tevent + * ** library. This does NOT imply that all of Samba is released + * ** under the LGPL + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LIB_UTIL_TEVENT_REQ_PROFILE_UNPACK +#define __LIB_UTIL_TEVENT_REQ_PROFILE_UNPACK + +#include "replace.h" +#include <tevent.h> + +char *tevent_req_profile_string(TALLOC_CTX *mem_ctx, + const struct tevent_req_profile *profile, + unsigned indent, + unsigned max_indent); +ssize_t tevent_req_profile_pack( + const struct tevent_req_profile *profile, + uint8_t *buf, + size_t buflen); +ssize_t tevent_req_profile_unpack( + const uint8_t *buf, + size_t buflen, + TALLOC_CTX *mem_ctx, + struct tevent_req_profile **p_profile); + +#endif diff --git a/lib/util/tevent_unix.c b/lib/util/tevent_unix.c new file mode 100644 index 0000000..63bdaf6 --- /dev/null +++ b/lib/util/tevent_unix.c @@ -0,0 +1,73 @@ +/* + Unix SMB/CIFS implementation. + Wrap unix errno around tevent_req + Copyright (C) Volker Lendecke 2009 + + ** NOTE! The following LGPL license applies to the tevent_unix + ** helper library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "../replace/replace.h" +#include "tevent_unix.h" + +bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno) +{ + enum tevent_req_state state; + uint64_t err; + + if (!tevent_req_is_error(req, &state, &err)) { + return false; + } + switch (state) { + case TEVENT_REQ_TIMED_OUT: + *perrno = ETIMEDOUT; + break; + case TEVENT_REQ_NO_MEMORY: + *perrno = ENOMEM; + break; + case TEVENT_REQ_USER_ERROR: + *perrno = err; + break; + default: + *perrno = EINVAL; + break; + } + return true; +} + +int tevent_req_simple_recv_unix(struct tevent_req *req) +{ + int err = 0; + + /* + * Ignore result of tevent_req_is_unix_error, we're only interested in + * the status + */ + tevent_req_is_unix_error(req, &err); + tevent_req_received(req); + return err; +} + +bool tevent_req_poll_unix(struct tevent_req *req, struct tevent_context *ev, + int *err) +{ + bool ret = tevent_req_poll(req, ev); + if (!ret) { + *err = errno; + } + return ret; +} diff --git a/lib/util/tevent_unix.h b/lib/util/tevent_unix.h new file mode 100644 index 0000000..39689d6 --- /dev/null +++ b/lib/util/tevent_unix.h @@ -0,0 +1,34 @@ +/* + Unix SMB/CIFS implementation. + Wrap unix errno around tevent_req + Copyright (C) Volker Lendecke 2009 + + ** NOTE! The following LGPL license applies to the tevent_unix + ** helper library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _TEVENT_UNIX_H +#define _TEVENT_UNIX_H + +#include <tevent.h> + +bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno); +int tevent_req_simple_recv_unix(struct tevent_req *req); +bool tevent_req_poll_unix(struct tevent_req *req, struct tevent_context *ev, + int *err); + +#endif diff --git a/lib/util/tevent_werror.c b/lib/util/tevent_werror.c new file mode 100644 index 0000000..edd503e --- /dev/null +++ b/lib/util/tevent_werror.c @@ -0,0 +1,94 @@ +/* + Unix SMB/CIFS implementation. + Wrap win32 errors around tevent_req + Copyright (C) Kai Blin 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "../replace/replace.h" +#include "tevent_werror.h" +#include "libcli/util/error.h" + +bool _tevent_req_werror(struct tevent_req *req, + WERROR werror, + const char *location) +{ + return _tevent_req_error(req, W_ERROR_V(werror), + location); +} + +bool tevent_req_is_werror(struct tevent_req *req, WERROR *error) +{ + enum tevent_req_state state; + uint64_t err; + + if (!tevent_req_is_error(req, &state, &err)) { + return false; + } + switch (state) { + case TEVENT_REQ_TIMED_OUT: + *error = WERR_TIMEOUT; + break; + case TEVENT_REQ_NO_MEMORY: + *error = WERR_NOT_ENOUGH_MEMORY; + break; + case TEVENT_REQ_USER_ERROR: + *error = W_ERROR(err); + break; + default: + *error = WERR_INTERNAL_ERROR; + break; + } + return true; +} + +WERROR tevent_req_simple_recv_werror(struct tevent_req *req) +{ + WERROR werror; + + if (tevent_req_is_werror(req, &werror)) { + tevent_req_received(req); + return werror; + } + tevent_req_received(req); + return WERR_OK; +} + +void tevent_req_simple_finish_werror(struct tevent_req *subreq, + WERROR subreq_error) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + + TALLOC_FREE(subreq); + + if (!W_ERROR_IS_OK(subreq_error)) { + tevent_req_werror(req, subreq_error); + return; + } + tevent_req_done(req); +} + +bool tevent_req_poll_werror(struct tevent_req *req, + struct tevent_context *ev, + WERROR *err) +{ + bool ret = tevent_req_poll(req, ev); + if (!ret) { + NTSTATUS status = map_nt_error_from_unix_common(errno); + *err = ntstatus_to_werror(status); + } + return ret; +} diff --git a/lib/util/tevent_werror.h b/lib/util/tevent_werror.h new file mode 100644 index 0000000..1e08c3d --- /dev/null +++ b/lib/util/tevent_werror.h @@ -0,0 +1,46 @@ +/* + Unix SMB/CIFS implementation. + Wrap win32 errors around tevent_req + Copyright (C) Kai Blin 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _TEVENT_WERROR_H +#define _TEVENT_WERROR_H + +#include <stdint.h> +#include <stdbool.h> +#include "../libcli/util/werror.h" +#include <tevent.h> + +bool _tevent_req_werror(struct tevent_req *req, + WERROR werror, + const char *location); +#define tevent_req_werror(req, werror) \ + _tevent_req_werror(req, werror, __location__) +bool tevent_req_is_werror(struct tevent_req *req, WERROR *error); +WERROR tevent_req_simple_recv_werror(struct tevent_req *req); + +/* + * Helper routine to pass the subreq_werror to the req embedded in + * tevent_req_callback_data(subreq), which will be freed. + */ +void tevent_req_simple_finish_werror(struct tevent_req *subreq, + WERROR subreq_error); + +bool tevent_req_poll_werror(struct tevent_req *req, + struct tevent_context *ev, + WERROR *err); +#endif diff --git a/lib/util/tfork.c b/lib/util/tfork.c new file mode 100644 index 0000000..316287b --- /dev/null +++ b/lib/util/tfork.c @@ -0,0 +1,944 @@ +/* + fork on steroids to avoid SIGCHLD and waitpid + + Copyright (C) Stefan Metzmacher 2010 + Copyright (C) Ralph Boehme 2017 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/wait.h" +#include "system/filesys.h" +#include "system/network.h" +#include "lib/util/samba_util.h" +#include "lib/util/sys_rw.h" +#include "lib/util/tfork.h" +#include "lib/util/debug.h" +#include "lib/util/util_process.h" + +#ifdef HAVE_PTHREAD +#include <pthread.h> +#endif + +#ifdef NDEBUG +#undef NDEBUG +#endif +#include <assert.h> + +/* + * This is how the process hierarchy looks like: + * + * +----------+ + * | caller | + * +----------+ + * | + * fork + * | + * v + * +----------+ + * | waiter | + * +----------+ + * | + * fork + * | + * v + * +----------+ + * | worker | + * +----------+ + */ + +#ifdef HAVE_VALGRIND_HELGRIND_H +#include <valgrind/helgrind.h> +#endif +#ifndef ANNOTATE_BENIGN_RACE_SIZED +#define ANNOTATE_BENIGN_RACE_SIZED(obj, size, description) +#endif + +#define TFORK_ANNOTATE_BENIGN_RACE(obj) \ + ANNOTATE_BENIGN_RACE_SIZED( \ + (obj), sizeof(*(obj)), \ + "no race, serialized by tfork_[un]install_sigchld_handler"); + +/* + * The resulting (private) state per tfork_create() call, returned as a opaque + * handle to the caller. + */ +struct tfork { + /* + * This is returned to the caller with tfork_event_fd() + */ + int event_fd; + + /* + * This is used in the caller by tfork_status() to read the worker exit + * status and to tell the waiter to exit by closing the fd. + */ + int status_fd; + + pid_t waiter_pid; + pid_t worker_pid; +}; + +/* + * Internal per-thread state maintained while inside tfork. + */ +struct tfork_state { + pid_t waiter_pid; + int waiter_errno; + + pid_t worker_pid; +}; + +/* + * A global state that synchronizes access to handling SIGCHLD and waiting for + * children. + */ +struct tfork_signal_state { + bool available; + +#ifdef HAVE_PTHREAD + pthread_cond_t cond; + pthread_mutex_t mutex; +#endif + + /* + * pid of the waiter child. This points at waiter_pid in either struct + * tfork or struct tfork_state, depending on who called + * tfork_install_sigchld_handler(). + * + * When tfork_install_sigchld_handler() is called the waiter_pid is + * still -1 and only set later after fork(), that's why this is must be + * a pointer. The signal handler checks this. + */ + pid_t *pid; + + struct sigaction oldact; + sigset_t oldset; +}; + +static struct tfork_signal_state signal_state; + +#ifdef HAVE_PTHREAD +static pthread_once_t tfork_global_is_initialized = PTHREAD_ONCE_INIT; +static pthread_key_t tfork_global_key; +#else +static struct tfork_state *global_state; +#endif + +static void tfork_sigchld_handler(int signum, siginfo_t *si, void *p); + +#ifdef HAVE_PTHREAD +static void tfork_global_destructor(void *state) +{ + anonymous_shared_free(state); +} +#endif + +static int tfork_acquire_sighandling(void) +{ + int ret = 0; + +#ifdef HAVE_PTHREAD + ret = pthread_mutex_lock(&signal_state.mutex); + if (ret != 0) { + return ret; + } + + while (!signal_state.available) { + ret = pthread_cond_wait(&signal_state.cond, + &signal_state.mutex); + if (ret != 0) { + return ret; + } + } + + signal_state.available = false; + + ret = pthread_mutex_unlock(&signal_state.mutex); + if (ret != 0) { + return ret; + } +#endif + + return ret; +} + +static int tfork_release_sighandling(void) +{ + int ret = 0; + +#ifdef HAVE_PTHREAD + ret = pthread_mutex_lock(&signal_state.mutex); + if (ret != 0) { + return ret; + } + + signal_state.available = true; + + ret = pthread_cond_signal(&signal_state.cond); + if (ret != 0) { + pthread_mutex_unlock(&signal_state.mutex); + return ret; + } + + ret = pthread_mutex_unlock(&signal_state.mutex); + if (ret != 0) { + return ret; + } +#endif + + return ret; +} + +#ifdef HAVE_PTHREAD +static void tfork_atfork_prepare(void) +{ + int ret; + + ret = pthread_mutex_lock(&signal_state.mutex); + assert(ret == 0); +} + +static void tfork_atfork_parent(void) +{ + int ret; + + ret = pthread_mutex_unlock(&signal_state.mutex); + assert(ret == 0); +} +#endif + +static void tfork_atfork_child(void) +{ + int ret; + +#ifdef HAVE_PTHREAD + ret = pthread_mutex_unlock(&signal_state.mutex); + assert(ret == 0); + + ret = pthread_key_delete(tfork_global_key); + assert(ret == 0); + + ret = pthread_key_create(&tfork_global_key, tfork_global_destructor); + assert(ret == 0); + + /* + * There's no data race on the cond variable from the signal state, we + * are writing here, but there are no readers yet. Some data race + * detection tools report a race, but the readers are in the parent + * process. + */ + TFORK_ANNOTATE_BENIGN_RACE(&signal_state.cond); + + /* + * There's no way to destroy a condition variable if there are waiters, + * pthread_cond_destroy() will return EBUSY. Just zero out memory and + * then initialize again. This is not backed by POSIX but should be ok. + */ + ZERO_STRUCT(signal_state.cond); + ret = pthread_cond_init(&signal_state.cond, NULL); + assert(ret == 0); +#endif + + if (signal_state.pid != NULL) { + + ret = sigaction(SIGCHLD, &signal_state.oldact, NULL); + assert(ret == 0); + +#ifdef HAVE_PTHREAD + ret = pthread_sigmask(SIG_SETMASK, &signal_state.oldset, NULL); +#else + ret = sigprocmask(SIG_SETMASK, &signal_state.oldset, NULL); +#endif + assert(ret == 0); + + signal_state.pid = NULL; + } + + signal_state.available = true; +} + +static void tfork_global_initialize(void) +{ +#ifdef HAVE_PTHREAD + int ret; + + pthread_atfork(tfork_atfork_prepare, + tfork_atfork_parent, + tfork_atfork_child); + + ret = pthread_key_create(&tfork_global_key, tfork_global_destructor); + assert(ret == 0); + + ret = pthread_mutex_init(&signal_state.mutex, NULL); + assert(ret == 0); + + ret = pthread_cond_init(&signal_state.cond, NULL); + assert(ret == 0); + + /* + * In a threaded process there's no data race on t->waiter_pid as + * we're serializing globally via tfork_acquire_sighandling() and + * tfork_release_sighandling(). + */ + TFORK_ANNOTATE_BENIGN_RACE(&signal_state.pid); +#endif + + signal_state.available = true; +} + +static struct tfork_state *tfork_global_get(void) +{ + struct tfork_state *state = NULL; +#ifdef HAVE_PTHREAD + int ret; +#endif + +#ifdef HAVE_PTHREAD + state = (struct tfork_state *)pthread_getspecific(tfork_global_key); +#else + state = global_state; +#endif + if (state != NULL) { + return state; + } + + state = (struct tfork_state *)anonymous_shared_allocate( + sizeof(struct tfork_state)); + if (state == NULL) { + return NULL; + } + +#ifdef HAVE_PTHREAD + ret = pthread_setspecific(tfork_global_key, state); + if (ret != 0) { + anonymous_shared_free(state); + return NULL; + } +#endif + return state; +} + +static void tfork_global_free(void) +{ + struct tfork_state *state = NULL; +#ifdef HAVE_PTHREAD + int ret; +#endif + +#ifdef HAVE_PTHREAD + state = (struct tfork_state *)pthread_getspecific(tfork_global_key); +#else + state = global_state; +#endif + if (state == NULL) { + return; + } + +#ifdef HAVE_PTHREAD + ret = pthread_setspecific(tfork_global_key, NULL); + if (ret != 0) { + return; + } +#endif + anonymous_shared_free(state); +} + +/** + * Only one thread at a time is allowed to handle SIGCHLD signals + **/ +static int tfork_install_sigchld_handler(pid_t *pid) +{ + int ret; + struct sigaction act; + sigset_t set; + + ret = tfork_acquire_sighandling(); + if (ret != 0) { + return -1; + } + + assert(signal_state.pid == NULL); + signal_state.pid = pid; + + act = (struct sigaction) { + .sa_sigaction = tfork_sigchld_handler, + .sa_flags = SA_SIGINFO, + }; + + ret = sigaction(SIGCHLD, &act, &signal_state.oldact); + if (ret != 0) { + return -1; + } + + sigemptyset(&set); + sigaddset(&set, SIGCHLD); +#ifdef HAVE_PTHREAD + ret = pthread_sigmask(SIG_UNBLOCK, &set, &signal_state.oldset); +#else + ret = sigprocmask(SIG_UNBLOCK, &set, &signal_state.oldset); +#endif + if (ret != 0) { + return -1; + } + + return 0; +} + +static int tfork_uninstall_sigchld_handler(void) +{ + int ret; + + signal_state.pid = NULL; + + ret = sigaction(SIGCHLD, &signal_state.oldact, NULL); + if (ret != 0) { + return -1; + } + +#ifdef HAVE_PTHREAD + ret = pthread_sigmask(SIG_SETMASK, &signal_state.oldset, NULL); +#else + ret = sigprocmask(SIG_SETMASK, &signal_state.oldset, NULL); +#endif + if (ret != 0) { + return -1; + } + + ret = tfork_release_sighandling(); + if (ret != 0) { + return -1; + } + + return 0; +} + +static void tfork_sigchld_handler(int signum, siginfo_t *si, void *p) +{ + if ((signal_state.pid != NULL) && + (*signal_state.pid != -1) && + (si->si_pid == *signal_state.pid)) + { + return; + } + + /* + * Not our child, forward to old handler + */ + if (signal_state.oldact.sa_flags & SA_SIGINFO) { + signal_state.oldact.sa_sigaction(signum, si, p); + return; + } + + if (signal_state.oldact.sa_handler == SIG_IGN) { + return; + } + if (signal_state.oldact.sa_handler == SIG_DFL) { + return; + } + signal_state.oldact.sa_handler(signum); +} + +static pid_t tfork_start_waiter_and_worker(struct tfork_state *state, + int *_event_fd, + int *_status_fd) +{ + int p[2]; + int status_sp_caller_fd = -1; + int status_sp_waiter_fd = -1; + int event_pipe_caller_fd = -1; + int event_pipe_waiter_fd = -1; + int ready_pipe_caller_fd = -1; + int ready_pipe_worker_fd = -1; + ssize_t nwritten; + ssize_t nread; + pid_t pid; + int status; + int fd; + char c; + int ret; + + *_event_fd = -1; + *_status_fd = -1; + + if (state == NULL) { + return -1; + } + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, p); + if (ret != 0) { + return -1; + } + set_close_on_exec(p[0]); + set_close_on_exec(p[1]); + status_sp_caller_fd = p[0]; + status_sp_waiter_fd = p[1]; + + ret = pipe(p); + if (ret != 0) { + close(status_sp_caller_fd); + close(status_sp_waiter_fd); + return -1; + } + set_close_on_exec(p[0]); + set_close_on_exec(p[1]); + event_pipe_caller_fd = p[0]; + event_pipe_waiter_fd = p[1]; + + + ret = pipe(p); + if (ret != 0) { + close(status_sp_caller_fd); + close(status_sp_waiter_fd); + close(event_pipe_caller_fd); + close(event_pipe_waiter_fd); + return -1; + } + set_close_on_exec(p[0]); + set_close_on_exec(p[1]); + ready_pipe_worker_fd = p[0]; + ready_pipe_caller_fd = p[1]; + + pid = fork(); + if (pid == -1) { + close(status_sp_caller_fd); + close(status_sp_waiter_fd); + close(event_pipe_caller_fd); + close(event_pipe_waiter_fd); + close(ready_pipe_caller_fd); + close(ready_pipe_worker_fd); + return -1; + } + if (pid != 0) { + /* The caller */ + + /* + * In a threaded process there's no data race on + * state->waiter_pid as we're serializing globally via + * tfork_acquire_sighandling() and tfork_release_sighandling(). + */ + TFORK_ANNOTATE_BENIGN_RACE(&state->waiter_pid); + + state->waiter_pid = pid; + + close(status_sp_waiter_fd); + close(event_pipe_waiter_fd); + close(ready_pipe_worker_fd); + + set_blocking(event_pipe_caller_fd, false); + + /* + * wait for the waiter to get ready. + */ + nread = sys_read(status_sp_caller_fd, &c, sizeof(char)); + if (nread != sizeof(char)) { + return -1; + } + + /* + * Notify the worker to start. + */ + nwritten = sys_write(ready_pipe_caller_fd, + &(char){0}, sizeof(char)); + if (nwritten != sizeof(char)) { + close(ready_pipe_caller_fd); + return -1; + } + close(ready_pipe_caller_fd); + + *_event_fd = event_pipe_caller_fd; + *_status_fd = status_sp_caller_fd; + + return pid; + } + +#ifndef HAVE_PTHREAD + /* cleanup sigchld_handler */ + tfork_atfork_child(); +#endif + + /* + * The "waiter" child. + */ + process_set_title("tfork waiter", "tfork waiter process"); + + CatchSignal(SIGCHLD, SIG_DFL); + + close(status_sp_caller_fd); + close(event_pipe_caller_fd); + close(ready_pipe_caller_fd); + + pid = fork(); + if (pid == -1) { + state->waiter_errno = errno; + _exit(0); + } + if (pid == 0) { + /* + * The worker child. + */ + + close(status_sp_waiter_fd); + close(event_pipe_waiter_fd); + + /* + * Wait for the caller to give us a go! + */ + nread = sys_read(ready_pipe_worker_fd, &c, sizeof(char)); + if (nread != sizeof(char)) { + _exit(1); + } + close(ready_pipe_worker_fd); + + return 0; + } + state->worker_pid = pid; + process_set_title("tfork(%d)", "tfork waiter process(%d)", pid); + + close(ready_pipe_worker_fd); + + /* + * We're going to stay around until child2 exits, so lets close all fds + * other than the pipe fd we may have inherited from the caller. + * + * Dup event_sp_waiter_fd and status_sp_waiter_fd onto fds 0 and 1 so we + * can then call closefrom(2). + */ + if (event_pipe_waiter_fd > 0) { + int dup_fd = 0; + + if (status_sp_waiter_fd == 0) { + dup_fd = 1; + } + + do { + fd = dup2(event_pipe_waiter_fd, dup_fd); + } while ((fd == -1) && (errno == EINTR)); + if (fd == -1) { + state->waiter_errno = errno; + kill(state->worker_pid, SIGKILL); + state->worker_pid = -1; + _exit(1); + } + event_pipe_waiter_fd = fd; + } + + if (status_sp_waiter_fd > 1) { + do { + fd = dup2(status_sp_waiter_fd, 1); + } while ((fd == -1) && (errno == EINTR)); + if (fd == -1) { + state->waiter_errno = errno; + kill(state->worker_pid, SIGKILL); + state->worker_pid = -1; + _exit(1); + } + status_sp_waiter_fd = fd; + } + + closefrom(2); + + /* Tell the caller we're ready */ + nwritten = sys_write(status_sp_waiter_fd, &(char){0}, sizeof(char)); + if (nwritten != sizeof(char)) { + _exit(1); + } + + tfork_global_free(); + state = NULL; + + do { + ret = waitpid(pid, &status, 0); + } while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { + status = errno; + kill(pid, SIGKILL); + } + + /* + * This writes the worker child exit status via our internal socketpair + * so the tfork_status() implementation can read it from its end. + */ + nwritten = sys_write(status_sp_waiter_fd, &status, sizeof(status)); + if (nwritten == -1) { + if (errno != EPIPE && errno != ECONNRESET) { + _exit(errno); + } + /* + * The caller exited and didn't call tfork_status(). + */ + _exit(0); + } + if (nwritten != sizeof(status)) { + _exit(1); + } + + /* + * This write to the event_fd returned by tfork_event_fd() and notifies + * the caller that the worker child is done and he may now call + * tfork_status(). + */ + nwritten = sys_write(event_pipe_waiter_fd, &(char){0}, sizeof(char)); + if (nwritten != sizeof(char)) { + _exit(1); + } + + /* + * Wait for our parent (the process that called tfork_create()) to + * close() the socketpair fd in tfork_status(). + * + * Again, the caller might have exited without calling tfork_status(). + */ + nread = sys_read(status_sp_waiter_fd, &c, 1); + if (nread == -1) { + if (errno == EPIPE || errno == ECONNRESET) { + _exit(0); + } + _exit(errno); + } + if (nread != 1) { + _exit(255); + } + + _exit(0); +} + +static int tfork_create_reap_waiter(pid_t waiter_pid) +{ + pid_t pid; + int waiter_status; + + if (waiter_pid == -1) { + return 0; + } + + kill(waiter_pid, SIGKILL); + + do { + pid = waitpid(waiter_pid, &waiter_status, 0); + } while ((pid == -1) && (errno == EINTR)); + assert(pid == waiter_pid); + + return 0; +} + +struct tfork *tfork_create(void) +{ + struct tfork_state *state = NULL; + struct tfork *t = NULL; + pid_t pid; + int saved_errno = 0; + int ret = 0; + int ret2; + +#ifdef HAVE_PTHREAD + ret = pthread_once(&tfork_global_is_initialized, + tfork_global_initialize); + if (ret != 0) { + return NULL; + } +#else + tfork_global_initialize(); +#endif + + state = tfork_global_get(); + if (state == NULL) { + return NULL; + } + *state = (struct tfork_state) { + .waiter_pid = -1, + .waiter_errno = ECANCELED, + .worker_pid = -1, + }; + + t = malloc(sizeof(struct tfork)); + if (t == NULL) { + ret = -1; + goto cleanup; + } + + *t = (struct tfork) { + .event_fd = -1, + .status_fd = -1, + .waiter_pid = -1, + .worker_pid = -1, + }; + + ret = tfork_install_sigchld_handler(&state->waiter_pid); + if (ret != 0) { + goto cleanup; + } + + pid = tfork_start_waiter_and_worker(state, + &t->event_fd, + &t->status_fd); + if (pid == -1) { + ret = -1; + goto cleanup; + } + if (pid == 0) { + /* In the worker */ + tfork_global_free(); + t->worker_pid = 0; + return t; + } + + /* + * In a threaded process there's no data race on t->waiter_pid as + * we're serializing globally via tfork_acquire_sighandling() and + * tfork_release_sighandling(). + */ + TFORK_ANNOTATE_BENIGN_RACE(&t->waiter_pid); + + t->waiter_pid = pid; + t->worker_pid = state->worker_pid; + +cleanup: + if (ret == -1) { + saved_errno = errno; + + if (t != NULL) { + if (t->status_fd != -1) { + close(t->status_fd); + } + if (t->event_fd != -1) { + close(t->event_fd); + } + + ret2 = tfork_create_reap_waiter(state->waiter_pid); + assert(ret2 == 0); + + free(t); + t = NULL; + } + } + + ret2 = tfork_uninstall_sigchld_handler(); + assert(ret2 == 0); + + tfork_global_free(); + + if (ret == -1) { + errno = saved_errno; + } + return t; +} + +pid_t tfork_child_pid(const struct tfork *t) +{ + return t->worker_pid; +} + +int tfork_event_fd(struct tfork *t) +{ + int fd = t->event_fd; + + assert(t->event_fd != -1); + t->event_fd = -1; + + return fd; +} + +int tfork_status(struct tfork **_t, bool wait) +{ + struct tfork *t = *_t; + int status; + ssize_t nread; + int waiter_status; + pid_t pid; + int ret; + + if (t == NULL) { + return -1; + } + + if (wait) { + set_blocking(t->status_fd, true); + + nread = sys_read(t->status_fd, &status, sizeof(int)); + } else { + set_blocking(t->status_fd, false); + + nread = read(t->status_fd, &status, sizeof(int)); + if ((nread == -1) && + ((errno == EAGAIN) || (errno == EWOULDBLOCK) || errno == EINTR)) { + errno = EAGAIN; + return -1; + } + } + if (nread != sizeof(int)) { + return -1; + } + + ret = tfork_install_sigchld_handler(&t->waiter_pid); + if (ret != 0) { + return -1; + } + + /* + * This triggers process exit in the waiter. + * We write to the fd as well as closing it, as any tforked sibling + * processes will also have the writable end of this socket open. + * + */ + { + size_t nwritten; + nwritten = sys_write(t->status_fd, &(char){0}, sizeof(char)); + if (nwritten != sizeof(char)) { + close(t->status_fd); + return -1; + } + } + close(t->status_fd); + + do { + pid = waitpid(t->waiter_pid, &waiter_status, 0); + } while ((pid == -1) && (errno == EINTR)); + assert(pid == t->waiter_pid); + + if (t->event_fd != -1) { + close(t->event_fd); + t->event_fd = -1; + } + + free(t); + t = NULL; + *_t = NULL; + + ret = tfork_uninstall_sigchld_handler(); + assert(ret == 0); + + return status; +} + +int tfork_destroy(struct tfork **_t) +{ + struct tfork *t = *_t; + int ret; + + if (t == NULL) { + errno = EINVAL; + return -1; + } + + kill(t->worker_pid, SIGKILL); + + ret = tfork_status(_t, true); + if (ret == -1) { + return -1; + } + + return 0; +} diff --git a/lib/util/tfork.h b/lib/util/tfork.h new file mode 100644 index 0000000..6c59caf --- /dev/null +++ b/lib/util/tfork.h @@ -0,0 +1,111 @@ +/* + fork on steroids to avoid SIGCHLD and waitpid + + Copyright (C) Stefan Metzmacher 2010 + Copyright (C) Ralph Boehme 2017 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef LIB_UTIL_TFORK_H +#define LIB_UTIL_TFORK_H + +struct tfork; + +/** + * @brief a fork() that avoids SIGCHLD and waitpid + * + * This function is a solution to the problem of fork() requiring special + * preparations in the caller to handle SIGCHLD signals and to reap the child by + * wait()ing for it. + * + * The advantage over fork() is that the child process termination is signalled + * to the caller by making a pipe fd readable returned by tfork_event_fd(), in + * which case the exit status of the child can be fetched with tfork_status() + * without blocking. + * + * The child process will start with SIGCHLD handler set to SIG_DFL. + * + * @return On success, a struct tfork. NULL on failure. + * Use tfork_worker_pid() to get the pid of the created + * child and tfork_event_fd() to get the file descriptor + * that can be used to poll for process termination and + * reading the child process exit status. + * + * @note There's one thing this thing can't protect us against and that is if a + * process installs a SIGCHLD handler from one thread while another thread is + * running inside tfork_create() or tfork_status() and the signal handler + * doesn't forward signals for exited children it didn't fork, ie our children. + **/ +struct tfork *tfork_create(void); + +/** + * @brief Return the child pid from tfork_create() + * + * @param[in] t Pointer to struct tfork returned by tfork_create() + * + * @return In the caller this returns the pid of the child, + * in the child this returns 0. + **/ +pid_t tfork_child_pid(const struct tfork *t); + +/** + * @brief Return an event fd that signals child termination + * + * @param[in] t Pointer to struct tfork returned by tfork_create() + * + * It is the callers responsibility to ensure that the event fd returned by + * tfork_event_fd() is closed. By calling tfork_event_fd() ownership of the fd + * is transferred to the caller, calling tfork_event_fd() again will trigger an + * abort(). + * + * @return An fd that becomes readable when the child created with + * tfork_create() terminates. It is guaranteed that a + * subsequent call to tfork_status() will not block and return + * the exit status of the child. + **/ +int tfork_event_fd(struct tfork *t); + +/** + * @brief Wait for the child to terminate and return its exit status + * + * @param[in] t Pointer-pointer to a struct tfork returned by + * tfork_create(). Upon successful completion t is freed and + * set to NULL. + * + * @param[in] wait Whether to wait for the child to change state. If wait is + * false, and the child hasn't changed state, tfork_status() + * will return -1 with errno set to EAGAIN. If wait is true, + * tfork_status() will block waiting for the child to change + * runstate. + * + * @return The exit status of the child, -1 on error. + * + * @note We overload the return value a bit, but a process exit status is pretty + * much guaranteed to be a 16-bit int and can't be -1. + **/ +int tfork_status(struct tfork **_t, bool wait); + +/** + * @brief Terminate the child discarding the exit status + * + * @param[in] t Pointer-pointer to a struct tfork returned by + * tfork_create(). Upon successful completion t is freed and + * set to NULL. + * + * @return 0 on success, -1 on error. + **/ +int tfork_destroy(struct tfork **_t); + +#endif /* LIB_UTIL_TFORK_H */ diff --git a/lib/util/tftw.c b/lib/util/tftw.c new file mode 100644 index 0000000..c59bb6a --- /dev/null +++ b/lib/util/tftw.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2008-2018 by Andreas Schneider <asn@samba.org> + * + * Adopted from the csync source code + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/dir.h" +#include "lib/util/debug.h" + +#include "tftw.h" + + +int tftw(TALLOC_CTX *mem_ctx, const char *fpath, tftw_walker_fn fn, size_t depth, void *userdata) +{ + char *filename = NULL; + char *d_name = NULL; + DIR *dh = NULL; + struct dirent *dirent = NULL; + struct stat sb = {0}; + int rc = 0; + + if (fpath[0] == '\0') { + errno = ENOENT; + goto error; + } + + if ((dh = opendir(fpath)) == NULL) { + /* permission denied */ + if (errno == EACCES) { + return 0; + } else { + DBG_ERR("opendir failed for: [%s]\n", strerror(errno)); + goto error; + } + } + + while ((dirent = readdir(dh))) { + int flag; + + d_name = dirent->d_name; + if (d_name == NULL) { + goto error; + } + + /* skip "." and ".." */ + if (d_name[0] == '.' && (d_name[1] == '\0' + || (d_name[1] == '.' && d_name[2] == '\0'))) { + dirent = NULL; + continue; + } + + filename = talloc_asprintf(mem_ctx, "%s/%s", fpath, d_name); + if (filename == NULL) { + goto error; + } + + rc = lstat(filename, &sb); + if (rc < 0) { + dirent = NULL; + goto error; + } + + switch (sb.st_mode & S_IFMT) { + case S_IFLNK: + flag = TFTW_FLAG_SLINK; + break; + case S_IFDIR: + flag = TFTW_FLAG_DIR; + break; + case S_IFBLK: + case S_IFCHR: + case S_IFSOCK: + case S_IFIFO: + flag = TFTW_FLAG_SPEC; + break; + default: + flag = TFTW_FLAG_FILE; + break; + } + + DBG_INFO("walk: [%s]\n", filename); + + /* Call walker function for each file */ + rc = fn(mem_ctx, filename, &sb, flag, userdata); + + if (rc < 0) { + DBG_ERR("provided callback fn() failed: [%s]\n", + strerror(errno)); + closedir(dh); + goto done; + } + + if (flag == TFTW_FLAG_DIR && depth) { + rc = tftw(mem_ctx, filename, fn, depth - 1, userdata); + if (rc < 0) { + closedir(dh); + goto done; + } + } + TALLOC_FREE(filename); + dirent = NULL; + } + closedir(dh); + +done: + TALLOC_FREE(filename); + return rc; +error: + if (dh != NULL) { + closedir(dh); + } + TALLOC_FREE(filename); + return -1; +} diff --git a/lib/util/tftw.h b/lib/util/tftw.h new file mode 100644 index 0000000..0d3d007 --- /dev/null +++ b/lib/util/tftw.h @@ -0,0 +1,32 @@ +#include <talloc.h> + +enum tftw_flags_e { + /* Regular file. */ + TFTW_FLAG_FILE, + /* Directory. */ + TFTW_FLAG_DIR, + /* Unreadable directory. */ + TFTW_FLAG_DNR, + /* Unstatable file. */ + TFTW_FLAG_NSTAT, + /* Symbolic link. */ + TFTW_FLAG_SLINK, + /* Special file (fifo, ...). */ + TFTW_FLAG_SPEC, + + /* Directory, all subdirs have been visited. */ + TFTW_FLAG_DP, + /* Symbolic link naming non-existing file. */ + TFTW_FLAG_SLN +}; + +/* Maximum number of subdirectories to descend into */ +#define TFTW_MAX_DEPTH 50 + +typedef int (*tftw_walker_fn)(TALLOC_CTX *mem_ctx, + const char *fpath, + const struct stat *sb, + enum tftw_flags_e flag, + void *userdata); + +int tftw(TALLOC_CTX *mem_ctx, const char *fpath, tftw_walker_fn fn, size_t depth, void *userdata); diff --git a/lib/util/time.c b/lib/util/time.c new file mode 100644 index 0000000..47ae320 --- /dev/null +++ b/lib/util/time.c @@ -0,0 +1,1494 @@ +/* + Unix SMB/CIFS implementation. + time handling functions + + Copyright (C) Andrew Tridgell 1992-2004 + Copyright (C) Stefan (metze) Metzmacher 2002 + Copyright (C) Jeremy Allison 2007 + Copyright (C) Andrew Bartlett 2011 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/time.h" +#include "byteorder.h" +#include "time_basic.h" +#include "lib/util/time.h" /* Avoid /usr/include/time.h */ +#include <sys/stat.h> +#ifndef NO_CONFIG_H +#include "config.h" +#endif + +/** + * @file + * @brief time handling functions + */ + +#define TIME_FIXUP_CONSTANT_INT INT64_C(11644473600) + + +#define NSEC_PER_SEC 1000000000 + +/** + External access to time_t_min and time_t_max. +**/ +_PUBLIC_ time_t get_time_t_max(void) +{ + return TIME_T_MAX; +} + +/** +a wrapper to preferably get the monotonic time +**/ +_PUBLIC_ void clock_gettime_mono(struct timespec *tp) +{ +/* prefer a suspend aware monotonic CLOCK_BOOTTIME: */ +#ifdef CLOCK_BOOTTIME + if (clock_gettime(CLOCK_BOOTTIME,tp) == 0) { + return; + } +#endif +/* then try the monotonic clock: */ +#ifndef CUSTOM_CLOCK_MONOTONIC_IS_REALTIME + if (clock_gettime(CUSTOM_CLOCK_MONOTONIC,tp) == 0) { + return; + } +#endif + clock_gettime(CLOCK_REALTIME,tp); +} + +/** +a wrapper to preferably get the monotonic time in seconds +**/ +_PUBLIC_ time_t time_mono(time_t *t) +{ + struct timespec tp; + + clock_gettime_mono(&tp); + if (t != NULL) { + *t = tp.tv_sec; + } + return tp.tv_sec; +} + + +#define TIME_FIXUP_CONSTANT 11644473600LL + +time_t convert_timespec_to_time_t(struct timespec ts) +{ + /* Ensure tv_nsec is less than 1sec. */ + normalize_timespec(&ts); + + /* 1 ns == 1,000,000,000 - one thousand millionths of a second. + increment if it's greater than 500 millionth of a second. */ + + if (ts.tv_nsec > 500000000) { + return ts.tv_sec + 1; + } + return ts.tv_sec; +} + +struct timespec convert_time_t_to_timespec(time_t t) +{ + struct timespec ts; + ts.tv_sec = t; + ts.tv_nsec = 0; + return ts; +} + + + +/** + Interpret an 8 byte "filetime" structure to a time_t + It's originally in "100ns units since jan 1st 1601" + + An 8 byte value of 0xffffffffffffffff will be returned as a timespec of + + tv_sec = 0 + tv_nsec = 0; + + Returns GMT. +**/ +time_t nt_time_to_unix(NTTIME nt) +{ + return convert_timespec_to_time_t(nt_time_to_unix_timespec(nt)); +} + + +/** +put a 8 byte filetime from a time_t +This takes GMT as input +**/ +_PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t) +{ + uint64_t t2; + + if (t == (time_t)-1) { + *nt = UINT64_MAX; + return; + } + + if (t == TIME_T_MAX || t == INT64_MAX) { + *nt = 0x7fffffffffffffffLL; + return; + } + + if (t == 0) { + *nt = 0; + return; + } + + t2 = t; + t2 += TIME_FIXUP_CONSTANT_INT; + t2 *= 1000*1000*10; + + *nt = t2; +} + + +/** +check if it's a null unix time +**/ +_PUBLIC_ bool null_time(time_t t) +{ + return t == 0 || + t == (time_t)0xFFFFFFFF || + t == (time_t)-1; +} + + +/** +check if it's a null NTTIME +**/ +_PUBLIC_ bool null_nttime(NTTIME t) +{ + return t == 0; +} + +/******************************************************************* + create a 16 bit dos packed date +********************************************************************/ +static uint16_t make_dos_date1(struct tm *t) +{ + uint16_t ret=0; + ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1); + ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5)); + return ret; +} + +/******************************************************************* + create a 16 bit dos packed time +********************************************************************/ +static uint16_t make_dos_time1(struct tm *t) +{ + uint16_t ret=0; + ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3)); + ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5)); + return ret; +} + +/******************************************************************* + create a 32 bit dos packed date/time from some parameters + This takes a GMT time and returns a packed localtime structure +********************************************************************/ +static uint32_t make_dos_date(time_t unixdate, int zone_offset) +{ + struct tm *t; + uint32_t ret=0; + + if (unixdate == 0) { + return 0; + } + + unixdate -= zone_offset; + + t = gmtime(&unixdate); + if (!t) { + return 0xFFFFFFFF; + } + + ret = make_dos_date1(t); + ret = ((ret&0xFFFF)<<16) | make_dos_time1(t); + + return ret; +} + +/** +put a dos date into a buffer (time/date format) +This takes GMT time and puts local time in the buffer +**/ +_PUBLIC_ void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset) +{ + uint32_t x = make_dos_date(unixdate, zone_offset); + SIVAL(buf,offset,x); +} + +/** +put a dos date into a buffer (date/time format) +This takes GMT time and puts local time in the buffer +**/ +_PUBLIC_ void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset) +{ + uint32_t x; + x = make_dos_date(unixdate, zone_offset); + x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); + SIVAL(buf,offset,x); +} + +/** +put a dos 32 bit "unix like" date into a buffer. This routine takes +GMT and converts it to LOCAL time before putting it (most SMBs assume +localtime for this sort of date) +**/ +_PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset) +{ + if (!null_time(unixdate)) { + unixdate -= zone_offset; + } + SIVAL(buf,offset,unixdate); +} + +/******************************************************************* + interpret a 32 bit dos packed date/time to some parameters +********************************************************************/ +void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second) +{ + uint32_t p0,p1,p2,p3; + + p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; + p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF; + + *second = 2*(p0 & 0x1F); + *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3); + *hour = (p1>>3)&0xFF; + *day = (p2&0x1F); + *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1; + *year = ((p3>>1)&0xFF) + 80; +} + +/** + create a unix date (int GMT) from a dos date (which is actually in + localtime) +**/ +_PUBLIC_ time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset) +{ + uint32_t dos_date=0; + struct tm t; + time_t ret; + + dos_date = IVAL(date_ptr,0); + + if (dos_date == 0) return (time_t)0; + + interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon, + &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); + t.tm_isdst = -1; + + ret = timegm(&t); + + ret += zone_offset; + + return ret; +} + +/** +like make_unix_date() but the words are reversed +**/ +_PUBLIC_ time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset) +{ + uint32_t x,x2; + + x = IVAL(date_ptr,0); + x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); + SIVAL(&x,0,x2); + + return pull_dos_date((const uint8_t *)&x, zone_offset); +} + +/** + create a unix GMT date from a dos date in 32 bit "unix like" format + these generally arrive as localtimes, with corresponding DST +**/ +_PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset) +{ + time_t t = (time_t)IVAL(date_ptr,0); + + if (t == (time_t)0xFFFFFFFF) { + t = (time_t)-1; + } + + if (!null_time(t)) { + t += zone_offset; + } + return t; +} + +/**************************************************************************** + Return the date and time as a string +****************************************************************************/ + +char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires) +{ + struct timeval_buf tmp; + char *result; + + result = talloc_strdup(ctx, timeval_str_buf(tp, false, hires, &tmp)); + if (result == NULL) { + return NULL; + } + + /* + * beautify the talloc_report output + * + * This is not just cosmetics. A C compiler might in theory make the + * talloc_strdup call above a tail call with the tail call + * optimization. This would render "tmp" invalid while talloc_strdup + * tries to duplicate it. The talloc_set_name_const call below puts + * the talloc_strdup call into non-tail position. + */ + talloc_set_name_const(result, result); + return result; +} + +/**************************************************************************** + Return the date and time as a string +****************************************************************************/ + +const char *timespec_string_buf(const struct timespec *tp, + bool hires, + struct timeval_buf *buf) +{ + time_t t; + struct tm *tm = NULL; + int len; + + if (is_omit_timespec(tp)) { + strlcpy(buf->buf, "SAMBA_UTIME_OMIT", sizeof(buf->buf)); + return buf->buf; + } + + t = (time_t)tp->tv_sec; + tm = localtime(&t); + + if (tm == NULL) { + if (hires) { + len = snprintf(buf->buf, sizeof(buf->buf), + "%ld.%09ld seconds since the Epoch", + (long)tp->tv_sec, (long)tp->tv_nsec); + } else { + len = snprintf(buf->buf, sizeof(buf->buf), + "%ld seconds since the Epoch", (long)t); + } + } else if (!hires) { + len = snprintf(buf->buf, sizeof(buf->buf), + "%04d-%02d-%02d %02d:%02d:%02d", + 1900 + tm->tm_year, + tm->tm_mon + 1, + tm->tm_mday, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + } else { + len = snprintf(buf->buf, sizeof(buf->buf), + "%04d-%02d-%02d %02d:%02d:%02d.%09ld", + 1900 + tm->tm_year, + tm->tm_mon + 1, + tm->tm_mday, + tm->tm_hour, + tm->tm_min, + tm->tm_sec, + (long)tp->tv_nsec); + } + if (len == -1) { + return ""; + } + + return buf->buf; +} + +char *current_timestring(TALLOC_CTX *ctx, bool hires) +{ + struct timeval tv; + + GetTimeOfDay(&tv); + return timeval_string(ctx, &tv, hires); +} + +/* + * Return date and time as a minimal string avoiding funny characters + * that may cause trouble in file names. We only use digits and + * underscore ... or a minus/hyphen if we got negative time. + */ +char *minimal_timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires) +{ + time_t t; + struct tm *tm; + + t = (time_t)tp->tv_sec; + tm = localtime(&t); + if (!tm) { + if (hires) { + return talloc_asprintf(ctx, "%ld_%06ld", + (long)tp->tv_sec, + (long)tp->tv_usec); + } else { + return talloc_asprintf(ctx, "%ld", (long)t); + } + } else { + if (hires) { + return talloc_asprintf(ctx, + "%04d%02d%02d_%02d%02d%02d_%06ld", + tm->tm_year+1900, + tm->tm_mon+1, + tm->tm_mday, + tm->tm_hour, + tm->tm_min, + tm->tm_sec, + (long)tp->tv_usec); + } else { + return talloc_asprintf(ctx, + "%04d%02d%02d_%02d%02d%02d", + tm->tm_year+1900, + tm->tm_mon+1, + tm->tm_mday, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + } + } +} + +char *current_minimal_timestring(TALLOC_CTX *ctx, bool hires) +{ + struct timeval tv; + + GetTimeOfDay(&tv); + return minimal_timeval_string(ctx, &tv, hires); +} + +/** +return a HTTP/1.0 time string +**/ +_PUBLIC_ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t) +{ + char *buf; + char tempTime[60]; + struct tm *tm = localtime(&t); + + if (t == TIME_T_MAX) { + return talloc_strdup(mem_ctx, "never"); + } + + if (!tm) { + return talloc_asprintf(mem_ctx,"%ld seconds since the Epoch",(long)t); + } + +#ifndef HAVE_STRFTIME + buf = talloc_strdup(mem_ctx, asctime(tm)); + if (buf[strlen(buf)-1] == '\n') { + buf[strlen(buf)-1] = 0; + } +#else + strftime(tempTime, sizeof(tempTime)-1, "%a, %d %b %Y %H:%M:%S %Z", tm); + buf = talloc_strdup(mem_ctx, tempTime); +#endif /* !HAVE_STRFTIME */ + + return buf; +} + +/** + Return the date and time as a string +**/ +_PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t) +{ + char *TimeBuf; + char tempTime[80]; + struct tm *tm; + + tm = localtime(&t); + if (!tm) { + return talloc_asprintf(mem_ctx, + "%ld seconds since the Epoch", + (long)t); + } + +#ifdef HAVE_STRFTIME + /* Some versions of gcc complain about using some special format + * specifiers. This is a bug in gcc, not a bug in this code. See a + * recent strftime() manual page for details. */ + strftime(tempTime,sizeof(tempTime)-1,"%a %b %e %X %Y %Z",tm); + TimeBuf = talloc_strdup(mem_ctx, tempTime); +#else + TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); + if (TimeBuf == NULL) { + return NULL; + } + if (TimeBuf[0] != '\0') { + size_t len = strlen(TimeBuf); + if (TimeBuf[len - 1] == '\n') { + TimeBuf[len - 1] = '\0'; + } + } +#endif + + return TimeBuf; +} + +/** + return a talloced string representing a NTTIME for human consumption +*/ +_PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt) +{ + time_t t; + if (nt == 0) { + return "NTTIME(0)"; + } + t = nt_time_to_full_time_t(nt); + return timestring(mem_ctx, t); +} + + +/** + put a NTTIME into a packet +*/ +_PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t) +{ + SBVAL(base, offset, t); +} + +/** + pull a NTTIME from a packet +*/ +_PUBLIC_ NTTIME pull_nttime(uint8_t *base, uint16_t offset) +{ + NTTIME ret = BVAL(base, offset); + return ret; +} + +/** + return (tv1 - tv2) in microseconds +*/ +_PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2) +{ + int64_t sec_diff = tv1->tv_sec - tv2->tv_sec; + return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec); +} + +/** + return (tp1 - tp2) in nanoseconds +*/ +_PUBLIC_ int64_t nsec_time_diff(const struct timespec *tp1, const struct timespec *tp2) +{ + int64_t sec_diff = tp1->tv_sec - tp2->tv_sec; + return (sec_diff * 1000000000) + (int64_t)(tp1->tv_nsec - tp2->tv_nsec); +} + + +/** + return a zero timeval +*/ +_PUBLIC_ struct timeval timeval_zero(void) +{ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + return tv; +} + +/** + return true if a timeval is zero +*/ +_PUBLIC_ bool timeval_is_zero(const struct timeval *tv) +{ + return tv->tv_sec == 0 && tv->tv_usec == 0; +} + +/** + return a timeval for the current time +*/ +_PUBLIC_ struct timeval timeval_current(void) +{ + struct timeval tv; + GetTimeOfDay(&tv); + return tv; +} + +/** + return a timeval struct with the given elements +*/ +_PUBLIC_ struct timeval timeval_set(uint32_t secs, uint32_t usecs) +{ + struct timeval tv; + tv.tv_sec = secs; + tv.tv_usec = usecs; + return tv; +} + + +/** + return a timeval ofs microseconds after tv +*/ +_PUBLIC_ struct timeval timeval_add(const struct timeval *tv, + uint32_t secs, uint32_t usecs) +{ + struct timeval tv2 = *tv; + const unsigned int million = 1000000; + tv2.tv_sec += secs; + tv2.tv_usec += usecs; + tv2.tv_sec += tv2.tv_usec / million; + tv2.tv_usec = tv2.tv_usec % million; + return tv2; +} + +/** + return the sum of two timeval structures +*/ +struct timeval timeval_sum(const struct timeval *tv1, + const struct timeval *tv2) +{ + return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec); +} + +/** + return a timeval secs/usecs into the future +*/ +_PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs) +{ + struct timeval tv = timeval_current(); + return timeval_add(&tv, secs, usecs); +} + +/** + return a timeval milliseconds into the future +*/ +_PUBLIC_ struct timeval timeval_current_ofs_msec(uint32_t msecs) +{ + struct timeval tv = timeval_current(); + return timeval_add(&tv, msecs / 1000, (msecs % 1000) * 1000); +} + +/** + return a timeval microseconds into the future +*/ +_PUBLIC_ struct timeval timeval_current_ofs_usec(uint32_t usecs) +{ + struct timeval tv = timeval_current(); + return timeval_add(&tv, usecs / 1000000, usecs % 1000000); +} + +/** + compare two timeval structures. + Return -1 if tv1 < tv2 + Return 0 if tv1 == tv2 + Return 1 if tv1 > tv2 +*/ +_PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2) +{ + if (tv1->tv_sec > tv2->tv_sec) return 1; + if (tv1->tv_sec < tv2->tv_sec) return -1; + if (tv1->tv_usec > tv2->tv_usec) return 1; + if (tv1->tv_usec < tv2->tv_usec) return -1; + return 0; +} + +/** + return true if a timer is in the past +*/ +_PUBLIC_ bool timeval_expired(const struct timeval *tv) +{ + struct timeval tv2 = timeval_current(); + if (tv2.tv_sec > tv->tv_sec) return true; + if (tv2.tv_sec < tv->tv_sec) return false; + return (tv2.tv_usec >= tv->tv_usec); +} + +/** + return the number of seconds elapsed between two times +*/ +_PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2) +{ + return (tv2->tv_sec - tv1->tv_sec) + + (tv2->tv_usec - tv1->tv_usec)*1.0e-6; +} + +/** + return the number of seconds elapsed since a given time +*/ +_PUBLIC_ double timeval_elapsed(const struct timeval *tv) +{ + struct timeval tv2 = timeval_current(); + return timeval_elapsed2(tv, &tv2); +} +/** + * return the number of seconds elapsed between two times + **/ +_PUBLIC_ double timespec_elapsed2(const struct timespec *ts1, + const struct timespec *ts2) +{ + return (ts2->tv_sec - ts1->tv_sec) + + (ts2->tv_nsec - ts1->tv_nsec)*1.0e-9; +} + +/** + * return the number of seconds elapsed since a given time + */ +_PUBLIC_ double timespec_elapsed(const struct timespec *ts) +{ + struct timespec ts2 = timespec_current(); + return timespec_elapsed2(ts, &ts2); +} + +/** + return the lesser of two timevals +*/ +_PUBLIC_ struct timeval timeval_min(const struct timeval *tv1, + const struct timeval *tv2) +{ + if (tv1->tv_sec < tv2->tv_sec) return *tv1; + if (tv1->tv_sec > tv2->tv_sec) return *tv2; + if (tv1->tv_usec < tv2->tv_usec) return *tv1; + return *tv2; +} + +/** + return the greater of two timevals +*/ +_PUBLIC_ struct timeval timeval_max(const struct timeval *tv1, + const struct timeval *tv2) +{ + if (tv1->tv_sec > tv2->tv_sec) return *tv1; + if (tv1->tv_sec < tv2->tv_sec) return *tv2; + if (tv1->tv_usec > tv2->tv_usec) return *tv1; + return *tv2; +} + +/** + return the difference between two timevals as a timeval + if tv1 comes after tv2, then return a zero timeval + (this is *tv2 - *tv1) +*/ +_PUBLIC_ struct timeval timeval_until(const struct timeval *tv1, + const struct timeval *tv2) +{ + struct timeval t; + if (timeval_compare(tv1, tv2) >= 0) { + return timeval_zero(); + } + t.tv_sec = tv2->tv_sec - tv1->tv_sec; + if (tv1->tv_usec > tv2->tv_usec) { + t.tv_sec--; + t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec); + } else { + t.tv_usec = tv2->tv_usec - tv1->tv_usec; + } + return t; +} + + +/** + convert a timeval to a NTTIME +*/ +_PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv) +{ + return 10*(tv->tv_usec + + ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000)); +} + +/** + convert a NTTIME to a timeval +*/ +_PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t) +{ + if (tv == NULL) return; + + t += 10/2; + t /= 10; + t -= TIME_FIXUP_CONSTANT*1000*1000; + + tv->tv_sec = t / 1000000; + + if (TIME_T_MIN > tv->tv_sec || tv->tv_sec > TIME_T_MAX) { + tv->tv_sec = 0; + tv->tv_usec = 0; + return; + } + + tv->tv_usec = t - tv->tv_sec*1000000; +} + +/******************************************************************* +yield the difference between *A and *B, in seconds, ignoring leap seconds +********************************************************************/ +static int tm_diff(struct tm *a, struct tm *b) +{ + int ay = a->tm_year + (1900 - 1); + int by = b->tm_year + (1900 - 1); + int intervening_leap_days = + (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); + int years = ay - by; + int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); + int hours = 24*days + (a->tm_hour - b->tm_hour); + int minutes = 60*hours + (a->tm_min - b->tm_min); + int seconds = 60*minutes + (a->tm_sec - b->tm_sec); + + return seconds; +} + + +/** + return the UTC offset in seconds west of UTC, or 0 if it cannot be determined + */ +_PUBLIC_ int get_time_zone(time_t t) +{ + struct tm *tm = gmtime(&t); + struct tm tm_utc; + if (!tm) + return 0; + tm_utc = *tm; + tm = localtime(&t); + if (!tm) + return 0; + return tm_diff(&tm_utc,tm); +} + +/* + * Raw convert an NTTIME to a unix timespec. + */ + +struct timespec nt_time_to_unix_timespec_raw( + NTTIME nt) +{ + int64_t d; + struct timespec ret; + + d = (int64_t)nt; + /* d is now in 100ns units, since jan 1st 1601". + Save off the ns fraction. */ + + /* + * Take the last seven decimal digits and multiply by 100. + * to convert from 100ns units to 1ns units. + */ + ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100); + + /* Convert to seconds */ + d /= 1000*1000*10; + + /* Now adjust by 369 years to make the secs since 1970 */ + d -= TIME_FIXUP_CONSTANT_INT; + + ret.tv_sec = (time_t)d; + return ret; +} + +struct timespec nt_time_to_unix_timespec(NTTIME nt) +{ + struct timespec ret; + + if (nt == 0 || nt == UINT64_MAX) { + ret.tv_sec = 0; + ret.tv_nsec = 0; + return ret; + } + + ret = nt_time_to_unix_timespec_raw(nt); + + if (ret.tv_sec <= TIME_T_MIN) { + ret.tv_sec = TIME_T_MIN; + ret.tv_nsec = 0; + return ret; + } + + if (ret.tv_sec >= TIME_T_MAX) { + ret.tv_sec = TIME_T_MAX; + ret.tv_nsec = 0; + return ret; + } + return ret; +} + + +/** + check if 2 NTTIMEs are equal. +*/ +bool nt_time_equal(NTTIME *t1, NTTIME *t2) +{ + return *t1 == *t2; +} + +/** + Check if it's a null timespec. +**/ + +bool null_timespec(struct timespec ts) +{ + return ts.tv_sec == 0 || + ts.tv_sec == (time_t)0xFFFFFFFF || + ts.tv_sec == (time_t)-1; +} + +/**************************************************************************** + Convert a normalized timeval to a timespec. +****************************************************************************/ + +struct timespec convert_timeval_to_timespec(const struct timeval tv) +{ + struct timespec ts; + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + return ts; +} + +/**************************************************************************** + Convert a normalized timespec to a timeval. +****************************************************************************/ + +struct timeval convert_timespec_to_timeval(const struct timespec ts) +{ + struct timeval tv; + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return tv; +} + +/**************************************************************************** + Return a timespec for the current time +****************************************************************************/ + +_PUBLIC_ struct timespec timespec_current(void) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return ts; +} + +/**************************************************************************** + Return the lesser of two timespecs. +****************************************************************************/ + +struct timespec timespec_min(const struct timespec *ts1, + const struct timespec *ts2) +{ + if (ts1->tv_sec < ts2->tv_sec) return *ts1; + if (ts1->tv_sec > ts2->tv_sec) return *ts2; + if (ts1->tv_nsec < ts2->tv_nsec) return *ts1; + return *ts2; +} + +/**************************************************************************** + compare two timespec structures. + Return -1 if ts1 < ts2 + Return 0 if ts1 == ts2 + Return 1 if ts1 > ts2 +****************************************************************************/ + +_PUBLIC_ int timespec_compare(const struct timespec *ts1, const struct timespec *ts2) +{ + if (ts1->tv_sec > ts2->tv_sec) return 1; + if (ts1->tv_sec < ts2->tv_sec) return -1; + if (ts1->tv_nsec > ts2->tv_nsec) return 1; + if (ts1->tv_nsec < ts2->tv_nsec) return -1; + return 0; +} + +/**************************************************************************** + Round up a timespec if nsec > 500000000, round down if lower, + then zero nsec. +****************************************************************************/ + +void round_timespec_to_sec(struct timespec *ts) +{ + ts->tv_sec = convert_timespec_to_time_t(*ts); + ts->tv_nsec = 0; +} + +/**************************************************************************** + Round a timespec to usec value. +****************************************************************************/ + +void round_timespec_to_usec(struct timespec *ts) +{ + struct timeval tv = convert_timespec_to_timeval(*ts); + *ts = convert_timeval_to_timespec(tv); + normalize_timespec(ts); +} + +/**************************************************************************** + Round a timespec to NTTIME resolution. +****************************************************************************/ + +void round_timespec_to_nttime(struct timespec *ts) +{ + ts->tv_nsec = (ts->tv_nsec / 100) * 100; +} + +/**************************************************************************** + Put a 8 byte filetime from a struct timespec. Uses GMT. +****************************************************************************/ + +_PUBLIC_ NTTIME unix_timespec_to_nt_time(struct timespec ts) +{ + uint64_t d; + + if (ts.tv_sec ==0 && ts.tv_nsec == 0) { + return 0; + } + if (ts.tv_sec == TIME_T_MAX) { + return 0x7fffffffffffffffLL; + } + if (ts.tv_sec == (time_t)-1) { + return UINT64_MAX; + } + + d = ts.tv_sec; + d += TIME_FIXUP_CONSTANT_INT; + d *= 1000*1000*10; + /* d is now in 100ns units. */ + d += (ts.tv_nsec / 100); + + return d; +} + +/* + * Functions supporting the full range of time_t and struct timespec values, + * including 0, -1 and all other negative values. These functions don't use 0 or + * -1 values as sentinel to denote "unset" variables, but use the POSIX 2008 + * define UTIME_OMIT from utimensat(2). + */ + +/** + * Check if it's a to be omitted timespec. + **/ +bool is_omit_timespec(const struct timespec *ts) +{ + return ts->tv_nsec == SAMBA_UTIME_OMIT; +} + +/** + * Return a to be omitted timespec. + **/ +struct timespec make_omit_timespec(void) +{ + return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT}; +} + +/** + * Like unix_timespec_to_nt_time() but without the special casing of tv_sec=0 + * and -1. Also dealing with SAMBA_UTIME_OMIT. + **/ +NTTIME full_timespec_to_nt_time(const struct timespec *_ts) +{ + struct timespec ts = *_ts; + uint64_t d; + + if (is_omit_timespec(_ts)) { + return NTTIME_OMIT; + } + + /* Ensure tv_nsec is less than 1 sec. */ + while (ts.tv_nsec > 1000000000) { + if (ts.tv_sec > TIME_T_MAX) { + return NTTIME_MAX; + } + ts.tv_sec += 1; + ts.tv_nsec -= 1000000000; + } + + if (ts.tv_sec >= TIME_T_MAX) { + return NTTIME_MAX; + } + if ((ts.tv_sec + TIME_FIXUP_CONSTANT_INT) <= 0) { + return NTTIME_MIN; + } + + d = TIME_FIXUP_CONSTANT_INT; + d += ts.tv_sec; + + d *= 1000*1000*10; + /* d is now in 100ns units. */ + d += (ts.tv_nsec / 100); + + return d; +} + +/** + * Like nt_time_to_unix_timespec() but allowing negative tv_sec values and + * returning NTTIME=0 and -1 as struct timespec {.tv_nsec = SAMBA_UTIME_OMIT}. + * + * See also: is_omit_timespec(). + **/ +struct timespec nt_time_to_full_timespec(NTTIME nt) +{ + struct timespec ret; + + if (nt == NTTIME_OMIT) { + return make_omit_timespec(); + } + if (nt == NTTIME_FREEZE || nt == NTTIME_THAW) { + /* + * This should be returned as SAMBA_UTIME_FREEZE or + * SAMBA_UTIME_THAW in the future. + */ + return make_omit_timespec(); + } + if (nt > NTTIME_MAX) { + nt = NTTIME_MAX; + } + + ret = nt_time_to_unix_timespec_raw(nt); + + if (ret.tv_sec >= TIME_T_MAX) { + ret.tv_sec = TIME_T_MAX; + ret.tv_nsec = 0; + return ret; + } + + return ret; +} + +/** + * Note: this function uses the full time_t range as valid date values including + * (time_t)0 and -1. That means that struct timespec sentinel values (cf + * is_omit_timespec()) can't be converted to sentinel values in a time_t + * representation. Callers should therefore check the NTTIME value with + * null_nttime() before calling this function. + **/ +time_t full_timespec_to_time_t(const struct timespec *_ts) +{ + struct timespec ts = *_ts; + + if (is_omit_timespec(_ts)) { + /* + * Unfortunately there's no sensible sentinel value in the + * time_t range that is not conflicting with a valid time value + * ((time_t)0 and -1 are valid time values). Bite the bullit and + * return 0. + */ + return 0; + } + + /* Ensure tv_nsec is less than 1sec. */ + while (ts.tv_nsec > 1000000000) { + ts.tv_sec += 1; + ts.tv_nsec -= 1000000000; + } + + /* 1 ns == 1,000,000,000 - one thousand millionths of a second. + increment if it's greater than 500 millionth of a second. */ + + if (ts.tv_nsec > 500000000) { + return ts.tv_sec + 1; + } + return ts.tv_sec; +} + +/** + * Like nt_time_to_unix() but supports negative time_t values. + * + * Note: this function uses the full time_t range as valid date values including + * (time_t)0 and -1. That means that NTTIME sentinel values of 0 and -1 which + * represent a "not-set" value, can't be converted to sentinel values in a + * time_t representation. Callers should therefore check the NTTIME value with + * null_nttime() before calling this function. + **/ +time_t nt_time_to_full_time_t(NTTIME nt) +{ + struct timespec ts; + + ts = nt_time_to_full_timespec(nt); + return full_timespec_to_time_t(&ts); +} + +/** + * Like time_t_to_unix_timespec() but supports negative time_t values. + * + * This version converts (time_t)0 and -1 to an is_omit_timespec(), so 0 and -1 + * can't be used as valid date values. The function supports values < -1 though. + **/ +struct timespec time_t_to_full_timespec(time_t t) +{ + if (null_time(t)) { + return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT}; + } + return (struct timespec){.tv_sec = t}; +} + +#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) + +/* Old system - no ns timestamp. */ +time_t get_atimensec(const struct stat *st) +{ + return 0; +} + +time_t get_mtimensec(const struct stat *st) +{ + return 0; +} + +time_t get_ctimensec(const struct stat *st) +{ + return 0; +} + +/* Set does nothing with no ns timestamp. */ +void set_atimensec(struct stat *st, time_t ns) +{ + return; +} + +void set_mtimensec(struct stat *st, time_t ns) +{ + return; +} + +void set_ctimensec(struct stat *st, time_t ns) +{ + return; +} + +#elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC + +time_t get_atimensec(const struct stat *st) +{ + return st->st_atimespec.tv_nsec; +} + +time_t get_mtimensec(const struct stat *st) +{ + return st->st_mtimespec.tv_nsec; +} + +time_t get_ctimensec(const struct stat *st) +{ + return st->st_ctimespec.tv_nsec; +} + +void set_atimensec(struct stat *st, time_t ns) +{ + st->st_atimespec.tv_nsec = ns; +} + +void set_mtimensec(struct stat *st, time_t ns) +{ + st->st_mtimespec.tv_nsec = ns; +} + +void set_ctimensec(struct stat *st, time_t ns) +{ + st->st_ctimespec.tv_nsec = ns; +} + +#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + +time_t get_atimensec(const struct stat *st) +{ + return st->st_atim.tv_nsec; +} + +time_t get_mtimensec(const struct stat *st) +{ + return st->st_mtim.tv_nsec; +} + +time_t get_ctimensec(const struct stat *st) +{ + return st->st_ctim.tv_nsec; +} + +void set_atimensec(struct stat *st, time_t ns) +{ + st->st_atim.tv_nsec = ns; +} + +void set_mtimensec(struct stat *st, time_t ns) +{ + st->st_mtim.tv_nsec = ns; +} +void set_ctimensec(struct stat *st, time_t ns) +{ + st->st_ctim.tv_nsec = ns; +} + +#elif HAVE_STRUCT_STAT_ST_MTIMENSEC + +time_t get_atimensec(const struct stat *st) +{ + return st->st_atimensec; +} + +time_t get_mtimensec(const struct stat *st) +{ + return st->st_mtimensec; +} + +time_t get_ctimensec(const struct stat *st) +{ + return st->st_ctimensec; +} + +void set_atimensec(struct stat *st, time_t ns) +{ + st->st_atimensec = ns; +} + +void set_mtimensec(struct stat *st, time_t ns) +{ + st->st_mtimensec = ns; +} + +void set_ctimensec(struct stat *st, time_t ns) +{ + st->st_ctimensec = ns; +} + +#elif HAVE_STRUCT_STAT_ST_MTIME_N + +time_t get_atimensec(const struct stat *st) +{ + return st->st_atime_n; +} + +time_t get_mtimensec(const struct stat *st) +{ + return st->st_mtime_n; +} + +time_t get_ctimensec(const struct stat *st) +{ + return st->st_ctime_n; +} + +void set_atimensec(struct stat *st, time_t ns) +{ + st->st_atime_n = ns; +} + +void set_mtimensec(struct stat *st, time_t ns) +{ + st->st_mtime_n = ns; +} + +void set_ctimensec(struct stat *st, time_t ns) +{ + st->st_ctime_n = ns; +} + +#elif HAVE_STRUCT_STAT_ST_UMTIME + +/* Only usec timestamps available. Convert to/from nsec. */ + +time_t get_atimensec(const struct stat *st) +{ + return st->st_uatime * 1000; +} + +time_t get_mtimensec(const struct stat *st) +{ + return st->st_umtime * 1000; +} + +time_t get_ctimensec(const struct stat *st) +{ + return st->st_uctime * 1000; +} + +void set_atimensec(struct stat *st, time_t ns) +{ + st->st_uatime = ns / 1000; +} + +void set_mtimensec(struct stat *st, time_t ns) +{ + st->st_umtime = ns / 1000; +} + +void set_ctimensec(struct stat *st, time_t ns) +{ + st->st_uctime = ns / 1000; +} + +#else +#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT +#endif + +struct timespec get_atimespec(const struct stat *pst) +{ + struct timespec ret; + + ret.tv_sec = pst->st_atime; + ret.tv_nsec = get_atimensec(pst); + return ret; +} + +struct timespec get_mtimespec(const struct stat *pst) +{ + struct timespec ret; + + ret.tv_sec = pst->st_mtime; + ret.tv_nsec = get_mtimensec(pst); + return ret; +} + +struct timespec get_ctimespec(const struct stat *pst) +{ + struct timespec ret; + + ret.tv_sec = pst->st_ctime; + ret.tv_nsec = get_ctimensec(pst); + return ret; +} + +/**************************************************************************** + Deal with nanoseconds overflow. +****************************************************************************/ + +void normalize_timespec(struct timespec *ts) +{ + lldiv_t dres; + + /* most likely case: nsec is valid */ + if ((unsigned long)ts->tv_nsec < NSEC_PER_SEC) { + return; + } + + dres = lldiv(ts->tv_nsec, NSEC_PER_SEC); + + /* if the operation would result in overflow, max out values and bail */ + if (dres.quot > 0) { + if ((int64_t)LONG_MAX - dres.quot < ts->tv_sec) { + ts->tv_sec = LONG_MAX; + ts->tv_nsec = NSEC_PER_SEC - 1; + return; + } + } else { + if ((int64_t)LONG_MIN - dres.quot > ts->tv_sec) { + ts->tv_sec = LONG_MIN; + ts->tv_nsec = 0; + return; + } + } + + ts->tv_nsec = dres.rem; + ts->tv_sec += dres.quot; + + /* if the ns part was positive or a multiple of -1000000000, we're done */ + if (ts->tv_nsec > 0 || dres.rem == 0) { + return; + } + + ts->tv_nsec += NSEC_PER_SEC; + --ts->tv_sec; +} diff --git a/lib/util/time.h b/lib/util/time.h new file mode 100644 index 0000000..4870c84 --- /dev/null +++ b/lib/util/time.h @@ -0,0 +1,404 @@ +/* + Unix SMB/CIFS implementation. + time utility functions + + Copyright (C) Andrew Tridgell 1992-2004 + Copyright (C) Stefan (metze) Metzmacher 2002 + Copyright (C) Jeremy Allison 2007 + Copyright (C) Andrew Bartlett 2011 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_TIME_H_ +#define _SAMBA_TIME_H_ + +#include <stdbool.h> +#include <stdint.h> +#include <talloc.h> +#include <time.h> + +#ifndef TIME_T_MIN +/* we use 0 here, because (time_t)-1 means error */ +#define TIME_T_MIN 0 +#endif + +/* + * we use the INT32_MAX here as on 64 bit systems, + * gmtime() fails with INT64_MAX + */ +#ifndef TIME_T_MAX +#define TIME_T_MAX MIN(INT32_MAX,_TYPE_MAXIMUM(time_t)) +#endif + +/* + * According to Windows API FileTimeToSystemTime() documentation the highest + * allowed value " ... must be less than 0x8000000000000000.". + */ +#define NTTIME_MAX INT64_MAX + +/* + * The lowest possible value when NTTIME=0 is used as sentinel value. + */ +#define NTTIME_MIN 1 + +/* + * NTTIME_OMIT in a setinfo tells us to not modify the corresponding on-disk + * timestamp value. + */ +#define NTTIME_OMIT 0 + +/* + * Disable automatic timestamp updates, as described in MS-FSA. Samba doesn't + * implement this yet. + */ +#define NTTIME_FREEZE UINT64_MAX +#define NTTIME_THAW (UINT64_MAX - 1) + +#define SAMBA_UTIME_NOW UTIME_NOW +#define SAMBA_UTIME_OMIT UTIME_OMIT + +/* 64 bit time (100 nanosec) 1601 - cifs6.txt, section 3.5, page 30, 4 byte aligned */ +typedef uint64_t NTTIME; + +#define NTTIME_USEC (10UL) +#define NTTIME_MSEC (1000UL * NTTIME_USEC) + +/** + External access to time_t_min and time_t_max. +**/ +time_t get_time_t_max(void); + +/** +a gettimeofday wrapper +**/ +void GetTimeOfDay(struct timeval *tval); + +/** +a wrapper to preferably get the monotonic time +**/ +void clock_gettime_mono(struct timespec *tp); + +/** +a wrapper to preferably get the monotonic time in s +**/ +time_t time_mono(time_t *t); + +/** +interpret an 8 byte "filetime" structure to a time_t +It's originally in "100ns units since jan 1st 1601" +**/ +time_t nt_time_to_unix(NTTIME nt); + +/** +put a 8 byte filetime from a time_t +This takes GMT as input +**/ +void unix_to_nt_time(NTTIME *nt, time_t t); + +/** +check if it's a null unix time +**/ +bool null_time(time_t t); + +/** +check if it's a null NTTIME +**/ +bool null_nttime(NTTIME t); + +/** +put a dos date into a buffer (time/date format) +This takes GMT time and puts local time in the buffer +**/ +void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset); + +/** +put a dos date into a buffer (date/time format) +This takes GMT time and puts local time in the buffer +**/ +void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset); + +/** +put a dos 32 bit "unix like" date into a buffer. This routine takes +GMT and converts it to LOCAL time before putting it (most SMBs assume +localtime for this sort of date) +**/ +void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset); + +/** + create a unix date (int GMT) from a dos date (which is actually in + localtime) +**/ +time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset); + +/** +like make_unix_date() but the words are reversed +**/ +time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset); + +/** + create a unix GMT date from a dos date in 32 bit "unix like" format + these generally arrive as localtimes, with corresponding DST +**/ +time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset); + +/** + Return a date and time as a string (optionally with microseconds) + + format is %Y/%m/%d %H:%M:%S if strftime is available +**/ + +char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires); + +struct timeval_buf; +const char *timespec_string_buf(const struct timespec *tp, + bool hires, + struct timeval_buf *buf); + +/** + Return the current date and time as a string (optionally with microseconds) + + format is %Y/%m/%d %H:%M:%S if strftime is available +**/ +char *current_timestring(TALLOC_CTX *ctx, bool hires); + +/** + Return a date and time as a string (optionally with microseconds) + + format is %Y%m%d_%H%M%S or %Y%m%d_%H%M%S_%us +**/ + +char *minimal_timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires); + +/** + Return the current date and time as a string (optionally with microseconds) + + format is %Y%m%d_%H%M%S or %Y%m%d_%H%M%S_%us +**/ +char *current_minimal_timestring(TALLOC_CTX *ctx, bool hires); + +/** +return a HTTP/1.0 time string +**/ +char *http_timestring(TALLOC_CTX *mem_ctx, time_t t); + +/** + Return the date and time as a string + + format is %a %b %e %X %Y %Z +**/ +char *timestring(TALLOC_CTX *mem_ctx, time_t t); + +/** + return a talloced string representing a NTTIME for human consumption +*/ +const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt); + +/** + put a NTTIME into a packet +*/ +void push_nttime(uint8_t *base, uint16_t offset, NTTIME t); + +/** + pull a NTTIME from a packet +*/ +NTTIME pull_nttime(uint8_t *base, uint16_t offset); + +/** + return (tv1 - tv2) in microseconds +*/ +int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2); + +/** + return (tp1 - tp2) in nanoseconds +*/ +int64_t nsec_time_diff(const struct timespec *tp1, const struct timespec *tp2); + +/** + return a zero timeval +*/ +struct timeval timeval_zero(void); + +/** + return true if a timeval is zero +*/ +bool timeval_is_zero(const struct timeval *tv); + +/** + return a timeval for the current time +*/ +struct timeval timeval_current(void); + +/** + return a timeval struct with the given elements +*/ +struct timeval timeval_set(uint32_t secs, uint32_t usecs); + +/** + return a timeval ofs microseconds after tv +*/ +struct timeval timeval_add(const struct timeval *tv, + uint32_t secs, uint32_t usecs); + +/** + return the sum of two timeval structures +*/ +struct timeval timeval_sum(const struct timeval *tv1, + const struct timeval *tv2); + +/** + return a timeval secs/usecs into the future +*/ +struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs); + +/** + return a timeval milliseconds into the future +*/ +struct timeval timeval_current_ofs_msec(uint32_t msecs); + +/** + return a timeval microseconds into the future +*/ +struct timeval timeval_current_ofs_usec(uint32_t usecs); + +/** + compare two timeval structures. + Return -1 if tv1 < tv2 + Return 0 if tv1 == tv2 + Return 1 if tv1 > tv2 +*/ +int timeval_compare(const struct timeval *tv1, const struct timeval *tv2); + +/** + return true if a timer is in the past +*/ +bool timeval_expired(const struct timeval *tv); + +/** + return the number of seconds elapsed between two times +*/ +double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2); + +/** + return the number of seconds elapsed since a given time +*/ +double timeval_elapsed(const struct timeval *tv); + +/** + return the number of seconds elapsed between two times +*/ +double timespec_elapsed2(const struct timespec *ts1, + const struct timespec *ts2); +/** + return the number of seconds elapsed since a given time +*/ +double timespec_elapsed(const struct timespec *ts); + +/** + return the lesser of two timevals +*/ +struct timeval timeval_min(const struct timeval *tv1, + const struct timeval *tv2); + +/** + return the greater of two timevals +*/ +struct timeval timeval_max(const struct timeval *tv1, + const struct timeval *tv2); + +/** + return the difference between two timevals as a timeval + if tv1 comes after tv2, then return a zero timeval + (this is *tv2 - *tv1) +*/ +struct timeval timeval_until(const struct timeval *tv1, + const struct timeval *tv2); + +/** + convert a timeval to a NTTIME +*/ +NTTIME timeval_to_nttime(const struct timeval *tv); + +/** + convert a NTTIME to a timeval +*/ +void nttime_to_timeval(struct timeval *tv, NTTIME t); + +/** + return the UTC offset in seconds west of UTC, or 0 if it cannot be determined + */ +int get_time_zone(time_t t); + +/** + check if 2 NTTIMEs are equal. +*/ +bool nt_time_equal(NTTIME *t1, NTTIME *t2); + +void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second); + +struct timespec nt_time_to_unix_timespec_raw(NTTIME nt); + +struct timespec nt_time_to_unix_timespec(NTTIME nt); + +time_t convert_timespec_to_time_t(struct timespec ts); + +struct timespec convert_time_t_to_timespec(time_t t); + +bool null_timespec(struct timespec ts); + +struct timespec convert_timeval_to_timespec(const struct timeval tv); +struct timeval convert_timespec_to_timeval(const struct timespec ts); +struct timespec timespec_current(void); +struct timespec timespec_min(const struct timespec *ts1, + const struct timespec *ts2); +int timespec_compare(const struct timespec *ts1, const struct timespec *ts2); +void round_timespec_to_sec(struct timespec *ts); +void round_timespec_to_usec(struct timespec *ts); +void round_timespec_to_nttime(struct timespec *ts); +NTTIME unix_timespec_to_nt_time(struct timespec ts); +void normalize_timespec(struct timespec *ts); + +/* + * Functions supporting the full range of time_t and struct timespec values, + * including 0, -1 and all other negative values. These functions don't use 0 or + * -1 values as sentinel to denote "unset" variables, but use the POSIX 2008 + * define UTIME_OMIT from utimensat(2). + */ +bool is_omit_timespec(const struct timespec *ts); +struct timespec make_omit_timespec(void); +NTTIME full_timespec_to_nt_time(const struct timespec *ts); +struct timespec nt_time_to_full_timespec(NTTIME nt); +time_t full_timespec_to_time_t(const struct timespec *ts); +time_t nt_time_to_full_time_t(NTTIME nt); +struct timespec time_t_to_full_timespec(time_t t); + +/* + * Functions to get and set the number of nanoseconds for times in a stat field. + * If the stat has timestamp granularity less than nanosecond, then the set_* + * operations will be lossy. + */ +struct stat; +time_t get_atimensec(const struct stat *); +time_t get_mtimensec(const struct stat *); +time_t get_ctimensec(const struct stat *); +void set_atimensec(struct stat *, time_t); +void set_mtimensec(struct stat *, time_t); +void set_ctimensec(struct stat *, time_t); + +/* These are convenience wrappers for the above getters. */ +struct timespec get_atimespec(const struct stat *); +struct timespec get_mtimespec(const struct stat *); +struct timespec get_ctimespec(const struct stat *); + +#endif /* _SAMBA_TIME_H_ */ diff --git a/lib/util/time_basic.c b/lib/util/time_basic.c new file mode 100644 index 0000000..095236b --- /dev/null +++ b/lib/util/time_basic.c @@ -0,0 +1,99 @@ +/* + * Unix SMB/CIFS implementation. + * time handling functions + * + * Copyright (C) Andrew Tridgell 1992-2004 + * Copyright (C) Stefan (metze) Metzmacher 2002 + * Copyright (C) Jeremy Allison 2007 + * Copyright (C) Andrew Bartlett 2011 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/time.h" +#include "lib/util/time_basic.h" + +/** +a gettimeofday wrapper +**/ +_PUBLIC_ void GetTimeOfDay(struct timeval *tval) +{ +#if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID) + gettimeofday(tval,NULL); +#else + gettimeofday(tval); +#endif +} + +/**************************************************************************** + Return the date and time as a string +****************************************************************************/ + +char *timeval_str_buf(const struct timeval *tp, bool rfc5424, bool hires, + struct timeval_buf *dst) +{ + time_t t; + struct tm *tm; + size_t len; + + t = (time_t)tp->tv_sec; + tm = localtime(&t); + + if (tm == NULL) { + if (hires) { + snprintf(dst->buf, sizeof(dst->buf), + "%ld.%06ld seconds since the Epoch", + (long)tp->tv_sec, (long)tp->tv_usec); + } else { + snprintf(dst->buf, sizeof(dst->buf), + "%ld seconds since the Epoch", (long)t); + } + return dst->buf; + } + + len = snprintf(dst->buf, sizeof(dst->buf), + (rfc5424 ? + "%04d-%02d-%02dT%02d:%02d:%02d" : + "%04d/%02d/%02d %02d:%02d:%02d"), + 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + if ((rfc5424 || hires) && (len < sizeof(dst->buf))) { + len += snprintf(dst->buf + len, sizeof(dst->buf) - len, + ".%06ld", (long)tp->tv_usec); + } + + if (rfc5424 && (len < sizeof(dst->buf))) { + struct tm tm_utc, tm_local; + int offset; + + tm_local = *tm; + /* It is reasonable to assume that if localtime() + * worked above, then gmtime() should also work + * without error. */ + tm_utc = *gmtime(&t); + + offset = (tm_local.tm_hour - tm_utc.tm_hour) * 60 + + (tm_local.tm_min - tm_utc.tm_min); + + snprintf(dst->buf + len, sizeof(dst->buf) - len, + "%c%02d:%02d", + (offset >=0 ? '+' : '-'), + abs(offset) / 60, + abs(offset) % 60); + } + + return dst->buf; +} diff --git a/lib/util/time_basic.h b/lib/util/time_basic.h new file mode 100644 index 0000000..e04cf1c --- /dev/null +++ b/lib/util/time_basic.h @@ -0,0 +1,49 @@ +/* + * Unix SMB/CIFS implementation. + * time handling functions + * + * Copyright (C) Andrew Tridgell 1992-2004 + * Copyright (C) Stefan (metze) Metzmacher 2002 + * Copyright (C) Jeremy Allison 2007 + * Copyright (C) Andrew Bartlett 2011 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SAMBA_TIME_BASIC_H_ +#define _SAMBA_TIME_BASIC_H_ + +struct timeval; + +/** +a gettimeofday wrapper +**/ +_PUBLIC_ void GetTimeOfDay(struct timeval *tval); + +struct timeval_buf { char buf[128]; }; + +/** + Put a date and time into dst->buf, return it dst->buf + (optionally with microseconds) + + If rfc5424 is true then produce the RFC5424 timestamp format (which + is a stricter instance of RFC3339 and is used for syslog). For + example: 2003-08-24T05:14:15.000003-07:00. Otherwise, + format is %Y/%m/%d %H:%M:%S +**/ + +char *timeval_str_buf(const struct timeval *tp, bool rfc5424, bool hires, + struct timeval_buf *dst); + +#endif /* _SAMBA_TIME_BASIC_H_ */ diff --git a/lib/util/tini.c b/lib/util/tini.c new file mode 100644 index 0000000..36d7a45 --- /dev/null +++ b/lib/util/tini.c @@ -0,0 +1,320 @@ +/* + * Trivial smb.conf parsing code + * + * Copyright Volker Lendecke <vl@samba.org> 2014 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License Version 3 or later, in which case the + * provisions of the GPL are required INSTEAD OF the above restrictions. + * (This clause is necessary due to a potential bad interaction between the + * GPL and the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include "tini.h" + +static bool c_isspace(char c) +{ + unsigned char uc = c; + if (c != uc) { + return false; + } + return isspace(uc); +} + +static int next_content(FILE *f) +{ + int c; + + for (c = fgetc(f); c != EOF; c = fgetc(f)) { + if (!c_isspace(c)) { + break; + } + if (c == '\n') { + break; + } + } + + return c; +} + +static int next_end_of_line(FILE *f) +{ + int c; + + for (c = fgetc(f); c != EOF; c = fgetc(f)) { + if (c == '\n') { + break; + } + } + return c; +} + +static bool make_space(char **buf, size_t *buflen, size_t position) +{ + char *tmp; + + if (position < *buflen) { + return true; + } + tmp = realloc(*buf, (*buflen) * 2); + if (tmp == NULL) { + return false; + } + *buf = tmp; + *buflen *= 2; + return true; +} + +/* + * Get a conf line into *pbuf (which must be a malloc'ed buffer already). + * + * Ignores leading spaces + * Ignores comment lines + * Ignores empty lines + * Takes care of continuation lines + * Zaps multiple spaces into one + */ + +static int get_line(FILE *f, char **pbuf, size_t *pbuflen) +{ + int c; + char *buf; + size_t buflen, pos; + + buf = *pbuf; + buflen = *pbuflen; + pos = 0; + +next_line: + + c = next_content(f); + if (c == EOF) { + return ENOENT; + } + + if ((c == '#') || (c == ';')) { + /* + * Line starting with a comment, skip + */ + c = next_end_of_line(f); + if (c == EOF) { + return ENOENT; + } + goto next_line; + } + + if (c == '\n') { + /* + * Blank line, skip + */ + goto next_line; + } + + for ( ; c != EOF ; c = fgetc(f)) { + + if (c == '\n') { + + if ((pos > 0) && (buf[pos-1] == '\\')) { + /* + * Line ends in "\". Continuation. + */ + pos -= 1; + continue; + } + + if ((pos > 1) && (buf[pos-2] == '\\') && + c_isspace(buf[pos-1])) { + /* + * Line ends in "\ ". Mind that we zap + * multiple spaces into one. Continuation. + */ + pos -= 2; + continue; + } + + /* + * No continuation, done with the line + */ + break; + } + + if ((pos > 0) && c_isspace(buf[pos-1]) && c_isspace(c)) { + /* + * Zap multiple spaces to one + */ + continue; + } + + if (!make_space(&buf, &buflen, pos)) { + return ENOMEM; + } + buf[pos++] = c; + } + + if (!make_space(&buf, &buflen, pos)) { + return ENOMEM; + } + buf[pos++] = '\0'; + + *pbuf = buf; + return 0; +} + +static bool parse_section( + char *buf, bool (*sfunc)(const char *section, void *private_data), + void *private_data) +{ + char *p, *q; + + p = buf+1; /* skip [ */ + + q = strchr(p, ']'); + if (q == NULL) { + return false; + } + *q = '\0'; + + return sfunc(p, private_data); +} + +static char *trim_one_space(char *buf) +{ + size_t len; + + if (c_isspace(buf[0])) { + buf += 1; + } + len = strlen(buf); + if (len == 0) { + return buf; + } + if (c_isspace(buf[len-1])) { + buf[len-1] = '\0'; + } + + return buf; +} + +static bool parse_param(char *buf, + bool allow_empty_value, + bool (*pfunc)(const char *name, const char *value, + void *private_data), + void *private_data) +{ + char *equals; + char *name; + const char *value; + size_t len; + bool no_value = false; + + equals = strchr(buf, '='); + if (equals != NULL) { + *equals = '\0'; + } else { + if (allow_empty_value) { + no_value = true; + } else { + return true; + } + } + + name = trim_one_space(buf); + len = strlen(buf); + if (len == 0) { + return false; + } + + if (no_value) { + value = ""; + } else { + value = trim_one_space(equals+1); + } + + return pfunc(name, value, private_data); +} + +bool tini_parse(FILE *f, + bool allow_empty_value, + bool (*sfunc)(const char *section, void *private_data), + bool (*pfunc)(const char *name, const char *value, + void *private_data), + void *private_data) +{ + char *buf; + size_t buflen; + + buflen = 256; + + buf = malloc(buflen); + if (buf == NULL) { + return false; + } + + while (true) { + int ret; + bool ok; + + ret = get_line(f, &buf, &buflen); + + if (ret == ENOENT) { + /* No lines anymore */ + break; + } + + if (ret != 0) { + /* Real error */ + free(buf); + return false; + } + + switch(buf[0]) { + case 0: + continue; + break; + case '[': + ok = parse_section(buf, sfunc, private_data); + break; + default: + ok = parse_param(buf, allow_empty_value, pfunc, private_data); + break; + } + + if (!ok) { + free(buf); + return false; + } + } + free(buf); + return true; +} diff --git a/lib/util/tini.h b/lib/util/tini.h new file mode 100644 index 0000000..36fc080 --- /dev/null +++ b/lib/util/tini.h @@ -0,0 +1,45 @@ +/* + * Trivial smb.conf parsing code + * + * Copyright Volker Lendecke <vl@samba.org> 2014 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> + +bool tini_parse(FILE *f, + bool allow_empty_value, + bool (*sfunc)(const char *section, void *private_data), + bool (*pfunc)(const char *name, const char *value, + void *private_data), + void *private_data); diff --git a/lib/util/tiniparser.c b/lib/util/tiniparser.c new file mode 100644 index 0000000..428ccff --- /dev/null +++ b/lib/util/tiniparser.c @@ -0,0 +1,390 @@ +/* + * Trivial smb.conf parsing code + * iniparser compatibility layer. + * + * Copyright Jeremy Allison <jra@samba.org> 2014 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License Version 3 or later, in which case the provisions + * of the GPL are required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <stddef.h> +#include "tini.h" +#include "tiniparser.h" + +struct tiniparser_entry { + struct tiniparser_entry *next_entry; + char *key; + char *value; +}; + +struct tiniparser_section { + struct tiniparser_section *next_section; + struct tiniparser_entry *entry_list; + char section_name[]; +}; + +struct tiniparser_dictionary { + struct tiniparser_section *section_list; +}; + +/* + * Find a section from a given key. + * Also return start of subkey. + * Return NULL if section name can't be found, + * if no section name given, or no subkey given. + */ + +static struct tiniparser_section *find_section(struct tiniparser_dictionary *d, + const char *key, + const char **subkey) +{ + struct tiniparser_section *curr_section; + const char *p; + size_t section_len; + + if (key == NULL) { + return NULL; + } + p = strchr(key, ':'); + if (p == NULL) { + /* No section. */ + return NULL; + } + + section_len = p - key; + /* Ensure we have at least one character of section name. */ + if (section_len == 0) { + return NULL; + } + /* Ensure we have at least one character of subkey. */ + if (p[1] == '\0') { + return NULL; + } + + for (curr_section = d->section_list; + curr_section; + curr_section = curr_section->next_section) { + /* + * Check if the key section matches the + * section name *exactly* (with terminating + * null after section_len characters. + */ + if ((strncasecmp(key, curr_section->section_name, section_len) == 0) && + (curr_section->section_name[section_len] == '\0')) { + *subkey = p+1; + return curr_section; + } + } + return NULL; +} + +static struct tiniparser_entry *find_entry(struct tiniparser_section *section, + const char *key) +{ + struct tiniparser_entry *curr_entry; + + for (curr_entry = section->entry_list; + curr_entry; + curr_entry = curr_entry->next_entry) { + if (strcasecmp(key, + curr_entry->key) == 0) { + return curr_entry; + } + } + return NULL; +} + +const char *tiniparser_getstring(struct tiniparser_dictionary *d, + const char *key, + const char *default_value) +{ + struct tiniparser_section *section; + struct tiniparser_entry *entry; + const char *subkey; + + section = find_section(d, key, &subkey); + if (section == NULL) { + return default_value; + } + + entry = find_entry(section, subkey); + if (entry == NULL) { + return default_value; + } + + return entry->value; +} + + +bool tiniparser_getboolean(struct tiniparser_dictionary *d, + const char *key, + bool default_value) +{ + const char *value = tiniparser_getstring(d, key, NULL); + + if (value == NULL) { + return default_value; + } + + switch(value[0]) { + case '1': + case 'T': + case 't': + case 'y': + case 'Y': + return true; + case '0': + case 'F': + case 'f': + case 'n': + case 'N': + return false; + default: + break; + } + + return default_value; +} + +int tiniparser_getint(struct tiniparser_dictionary *d, + const char *key, + int default_value) +{ + const char *value = tiniparser_getstring(d, key, NULL); + + if (value == NULL) { + return default_value; + } + + return (int)strtol(value, NULL, 0); +} + +static bool value_parser(const char *key, + const char *value, + void *private_data) +{ + struct tiniparser_dictionary *d = + (struct tiniparser_dictionary *)private_data; + struct tiniparser_section *section = d->section_list; + struct tiniparser_entry *entry = NULL; + size_t val_len; + size_t key_len; + + if (section == NULL) { + return false; + } + if (key == NULL) { + return false; + } + if (value == NULL) { + return false; + } + + key_len = strlen(key) + 1; + val_len = strlen(value) + 1; + + entry = find_entry(section, key); + if (entry) { + /* Replace current value. */ + char *new_val = malloc(val_len); + if (new_val == NULL) { + return false; + } + memcpy(new_val, value, val_len); + free(entry->value); + entry->value = new_val; + return true; + } + + /* Create a new entry. */ + entry = malloc(sizeof(struct tiniparser_entry)); + if (entry == NULL) { + return false; + } + entry->key = malloc(key_len); + if (entry->key == NULL) { + free(entry); + return false; + } + memcpy(entry->key, key, key_len); + + entry->value = malloc(val_len); + if (entry->value == NULL) { + free(entry->key); + free(entry); + return false; + } + memcpy(entry->value, value, val_len); + + entry->next_entry = section->entry_list; + section->entry_list = entry; + return true; +} + +static bool section_parser(const char *section_name, + void *private_data) +{ + struct tiniparser_section **pp_section; + struct tiniparser_section *new_section; + struct tiniparser_dictionary *d = + (struct tiniparser_dictionary *)private_data; + size_t section_name_len; + + if (section_name == NULL) { + return false; + } + + /* Section names can't contain ':' */ + if (strchr(section_name, ':') != NULL) { + return false; + } + + /* Do we already have this section ? */ + for (pp_section = &d->section_list; + *pp_section; + pp_section = &(*pp_section)->next_section) { + if (strcasecmp(section_name, + (*pp_section)->section_name) == 0) { + /* + * Move to the front of the list for + * value_parser() to find it. + */ + + /* First save current entry. */ + struct tiniparser_section *curr_section = *pp_section; + + /* Now unlink current entry from list. */ + *pp_section = curr_section->next_section; + + /* Make current entry next point to whole list. */ + curr_section->next_section = d->section_list; + + /* And replace list with current entry at start. */ + d->section_list = curr_section; + + return true; + } + } + + section_name_len = strlen(section_name) + 1; + + /* Create new section. */ + new_section = malloc( + offsetof(struct tiniparser_section, section_name) + + section_name_len); + if (new_section == NULL) { + return false; + } + + memcpy(new_section->section_name, section_name, section_name_len); + + new_section->entry_list = NULL; + + /* Add it to the head of the singly linked list. */ + new_section->next_section = d->section_list; + d->section_list = new_section; + return true; +} + +struct tiniparser_dictionary *tiniparser_load_stream(FILE *fp) +{ + bool ret; + struct tiniparser_dictionary *d = NULL; + + d = malloc(sizeof(struct tiniparser_dictionary)); + if (d == NULL) { + return NULL; + } + d->section_list = NULL; + + ret = tini_parse(fp, + false, + section_parser, + value_parser, + d); + if (ret == false) { + tiniparser_freedict(d); + d = NULL; + } + return d; +} + +struct tiniparser_dictionary *tiniparser_load(const char *filename) +{ + struct tiniparser_dictionary *d; + FILE *fp = fopen(filename, "r"); + + if (fp == NULL) { + return NULL; + } + + d = tiniparser_load_stream(fp); + + fclose(fp); + + return d; +} + +void tiniparser_freedict(struct tiniparser_dictionary *d) +{ + struct tiniparser_section *curr_section, *next_section; + + if (d == NULL) { + return; + } + + for (curr_section = d->section_list; + curr_section; + curr_section = next_section) { + struct tiniparser_entry *curr_entry, *next_entry; + + next_section = curr_section->next_section; + + for (curr_entry = curr_section->entry_list; + curr_entry; + curr_entry = next_entry) { + next_entry = curr_entry->next_entry; + + free(curr_entry->key); + free(curr_entry->value); + free(curr_entry); + } + free(curr_section); + } + free(d); +} diff --git a/lib/util/tiniparser.h b/lib/util/tiniparser.h new file mode 100644 index 0000000..5356b22 --- /dev/null +++ b/lib/util/tiniparser.h @@ -0,0 +1,56 @@ +#ifndef _TINIPARSER_H_ +#define _TINIPARSER_H_ +/* + * Trivial smb.conf parsing code + * iniparser compatibility layer. + * + * Copyright Jeremy Allison <jra@samba.org> 2014 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +struct tiniparser_dictionary; + +bool tiniparser_getboolean(struct tiniparser_dictionary *d, + const char *key, + bool default_value); +const char *tiniparser_getstring(struct tiniparser_dictionary *d, + const char *key, + const char *default_value); +int tiniparser_getint(struct tiniparser_dictionary *d, + const char *key, + int default_value); +struct tiniparser_dictionary *tiniparser_load_stream(FILE *fp); +struct tiniparser_dictionary *tiniparser_load(const char *filename); +void tiniparser_freedict(struct tiniparser_dictionary *d); + +#endif diff --git a/lib/util/tsort.h b/lib/util/tsort.h new file mode 100644 index 0000000..811d6cd --- /dev/null +++ b/lib/util/tsort.h @@ -0,0 +1,40 @@ +/* + Unix SMB/CIFS implementation. + + typesafe qsort + + Copyright (C) Andrew Tridgell 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _TSORT_H +#define _TSORT_H +#include <assert.h> + +/* + a wrapper around qsort() that ensures the comparison function is + type safe. + */ +#ifndef TYPESAFE_QSORT +#define TYPESAFE_QSORT(base, numel, comparison) \ +do { \ + if (numel > 1) { \ + qsort(base, numel, sizeof((base)[0]), (int (*)(const void *, const void *))comparison); \ + assert(comparison(&((base)[0]), &((base)[1])) <= 0); \ + } \ +} while (0) +#endif + +#endif diff --git a/lib/util/unix_match.c b/lib/util/unix_match.c new file mode 100644 index 0000000..38edc18 --- /dev/null +++ b/lib/util/unix_match.c @@ -0,0 +1,183 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jeremy Allison 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include <talloc.h> +#include "lib/util/talloc_stack.h" +#include "lib/util/charset/charset.h" +#include "lib/util/unix_match.h" + +/********************************************************* + Recursive routine that is called by unix_wild_match. +*********************************************************/ + +static bool unix_do_match(const char *regexp, const char *str) +{ + const char *p; + + for( p = regexp; *p && *str; ) { + + switch(*p) { + case '?': + str++; + p++; + break; + + case '*': + + /* + * Look for a character matching + * the one after the '*'. + */ + p++; + if(!*p) { + return true; /* Automatic match */ + } + while(*str) { + + while(*str && (*p != *str)) { + str++; + } + + /* + * Patch from weidel@multichart.de. + * In the case of the regexp + * '*XX*' we want to ensure there are + * at least 2 'X' characters in the + * string after the '*' for a match to + * be made. + */ + + { + int matchcount=0; + + /* + * Eat all the characters that + * match, but count how many + * there were. + */ + + while(*str && (*p == *str)) { + str++; + matchcount++; + } + + /* + * Now check that if the regexp + * had n identical characters + * that matchcount had at least + * that many matches. + */ + + while (*(p+1) && (*(p+1)==*p)) { + p++; + matchcount--; + } + + if ( matchcount <= 0 ) { + return false; + } + } + + /* + * We've eaten the match char + * after the '*' + */ + str--; + + if(unix_do_match(p, str)) { + return true; + } + + if(!*str) { + return false; + } else { + str++; + } + } + return false; + + default: + if(*str != *p) { + return false; + } + str++; + p++; + break; + } + } + + if(!*p && !*str) { + return true; + } + + if (!*p && str[0] == '.' && str[1] == 0) { + return true; + } + + if (!*str && *p == '?') { + while (*p == '?') { + p++; + } + return(!*p); + } + + if(!*str && (*p == '*' && p[1] == '\0')) { + return true; + } + + return false; +} + +/******************************************************************* + Simple case insensitive interface to a UNIX wildcard matcher. + Returns True if match, False if not. +*******************************************************************/ + +bool unix_wild_match(const char *pattern, const char *string) +{ + TALLOC_CTX *ctx = talloc_stackframe(); + char *p2; + char *s2; + char *p; + bool ret = false; + + p2 = strlower_talloc(ctx, pattern); + s2 = strlower_talloc(ctx, string); + if (!p2 || !s2) { + TALLOC_FREE(ctx); + return false; + } + + /* Remove any *? and ** from the pattern as they are meaningless */ + for(p = p2; *p; p++) { + while( *p == '*' && (p[1] == '?' ||p[1] == '*')) { + memmove(&p[1], &p[2], strlen(&p[2])+1); + } + } + + if (p2[0] == '*' && p2[1] == '\0') { + TALLOC_FREE(ctx); + return true; + } + + ret = unix_do_match(p2, s2); + TALLOC_FREE(ctx); + return ret; +} diff --git a/lib/util/unix_match.h b/lib/util/unix_match.h new file mode 100644 index 0000000..a7b6935 --- /dev/null +++ b/lib/util/unix_match.h @@ -0,0 +1,25 @@ +/* + Unix SMB/CIFS implementation. + Utility functions for Samba + Copyright (C) Jeremy Allison 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _UNIX_MASK_H_ +#define _UNIX_MASK_H_ + +bool unix_wild_match(const char *pattern, const char *string); + +#endif diff --git a/lib/util/unix_privs.c b/lib/util/unix_privs.c new file mode 100644 index 0000000..9f28432 --- /dev/null +++ b/lib/util/unix_privs.c @@ -0,0 +1,92 @@ +/* + Unix SMB/CIFS implementation. + + gain/lose root privileges + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include <talloc.h> +#include "lib/util/fault.h" +#include "system/passwd.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "../lib/util/unix_privs.h" +#include "../lib/util/setid.h" + +/** + * @file + * @brief Gaining/losing root privileges + */ + +/* + there are times when smbd needs to temporarily gain root privileges + to do some operation. To do this you call root_privileges(), which + returns a talloc handle. To restore your previous privileges + talloc_free() this pointer. + + Note that this call is considered successful even if it does not + manage to gain root privileges, but it will call smb_abort() if it + fails to restore the privileges afterwards. The logic is that + failing to gain root access can be caught by whatever operation + needs to be run as root failing, but failing to lose the root + privileges is dangerous. + + This also means that this code is safe to be called from completely + unprivileged processes. +*/ + +struct saved_state { + uid_t uid; +}; + +static int privileges_destructor(struct saved_state *s) +{ + if (geteuid() != s->uid && + samba_seteuid(s->uid) != 0) { + smb_panic("Failed to restore privileges"); + } + return 0; +} + +/** + * Obtain root privileges for the current process. + * + * The privileges can be dropped by talloc_free()-ing the + * token returned by this function + */ +void *root_privileges(void) +{ + struct saved_state *s; + s = talloc(NULL, struct saved_state); + if (!s) return NULL; + s->uid = geteuid(); + if (s->uid != 0) { + samba_seteuid(0); + } + talloc_set_destructor(s, privileges_destructor); + return s; +} + +uid_t root_privileges_original_uid(void *s) +{ + struct saved_state *saved = talloc_get_type_abort(s, struct saved_state); + return saved->uid; +} diff --git a/lib/util/util.c b/lib/util/util.c new file mode 100644 index 0000000..5f9310e --- /dev/null +++ b/lib/util/util.c @@ -0,0 +1,1335 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001-2002 + Copyright (C) Simo Sorce 2001-2011 + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + Copyright (C) James J Myers 2003 + Copyright (C) Volker Lendecke 2010 + Copyright (C) Swen Schillig 2019 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include <talloc.h> +#include <tevent.h> +#include "system/network.h" +#include "system/filesys.h" +#include "system/locale.h" +#include "system/shmem.h" +#include "system/passwd.h" +#include "system/time.h" +#include "system/wait.h" +#include "debug.h" +#include "samba_util.h" +#include "lib/util/select.h" +#include <libgen.h> +#include <gnutls/gnutls.h> + +#ifdef HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif + +#undef malloc +#undef strcasecmp +#undef strncasecmp +#undef strdup +#undef realloc +#undef calloc + +/** + * @file + * @brief Misc utility functions + */ + +/** + Find a suitable temporary directory. The result should be copied immediately + as it may be overwritten by a subsequent call. +**/ +_PUBLIC_ const char *tmpdir(void) +{ + char *p; + if ((p = getenv("TMPDIR"))) + return p; + return "/tmp"; +} + + +/** + Create a tmp file, open it and immediately unlink it. + If dir is NULL uses tmpdir() + Returns the file descriptor or -1 on error. +**/ +int create_unlink_tmp(const char *dir) +{ + size_t len = strlen(dir ? dir : (dir = tmpdir())); + char fname[len+25]; + int fd; + mode_t mask; + + len = snprintf(fname, sizeof(fname), "%s/listenerlock_XXXXXX", dir); + if (len >= sizeof(fname)) { + errno = ENOMEM; + return -1; + } + mask = umask(S_IRWXO | S_IRWXG); + fd = mkstemp(fname); + umask(mask); + if (fd == -1) { + return -1; + } + if (unlink(fname) == -1) { + int sys_errno = errno; + close(fd); + errno = sys_errno; + return -1; + } + return fd; +} + + +/** + Check if a file exists - call vfs_file_exist for samba files. +**/ +_PUBLIC_ bool file_exist(const char *fname) +{ + struct stat st; + + if (stat(fname, &st) != 0) { + return false; + } + + return ((S_ISREG(st.st_mode)) || (S_ISFIFO(st.st_mode))); +} + +/** + * @brief Return a files modification time. + * + * @param fname The name of the file. + * + * @param mt A pointer to store the modification time. + * + * @return 0 on success, errno otherwise. + */ +_PUBLIC_ int file_modtime(const char *fname, struct timespec *mt) +{ + struct stat st = {0}; + + if (stat(fname, &st) != 0) { + return errno; + } + + *mt = get_mtimespec(&st); + return 0; +} + +/** + Check file permissions. +**/ + +_PUBLIC_ bool file_check_permissions(const char *fname, + uid_t uid, + mode_t file_perms, + struct stat *pst) +{ + int ret; + struct stat st; + + if (pst == NULL) { + pst = &st; + } + + ZERO_STRUCTP(pst); + + ret = stat(fname, pst); + if (ret != 0) { + DEBUG(0, ("stat failed on file '%s': %s\n", + fname, strerror(errno))); + return false; + } + + if (pst->st_uid != uid && !uid_wrapper_enabled()) { + DEBUG(0, ("invalid ownership of file '%s': " + "owned by uid %u, should be %u\n", + fname, (unsigned int)pst->st_uid, + (unsigned int)uid)); + return false; + } + + if ((pst->st_mode & 0777) != file_perms) { + DEBUG(0, ("invalid permissions on file " + "'%s': has 0%o should be 0%o\n", fname, + (unsigned int)(pst->st_mode & 0777), + (unsigned int)file_perms)); + return false; + } + + return true; +} + +/** + Check if a directory exists. +**/ + +_PUBLIC_ bool directory_exist(const char *dname) +{ + struct stat st; + bool ret; + + if (stat(dname,&st) != 0) { + return false; + } + + ret = S_ISDIR(st.st_mode); + if(!ret) + errno = ENOTDIR; + return ret; +} + +/** + * Try to create the specified directory if it didn't exist. + * A symlink to a directory is also accepted as a valid existing directory. + * + * @retval true if the directory already existed + * or was successfully created. + */ +_PUBLIC_ bool directory_create_or_exist(const char *dname, + mode_t dir_perms) +{ + int ret; + mode_t old_umask; + + /* Create directory */ + old_umask = umask(0); + ret = mkdir(dname, dir_perms); + if (ret == -1 && errno != EEXIST) { + int dbg_level = geteuid() == 0 ? DBGLVL_ERR : DBGLVL_NOTICE; + + DBG_PREFIX(dbg_level, + ("mkdir failed on directory %s: %s\n", + dname, + strerror(errno))); + umask(old_umask); + return false; + } + umask(old_umask); + + if (ret != 0 && errno == EEXIST) { + struct stat sbuf; + + ret = lstat(dname, &sbuf); + if (ret != 0) { + return false; + } + + if (S_ISDIR(sbuf.st_mode)) { + return true; + } + + if (S_ISLNK(sbuf.st_mode)) { + ret = stat(dname, &sbuf); + if (ret != 0) { + return false; + } + + if (S_ISDIR(sbuf.st_mode)) { + return true; + } + } + + return false; + } + + return true; +} + +_PUBLIC_ bool directory_create_or_exists_recursive( + const char *dname, + mode_t dir_perms) +{ + bool ok; + + ok = directory_create_or_exist(dname, dir_perms); + if (!ok) { + if (!directory_exist(dname)) { + char tmp[PATH_MAX] = {0}; + char *parent = NULL; + size_t n; + + /* Use the null context */ + n = strlcpy(tmp, dname, sizeof(tmp)); + if (n < strlen(dname)) { + DBG_ERR("Path too long!\n"); + return false; + } + + parent = dirname(tmp); + if (parent == NULL) { + DBG_ERR("Failed to create dirname!\n"); + return false; + } + + ok = directory_create_or_exists_recursive(parent, + dir_perms); + if (!ok) { + return false; + } + + ok = directory_create_or_exist(dname, dir_perms); + } + } + + return ok; +} + +/** + * @brief Try to create a specified directory if it doesn't exist. + * + * The function creates a directory with the given uid and permissions if it + * doesn't exist. If it exists it makes sure the uid and permissions are + * correct and it will fail if they are different. + * + * @param[in] dname The directory to create. + * + * @param[in] uid The uid the directory needs to belong too. + * + * @param[in] dir_perms The expected permissions of the directory. + * + * @return True on success, false on error. + */ +_PUBLIC_ bool directory_create_or_exist_strict(const char *dname, + uid_t uid, + mode_t dir_perms) +{ + struct stat st; + bool ok; + int rc; + + ok = directory_create_or_exist(dname, dir_perms); + if (!ok) { + return false; + } + + rc = lstat(dname, &st); + if (rc == -1) { + DEBUG(0, ("lstat failed on created directory %s: %s\n", + dname, strerror(errno))); + return false; + } + + /* Check ownership and permission on existing directory */ + if (!S_ISDIR(st.st_mode)) { + DEBUG(0, ("directory %s isn't a directory\n", + dname)); + return false; + } + if (st.st_uid != uid && !uid_wrapper_enabled()) { + DBG_NOTICE("invalid ownership on directory " + "%s\n", dname); + return false; + } + if ((st.st_mode & 0777) != dir_perms) { + DEBUG(0, ("invalid permissions on directory " + "'%s': has 0%o should be 0%o\n", dname, + (unsigned int)(st.st_mode & 0777), (unsigned int)dir_perms)); + return false; + } + + return true; +} + + +/** + Sleep for a specified number of milliseconds. +**/ + +_PUBLIC_ void smb_msleep(unsigned int t) +{ + sys_poll_intr(NULL, 0, t); +} + +/** + Get my own name, return in talloc'ed storage. +**/ + +_PUBLIC_ char *get_myname(TALLOC_CTX *ctx) +{ + char *p; + char hostname[HOST_NAME_MAX]; + + /* get my host name */ + if (gethostname(hostname, sizeof(hostname)) == -1) { + DEBUG(0,("gethostname failed\n")); + return NULL; + } + + /* Ensure null termination. */ + hostname[sizeof(hostname)-1] = '\0'; + + /* split off any parts after an initial . */ + p = strchr_m(hostname, '.'); + if (p) { + *p = 0; + } + + return talloc_strdup(ctx, hostname); +} + +/** + Check if a process exists. Does this work on all unixes? +**/ + +_PUBLIC_ bool process_exists_by_pid(pid_t pid) +{ + /* Doing kill with a non-positive pid causes messages to be + * sent to places we don't want. */ + if (pid <= 0) { + return false; + } + return(kill(pid,0) == 0 || errno != ESRCH); +} + +/** + Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping + is dealt with in posix.c +**/ + +_PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type) +{ + struct flock lock; + int ret; + + DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type)); + + lock.l_type = type; + lock.l_whence = SEEK_SET; + lock.l_start = offset; + lock.l_len = count; + lock.l_pid = 0; + + ret = fcntl(fd,op,&lock); + + if (ret == -1 && errno != 0) + DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno))); + + /* a lock query */ + if (op == F_GETLK) { + if ((ret != -1) && + (lock.l_type != F_UNLCK) && + (lock.l_pid != 0) && + (lock.l_pid != tevent_cached_getpid())) { + DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid)); + return true; + } + + /* it must be not locked or locked by me */ + return false; + } + + /* a lock set or unset */ + if (ret == -1) { + DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n", + (double)offset,(double)count,op,type,strerror(errno))); + return false; + } + + /* everything went OK */ + DEBUG(8,("fcntl_lock: Lock call successful\n")); + + return true; +} + +struct debug_channel_level { + int channel; + int level; +}; + +static void debugadd_channel_cb(const char *buf, void *private_data) +{ + struct debug_channel_level *dcl = + (struct debug_channel_level *)private_data; + + DEBUGADDC(dcl->channel, dcl->level,("%s", buf)); +} + +static void debugadd_cb(const char *buf, void *private_data) +{ + int *plevel = (int *)private_data; + DEBUGADD(*plevel, ("%s", buf)); +} + +void print_asc_cb(const uint8_t *buf, int len, + void (*cb)(const char *buf, void *private_data), + void *private_data) +{ + int i; + char s[2]; + s[1] = 0; + + for (i=0; i<len; i++) { + s[0] = isprint(buf[i]) ? buf[i] : '.'; + cb(s, private_data); + } +} + +void print_asc(int level, const uint8_t *buf,int len) +{ + print_asc_cb(buf, len, debugadd_cb, &level); +} + +static void dump_data_block16(const char *prefix, size_t idx, + const uint8_t *buf, size_t len, + void (*cb)(const char *buf, void *private_data), + void *private_data) +{ + char tmp[16]; + size_t i; + + SMB_ASSERT(len <= 16); + + snprintf(tmp, sizeof(tmp), "%s[%04zX]", prefix, idx); + cb(tmp, private_data); + + for (i=0; i<16; i++) { + if (i == 8) { + cb(" ", private_data); + } + if (i < len) { + snprintf(tmp, sizeof(tmp), " %02X", (int)buf[i]); + } else { + snprintf(tmp, sizeof(tmp), " "); + } + cb(tmp, private_data); + } + + cb(" ", private_data); + + if (len == 0) { + cb("EMPTY BLOCK\n", private_data); + return; + } + + for (i=0; i<len; i++) { + if (i == 8) { + cb(" ", private_data); + } + print_asc_cb(&buf[i], 1, cb, private_data); + } + + cb("\n", private_data); +} + +/** + * Write dump of binary data to a callback + */ +void dump_data_cb(const uint8_t *buf, int len, + bool omit_zero_bytes, + void (*cb)(const char *buf, void *private_data), + void *private_data) +{ + int i=0; + bool skipped = false; + + if (len<=0) return; + + for (i=0;i<len;i+=16) { + size_t remaining_len = len - i; + size_t this_len = MIN(remaining_len, 16); + const uint8_t *this_buf = &buf[i]; + + if ((omit_zero_bytes == true) && + (i > 0) && (remaining_len > 16) && + (this_len == 16) && all_zero(this_buf, 16)) + { + if (!skipped) { + cb("skipping zero buffer bytes\n", + private_data); + skipped = true; + } + continue; + } + + skipped = false; + dump_data_block16("", i, this_buf, this_len, + cb, private_data); + } +} + +/** + * Write dump of binary data to the log file. + * + * The data is only written if the log level is at least level. + */ +_PUBLIC_ void dump_data(int level, const uint8_t *buf, int len) +{ + if (!DEBUGLVL(level)) { + return; + } + dump_data_cb(buf, len, false, debugadd_cb, &level); +} + +/** + * Write dump of binary data to the log file. + * + * The data is only written if the log level is at least level for + * debug class dbgc_class. + */ +_PUBLIC_ void dump_data_dbgc(int dbgc_class, int level, const uint8_t *buf, int len) +{ + struct debug_channel_level dcl = { dbgc_class, level }; + + if (!DEBUGLVLC(dbgc_class, level)) { + return; + } + dump_data_cb(buf, len, false, debugadd_channel_cb, &dcl); +} + +/** + * Write dump of binary data to the log file. + * + * The data is only written if the log level is at least level. + * 16 zero bytes in a row are omitted + */ +_PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len) +{ + if (!DEBUGLVL(level)) { + return; + } + dump_data_cb(buf, len, true, debugadd_cb, &level); +} + +static void fprintf_cb(const char *buf, void *private_data) +{ + FILE *f = (FILE *)private_data; + fprintf(f, "%s", buf); +} + +void dump_data_file(const uint8_t *buf, int len, bool omit_zero_bytes, + FILE *f) +{ + dump_data_cb(buf, len, omit_zero_bytes, fprintf_cb, f); +} + +/** + * Write dump of compared binary data to a callback + */ +void dump_data_diff_cb(const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2, + bool omit_zero_bytes, + void (*cb)(const char *buf, void *private_data), + void *private_data) +{ + size_t len = MAX(len1, len2); + size_t i; + bool skipped = false; + + for (i=0; i<len; i+=16) { + size_t remaining_len = len - i; + size_t remaining_len1 = 0; + size_t this_len1 = 0; + const uint8_t *this_buf1 = NULL; + size_t remaining_len2 = 0; + size_t this_len2 = 0; + const uint8_t *this_buf2 = NULL; + + if (i < len1) { + remaining_len1 = len1 - i; + this_len1 = MIN(remaining_len1, 16); + this_buf1 = &buf1[i]; + } + if (i < len2) { + remaining_len2 = len2 - i; + this_len2 = MIN(remaining_len2, 16); + this_buf2 = &buf2[i]; + } + + if ((omit_zero_bytes == true) && + (i > 0) && (remaining_len > 16) && + (this_len1 == 16) && all_zero(this_buf1, 16) && + (this_len2 == 16) && all_zero(this_buf2, 16)) + { + if (!skipped) { + cb("skipping zero buffer bytes\n", + private_data); + skipped = true; + } + continue; + } + + skipped = false; + + if ((this_len1 == this_len2) && + (memcmp(this_buf1, this_buf2, this_len1) == 0)) + { + dump_data_block16(" ", i, this_buf1, this_len1, + cb, private_data); + continue; + } + + dump_data_block16("-", i, this_buf1, this_len1, + cb, private_data); + dump_data_block16("+", i, this_buf2, this_len2, + cb, private_data); + } +} + +_PUBLIC_ void dump_data_diff(int dbgc_class, int level, + bool omit_zero_bytes, + const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2) +{ + struct debug_channel_level dcl = { dbgc_class, level }; + + if (!DEBUGLVLC(dbgc_class, level)) { + return; + } + dump_data_diff_cb(buf1, len1, buf2, len2, true, debugadd_channel_cb, &dcl); +} + +_PUBLIC_ void dump_data_file_diff(FILE *f, + bool omit_zero_bytes, + const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2) +{ + dump_data_diff_cb(buf1, len1, buf2, len2, omit_zero_bytes, fprintf_cb, f); +} + +/** + malloc that aborts with smb_panic on fail or zero size. +**/ + +_PUBLIC_ void *smb_xmalloc(size_t size) +{ + void *p; + if (size == 0) + smb_panic("smb_xmalloc: called with zero size.\n"); + if ((p = malloc(size)) == NULL) + smb_panic("smb_xmalloc: malloc fail.\n"); + return p; +} + +/** + Memdup with smb_panic on fail. +**/ + +_PUBLIC_ void *smb_xmemdup(const void *p, size_t size) +{ + void *p2; + p2 = smb_xmalloc(size); + memcpy(p2, p, size); + return p2; +} + +/** + strdup that aborts on malloc fail. +**/ + +char *smb_xstrdup(const char *s) +{ +#if defined(PARANOID_MALLOC_CHECKER) +#ifdef strdup +#undef strdup +#endif +#endif + +#ifndef HAVE_STRDUP +#define strdup rep_strdup +#endif + + char *s1 = strdup(s); +#if defined(PARANOID_MALLOC_CHECKER) +#ifdef strdup +#undef strdup +#endif +#define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY +#endif + if (!s1) { + smb_panic("smb_xstrdup: malloc failed"); + } + return s1; + +} + +/** + strndup that aborts on malloc fail. +**/ + +char *smb_xstrndup(const char *s, size_t n) +{ +#if defined(PARANOID_MALLOC_CHECKER) +#ifdef strndup +#undef strndup +#endif +#endif + +#if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP)) +#undef HAVE_STRNDUP +#define strndup rep_strndup +#endif + + char *s1 = strndup(s, n); +#if defined(PARANOID_MALLOC_CHECKER) +#ifdef strndup +#undef strndup +#endif +#define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY +#endif + if (!s1) { + smb_panic("smb_xstrndup: malloc failed"); + } + return s1; +} + + + +/** + Like strdup but for memory. +**/ + +_PUBLIC_ void *smb_memdup(const void *p, size_t size) +{ + void *p2; + if (size == 0) + return NULL; + p2 = malloc(size); + if (!p2) + return NULL; + memcpy(p2, p, size); + return p2; +} + +/** + * Write a password to the log file. + * + * @note Only actually does something if DEBUG_PASSWORD was defined during + * compile-time. + */ +_PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len) +{ +#ifdef DEBUG_PASSWORD + DEBUG(11, ("%s", msg)); + if (data != NULL && len > 0) + { + dump_data(11, data, len); + } +#endif +} + +static void dump_data_addbuf_cb(const char *buf, void *private_data) +{ + char **str = private_data; + talloc_asprintf_addbuf(str, "%s", buf); +} + +_PUBLIC_ void dump_data_addbuf(const uint8_t *buf, size_t buflen, char **str) +{ + dump_data_cb(buf, buflen, false, dump_data_addbuf_cb, str); +} + + +/** + * see if a range of memory is all zero. A NULL pointer is considered + * to be all zero + */ +_PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size) +{ + size_t i; + if (!ptr) return true; + for (i=0;i<size;i++) { + if (ptr[i]) return false; + } + return true; +} + +/** + realloc an array, checking for integer overflow in the array size +*/ +_PUBLIC_ void *realloc_array(void *ptr, size_t el_size, unsigned count, bool free_on_fail) +{ +#define MAX_MALLOC_SIZE 0x7fffffff + if (count == 0 || + count >= MAX_MALLOC_SIZE/el_size) { + if (free_on_fail) + SAFE_FREE(ptr); + return NULL; + } + if (!ptr) { + return malloc(el_size * count); + } + return realloc(ptr, el_size * count); +} + +/**************************************************************************** + Type-safe malloc. +****************************************************************************/ + +void *malloc_array(size_t el_size, unsigned int count) +{ + return realloc_array(NULL, el_size, count, false); +} + +/**************************************************************************** + Type-safe memalign +****************************************************************************/ + +void *memalign_array(size_t el_size, size_t align, unsigned int count) +{ + if (el_size == 0 || count >= MAX_MALLOC_SIZE/el_size) { + return NULL; + } + + return memalign(align, el_size*count); +} + +/**************************************************************************** + Type-safe calloc. +****************************************************************************/ + +void *calloc_array(size_t size, size_t nmemb) +{ + if (nmemb >= MAX_MALLOC_SIZE/size) { + return NULL; + } + if (size == 0 || nmemb == 0) { + return NULL; + } + return calloc(nmemb, size); +} + +/** + Trim the specified elements off the front and back of a string. +**/ +_PUBLIC_ bool trim_string(char *s, const char *front, const char *back) +{ + bool ret = false; + size_t front_len; + size_t back_len; + size_t len; + + /* Ignore null or empty strings. */ + if (!s || (s[0] == '\0')) { + return false; + } + len = strlen(s); + + front_len = front? strlen(front) : 0; + back_len = back? strlen(back) : 0; + + if (front_len) { + size_t front_trim = 0; + + while (strncmp(s+front_trim, front, front_len)==0) { + front_trim += front_len; + } + if (front_trim > 0) { + /* Must use memmove here as src & dest can + * easily overlap. Found by valgrind. JRA. */ + memmove(s, s+front_trim, (len-front_trim)+1); + len -= front_trim; + ret=true; + } + } + + if (back_len) { + while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) { + s[len-back_len]='\0'; + len -= back_len; + ret=true; + } + } + return ret; +} + +/** + Find the number of 'c' chars in a string +**/ +_PUBLIC_ _PURE_ size_t count_chars(const char *s, char c) +{ + size_t count = 0; + + while (*s) { + if (*s == c) count++; + s ++; + } + + return count; +} + +/** + * Routine to get hex characters and turn them into a byte array. + * the array can be variable length. + * - "0xnn" or "0Xnn" is specially catered for. + * - The first non-hex-digit character (apart from possibly leading "0x" + * finishes the conversion and skips the rest of the input. + * - A single hex-digit character at the end of the string is skipped. + * + * valid examples: "0A5D15"; "0x123456" + */ +_PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len) +{ + size_t i = 0; + size_t num_chars = 0; + + /* skip leading 0x prefix */ + if (strncasecmp(strhex, "0x", 2) == 0) { + i += 2; /* skip two chars */ + } + + while ((i < strhex_len) && (num_chars < p_len)) { + bool ok = hex_byte(&strhex[i], (uint8_t *)&p[num_chars]); + if (!ok) { + break; + } + i += 2; + num_chars += 1; + } + + return num_chars; +} + +/** + * Parse a hex string and return a data blob. + */ +_PUBLIC_ DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex) +{ + DATA_BLOB ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1); + if (ret_blob.data == NULL) { + /* ret_blob.length is already 0 */ + return ret_blob; + } + ret_blob.length = strhex_to_str((char *)ret_blob.data, ret_blob.length, + strhex, + strlen(strhex)); + + return ret_blob; +} + +/** + * Parse a hex dump and return a data blob. Hex dump is structured as + * is generated from dump_data_cb() elsewhere in this file + * + */ +_PUBLIC_ DATA_BLOB hexdump_to_data_blob(TALLOC_CTX *mem_ctx, const char *hexdump, size_t hexdump_len) +{ + DATA_BLOB ret_blob = { 0 }; + size_t i = 0; + size_t char_count = 0; + /* hexdump line length is 77 chars long. We then use the ASCII representation of the bytes + * at the end of the final line to calculate how many are in that line, minus the extra space + * and newline. */ + size_t hexdump_byte_count = (16 * (hexdump_len / 77)); + if (hexdump_len % 77) { + hexdump_byte_count += ((hexdump_len % 77) - 59 - 2); + } + + ret_blob = data_blob_talloc(mem_ctx, NULL, hexdump_byte_count+1); + for (; i+1 < hexdump_len && hexdump[i] != 0 && hexdump[i+1] != 0; i++) { + if ((i%77) == 0) + i += 7; /* Skip the offset at the start of the line */ + if ((i%77) < 56) { /* position 56 is after both hex chunks */ + if (hexdump[i] != ' ') { + char_count += strhex_to_str((char *)&ret_blob.data[char_count], + hexdump_byte_count - char_count, + &hexdump[i], 2); + i += 2; + } else { + i++; + } + } else { + i++; + } + } + ret_blob.length = char_count; + + return ret_blob; +} + +/** + * Print a buf in hex. Assumes dst is at least (srclen*2)+1 large. + */ +_PUBLIC_ void hex_encode_buf(char *dst, const uint8_t *src, size_t srclen) +{ + size_t i; + for (i=0; i<srclen; i++) { + snprintf(dst + i*2, 3, "%02X", src[i]); + } + /* + * Ensure 0-termination for 0-length buffers + */ + dst[srclen*2] = '\0'; +} + +/** + * talloc version of hex_encode_buf() + */ +_PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len) +{ + char *hex_buffer; + + hex_buffer = talloc_array(mem_ctx, char, (len*2)+1); + if (!hex_buffer) { + return NULL; + } + hex_encode_buf(hex_buffer, buff_in, len); + talloc_set_name_const(hex_buffer, hex_buffer); + return hex_buffer; +} + +/** + variant of strcmp() that handles NULL ptrs +**/ +_PUBLIC_ int strcmp_safe(const char *s1, const char *s2) +{ + if (s1 == s2) { + return 0; + } + if (s1 == NULL || s2 == NULL) { + return s1?-1:1; + } + return strcmp(s1, s2); +} + + +/** +return the number of bytes occupied by a buffer in ASCII format +the result includes the null termination +limited by 'n' bytes +**/ +_PUBLIC_ size_t ascii_len_n(const char *src, size_t n) +{ + size_t len; + + len = strnlen(src, n); + if (len+1 <= n) { + len += 1; + } + + return len; +} + +_PUBLIC_ bool mem_equal_const_time(const void *s1, const void *s2, size_t n) +{ + /* Ensure we won't overflow the unsigned index used by gnutls. */ + SMB_ASSERT(n <= UINT_MAX); + + return gnutls_memcmp(s1, s2, n) == 0; +} + +struct anonymous_shared_header { + union { + size_t length; + uint8_t pad[16]; + } u; +}; + +/* Map a shared memory buffer of at least nelem counters. */ +void *anonymous_shared_allocate(size_t orig_bufsz) +{ + void *ptr; + void *buf; + size_t pagesz = getpagesize(); + size_t pagecnt; + size_t bufsz = orig_bufsz; + struct anonymous_shared_header *hdr; + + bufsz += sizeof(*hdr); + + /* round up to full pages */ + pagecnt = bufsz / pagesz; + if (bufsz % pagesz) { + pagecnt += 1; + } + bufsz = pagesz * pagecnt; + + if (orig_bufsz >= bufsz) { + /* integer wrap */ + errno = ENOMEM; + return NULL; + } + +#ifdef MAP_ANON + /* BSD */ + buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, + -1 /* fd */, 0 /* offset */); +#else +{ + int saved_errno; + int fd; + + fd = open("/dev/zero", O_RDWR); + if (fd == -1) { + return NULL; + } + + buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, + fd, 0 /* offset */); + saved_errno = errno; + close(fd); + errno = saved_errno; +} +#endif + + if (buf == MAP_FAILED) { + return NULL; + } + + hdr = (struct anonymous_shared_header *)buf; + hdr->u.length = bufsz; + + ptr = (void *)(&hdr[1]); + + return ptr; +} + +void *anonymous_shared_resize(void *ptr, size_t new_size, bool maymove) +{ +#ifdef HAVE_MREMAP + void *buf; + size_t pagesz = getpagesize(); + size_t pagecnt; + size_t bufsz; + struct anonymous_shared_header *hdr; + int flags = 0; + + if (ptr == NULL) { + errno = EINVAL; + return NULL; + } + + hdr = (struct anonymous_shared_header *)ptr; + hdr--; + if (hdr->u.length > (new_size + sizeof(*hdr))) { + errno = EINVAL; + return NULL; + } + + bufsz = new_size + sizeof(*hdr); + + /* round up to full pages */ + pagecnt = bufsz / pagesz; + if (bufsz % pagesz) { + pagecnt += 1; + } + bufsz = pagesz * pagecnt; + + if (new_size >= bufsz) { + /* integer wrap */ + errno = ENOSPC; + return NULL; + } + + if (bufsz <= hdr->u.length) { + return ptr; + } + + if (maymove) { + flags = MREMAP_MAYMOVE; + } + + buf = mremap(hdr, hdr->u.length, bufsz, flags); + + if (buf == MAP_FAILED) { + errno = ENOSPC; + return NULL; + } + + hdr = (struct anonymous_shared_header *)buf; + hdr->u.length = bufsz; + + ptr = (void *)(&hdr[1]); + + return ptr; +#else + errno = ENOSPC; + return NULL; +#endif +} + +void anonymous_shared_free(void *ptr) +{ + struct anonymous_shared_header *hdr; + + if (ptr == NULL) { + return; + } + + hdr = (struct anonymous_shared_header *)ptr; + + hdr--; + + munmap(hdr, hdr->u.length); +} + +#ifdef DEVELOPER +/* used when you want a debugger started at a particular point in the + code. Mostly useful in code that runs as a child process, where + normal gdb attach is harder to organise. +*/ +void samba_start_debugger(void) +{ + int ready_pipe[2]; + char c; + int ret; + pid_t pid; + + ret = pipe(ready_pipe); + SMB_ASSERT(ret == 0); + + pid = fork(); + SMB_ASSERT(pid >= 0); + + if (pid) { + c = 0; + + ret = close(ready_pipe[0]); + SMB_ASSERT(ret == 0); +#if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER) + /* + * Make sure the child process can attach a debugger. + * + * We don't check the error code as the debugger + * will tell us if it can't attach. + */ + (void)prctl(PR_SET_PTRACER, pid, 0, 0, 0); +#endif + ret = write(ready_pipe[1], &c, 1); + SMB_ASSERT(ret == 1); + + ret = close(ready_pipe[1]); + SMB_ASSERT(ret == 0); + + /* Wait for gdb to attach. */ + sleep(2); + } else { + char *cmd = NULL; + + ret = close(ready_pipe[1]); + SMB_ASSERT(ret == 0); + + ret = read(ready_pipe[0], &c, 1); + SMB_ASSERT(ret == 1); + + ret = close(ready_pipe[0]); + SMB_ASSERT(ret == 0); + + ret = asprintf(&cmd, "gdb --pid %u", getppid()); + SMB_ASSERT(ret != -1); + + execlp("xterm", "xterm", "-e", cmd, (char *) NULL); + smb_panic("execlp() failed"); + } +} +#endif diff --git a/lib/util/util.h b/lib/util/util.h new file mode 100644 index 0000000..59d24a8 --- /dev/null +++ b/lib/util/util.h @@ -0,0 +1,94 @@ +/* + Unix SMB/CIFS implementation. + Utility functions for Samba + Copyright (C) Andrew Tridgell 1992-1999 + Copyright (C) Jelmer Vernooij 2005 + Copyright (C) Swen Schillig 2019 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __UTIL_SAMBA_UTIL_H__ +#define __UTIL_SAMBA_UTIL_H__ + +/** + * Write dump of binary data to a callback + */ +void dump_data_cb(const uint8_t *buf, int len, + bool omit_zero_bytes, + void (*cb)(const char *buf, void *private_data), + void *private_data); + +/** + * Write dump of binary data to a FILE + */ +void dump_data_file(const uint8_t *buf, int len, bool omit_zero_bytes, + FILE *f); + +/** + * Write dump of binary data to the log file. + * + * The data is only written if the log level is at least level. + */ +_PUBLIC_ void dump_data(int level, const uint8_t *buf,int len); + +/** + * Write dump of binary data to the log file. + * + * The data is only written if the log level is at least level for + * debug class dbgc_class. + */ +_PUBLIC_ void dump_data_dbgc(int dbgc_class, int level, const uint8_t *buf, int len); + +/** + * Write dump of compared binary data to a callback + */ +void dump_data_diff_cb(const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2, + bool omit_zero_bytes, + void (*cb)(const char *buf, void *private_data), + void *private_data); + +/** + * Write dump of compared binary data to the log file. + * + * The data is only written if the log level is at least level for + * debug class dbgc_class. + */ +_PUBLIC_ void dump_data_diff(int dbgc_class, int level, + bool omit_zero_bytes, + const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2); + +/** + * Write dump of compared binary data to the given file handle + */ +_PUBLIC_ void dump_data_file_diff(FILE *f, + bool omit_zero_bytes, + const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2); + +/** + * Write a password to the log file. + * + * @note Only actually does something if DEBUG_PASSWORD was defined during + * compile-time. + */ +_PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len); + +/** + * Dump data to "str" via talloc_asprintf_addbuf() + */ +_PUBLIC_ void dump_data_addbuf(const uint8_t *buf, size_t buflen, char **str); +#endif diff --git a/lib/util/util_file.c b/lib/util/util_file.c new file mode 100644 index 0000000..0e54dff --- /dev/null +++ b/lib/util/util_file.c @@ -0,0 +1,498 @@ +/* + * Unix SMB/CIFS implementation. + * SMB parameters and setup + * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995. + * + * Added afdgets() Jelmer Vernooij 2005 + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/shmem.h" +#include "system/filesys.h" +#include <talloc.h> +#include "lib/util/samba_util.h" +#include "lib/util/sys_popen.h" +#include "lib/util/sys_rw.h" +#include "lib/util/debug.h" + +/** + * Read one line (data until next newline or eof) and allocate it + */ +_PUBLIC_ char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint) +{ + char *data = NULL; + ssize_t alloc_size = 0, offset = 0, ret; + int p; + + if (hint <= 0) hint = 0x100; + + do { + alloc_size += hint; + + data = talloc_realloc(mem_ctx, data, char, alloc_size); + + if (!data) + return NULL; + + ret = read(fd, data + offset, hint); + + if (ret == 0) { + return NULL; + } + + if (ret == -1) { + talloc_free(data); + return NULL; + } + + /* Find newline */ + for (p = 0; p < ret; p++) { + if (data[offset + p] == '\n') + break; + } + + if (p < ret) { + data[offset + p] = '\0'; + + /* Go back to position of newline */ + lseek(fd, p - ret + 1, SEEK_CUR); + return data; + } + + offset += ret; + + } while ((size_t)ret == hint); + + data[offset] = '\0'; + + return data; +} + +char *fgets_slash(TALLOC_CTX *mem_ctx, char *s2, size_t maxlen, FILE *f) +{ + char *s = s2; + size_t len = 0; + int c; + bool start_of_line = true; + + if (feof(f)) { + return NULL; + } + + if (maxlen < 2) { + return NULL; + } + + if (s2 == NULL) { + maxlen = MIN(maxlen,8); + s = talloc_array(mem_ctx, char, maxlen); + } + + if (s == NULL) { + return NULL; + } + + *s = 0; + + while (len < maxlen-1) { + c = getc(f); + switch (c) + { + case '\r': + break; + case '\n': + while (len > 0 && s[len-1] == ' ') { + s[--len] = 0; + } + if (len > 0 && s[len-1] == '\\') { + s[--len] = 0; + start_of_line = true; + break; + } + return s; + case EOF: + if (len <= 0 && (s2 == NULL)) { + TALLOC_FREE(s); + } + return (len>0) ? s : NULL; + case ' ': + if (start_of_line) { + break; + } + + FALL_THROUGH; + default: + start_of_line = false; + s[len++] = c; + s[len] = 0; + } + if ((s2 == NULL) && (len > maxlen-3)) { + size_t m; + char *t; + + m = maxlen * 2; + if (m < maxlen) { + DBG_ERR("length overflow\n"); + TALLOC_FREE(s); + return NULL; + } + maxlen = m; + + t = talloc_realloc(mem_ctx, s, char, maxlen); + if (t == NULL) { + DBG_ERR("failed to expand buffer!\n"); + TALLOC_FREE(s); + return NULL; + } + + s = t; + } + } + + return s; +} + +/** +load a file into memory from a fd. +**/ +_PUBLIC_ char *fd_load(int fd, size_t *psize, size_t maxsize, TALLOC_CTX *mem_ctx) +{ + FILE *file; + char *p = NULL; + size_t size = 0; + size_t chunk = 1024; + int err; + int fd_dup; + + if (maxsize == 0) { + maxsize = SIZE_MAX; + } + + fd_dup = dup(fd); + if (fd_dup == -1) { + return NULL; + } + + file = fdopen(fd_dup, "r"); + if (file == NULL) { + close(fd_dup); + return NULL; + } + + while (size < maxsize) { + size_t newbufsize; + size_t nread; + + chunk = MIN(chunk, (maxsize - size)); + + newbufsize = size + (chunk+1); /* chunk+1 can't overflow */ + if (newbufsize < size) { + goto fail; /* overflow */ + } + + p = talloc_realloc(mem_ctx, p, char, newbufsize); + if (p == NULL) { + goto fail; + } + + nread = fread(p+size, 1, chunk, file); + size += nread; + + if (nread != chunk) { + break; + } + } + + err = ferror(file); + if (err != 0) { + goto fail; + } + + p[size] = '\0'; + + if (psize != NULL) { + *psize = size; + } + + fclose(file); + return p; + +fail: + TALLOC_FREE(p); + fclose(file); + return NULL; +} + +/** +load a file into memory +**/ +_PUBLIC_ char *file_load(const char *fname, size_t *size, size_t maxsize, TALLOC_CTX *mem_ctx) +{ + int fd; + char *p; + + if (!fname || !*fname) return NULL; + + fd = open(fname,O_RDONLY); + if (fd == -1) return NULL; + + p = fd_load(fd, size, maxsize, mem_ctx); + + close(fd); + + return p; +} + +/** +parse a buffer into lines +'p' will be freed on error, and otherwise will be made a child of the returned array +**/ +static char **file_lines_parse_internal(char *p, size_t size, int *numlines, TALLOC_CTX *mem_ctx) +{ + unsigned int i; + char *s, **ret; + + if (!p) return NULL; + + for (s = p, i=0; s < p+size; s++) { + if (s[0] == '\n') i++; + } + + ret = talloc_zero_array(mem_ctx, char *, i+2); + if (!ret) { + talloc_free(p); + return NULL; + } + + talloc_steal(ret, p); + + ret[0] = p; + for (s = p, i=1; s < p+size; s++) { + if (s[0] == '\n') { + s[0] = 0; + ret[i] = s+1; + i++; + } + if (s[0] == '\r') s[0] = 0; + } + + /* remove any blank lines at the end */ + while (i > 0 && ret[i-1][0] == 0) { + i--; + } + + if (numlines) *numlines = i; + + return ret; +} + + +/** +load a file into memory and return an array of pointers to lines in the file +must be freed with talloc_free(). +**/ +_PUBLIC_ char **file_lines_load(const char *fname, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx) +{ + char *p; + size_t size; + + p = file_load(fname, &size, maxsize, mem_ctx); + if (!p) return NULL; + + return file_lines_parse_internal(p, size, numlines, mem_ctx); +} + +/** +load a fd into memory and return an array of pointers to lines in the file +must be freed with talloc_free(). If convert is true calls unix_to_dos on +the list. +**/ +_PUBLIC_ char **fd_lines_load(int fd, int *numlines, size_t maxsize, TALLOC_CTX *mem_ctx) +{ + char *p; + size_t size; + + p = fd_load(fd, &size, maxsize, mem_ctx); + if (!p) return NULL; + + return file_lines_parse_internal(p, size, numlines, mem_ctx); +} + +_PUBLIC_ char **file_lines_parse(const char *p_in, + size_t size, + int *numlines, + TALLOC_CTX *mem_ctx) +{ + /* + * Copy the incoming string so it can end up + * being owned by the returned pointer and + * freed when that is. + */ + char *p = talloc_strdup(mem_ctx, p_in); + if (p == NULL) { + return NULL; + } + return file_lines_parse_internal(p, size, numlines, mem_ctx); +} + +_PUBLIC_ bool file_save_mode(const char *fname, const void *packet, + size_t length, mode_t mode) +{ + ssize_t num_written; + int fd; + fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, mode); + if (fd == -1) { + return false; + } + num_written = write(fd, packet, length); + if (num_written == -1 || (size_t)num_written != length) { + close(fd); + return false; + } + close(fd); + return true; +} + +/** + save a lump of data into a file. Mostly used for debugging +*/ +_PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length) +{ + return file_save_mode(fname, packet, length, 0644); +} + +_PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap) +{ + char *p; + int len, ret; + va_list ap2; + + va_copy(ap2, ap); + len = vasprintf(&p, format, ap2); + va_end(ap2); + if (len <= 0) return len; + ret = write(fd, p, len); + SAFE_FREE(p); + return ret; +} + +_PUBLIC_ int fdprintf(int fd, const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = vfdprintf(fd, format, ap); + va_end(ap); + return ret; +} + + +/* + compare two files, return true if the two files have the same content + */ +bool file_compare(const char *path1, const char *path2) +{ + FILE *f1 = NULL, *f2 = NULL; + uint8_t buf1[1024], buf2[1024]; + bool ret = false; + + f1 = fopen(path1, "r"); + if (f1 == NULL) { + goto done; + } + f2 = fopen(path2, "r"); + if (f2 == NULL) { + goto done; + } + + while (!feof(f1)) { + size_t n1 = fread(buf1, 1, sizeof(buf1), f1); + size_t n2 = fread(buf2, 1, sizeof(buf2), f2); + + if (n1 != n2) { + goto done; + } + if (n1 == 0) { + ret = (feof(f1) && feof(f2)); + goto done; + } + if (memcmp(buf1, buf2, n1) != 0) { + goto done; + } + if (n1 < sizeof(buf1)) { + bool has_error = (ferror(f1) || ferror(f2)); + if (has_error) { + goto done; + } + } + } + ret = true; +done: + if (f2 != NULL) { + fclose(f2); + } + if (f1 != NULL) { + fclose(f1); + } + return ret; +} + +/** + Load from a pipe into memory. +**/ +char *file_ploadv(char * const argl[], size_t *size) +{ + int fd, n; + char *p = NULL; + char buf[1024]; + size_t total; + + fd = sys_popenv(argl); + if (fd == -1) { + return NULL; + } + + total = 0; + + while ((n = sys_read(fd, buf, sizeof(buf))) > 0) { + p = talloc_realloc(NULL, p, char, total + n + 1); + if (p == NULL) { + DBG_ERR("failed to expand buffer!\n"); + close(fd); + return NULL; + } + memcpy(p+total, buf, n); + total += n; + } + + if (p != NULL) { + p[total] = 0; + } + + /* + * FIXME: Perhaps ought to check that the command completed + * successfully (returned 0); if not the data may be + * truncated. + */ + sys_pclose(fd); + + if (size) { + *size = total; + } + + return p; +} diff --git a/lib/util/util_id.c b/lib/util/util_id.c new file mode 100644 index 0000000..19486f9 --- /dev/null +++ b/lib/util/util_id.c @@ -0,0 +1,89 @@ +/* + Unix SMB/CIFS implementation. + + Helper routines for uid and gid arrays + + Copyright (C) Guenther Deschner 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "lib/util/samba_util.h" + +/**************************************************************************** + Add a gid to an array of gids if it's not already there. +****************************************************************************/ + +bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, + gid_t **gids, uint32_t *num_gids) +{ + uint32_t i; + + if ((*num_gids != 0) && (*gids == NULL)) { + /* + * A former call to this routine has failed to allocate memory + */ + return false; + } + + for (i=0; i<*num_gids; i++) { + if ((*gids)[i] == gid) { + return true; + } + } + + *gids = talloc_realloc(mem_ctx, *gids, gid_t, *num_gids+1); + if (*gids == NULL) { + *num_gids = 0; + return false; + } + + (*gids)[*num_gids] = gid; + *num_gids += 1; + return true; +} + +/**************************************************************************** + Add a uid to an array of uids if it's not already there. +****************************************************************************/ + +bool add_uid_to_array_unique(TALLOC_CTX *mem_ctx, uid_t uid, + uid_t **uids, uint32_t *num_uids) +{ + uint32_t i; + + if ((*num_uids != 0) && (*uids == NULL)) { + /* + * A former call to this routine has failed to allocate memory + */ + return false; + } + + for (i=0; i<*num_uids; i++) { + if ((*uids)[i] == uid) { + return true; + } + } + + *uids = talloc_realloc(mem_ctx, *uids, uid_t, *num_uids+1); + if (*uids == NULL) { + *num_uids = 0; + return false; + } + + (*uids)[*num_uids] = uid; + *num_uids += 1; + return true; +} diff --git a/lib/util/util_ldb.c b/lib/util/util_ldb.c new file mode 100644 index 0000000..1fd5422 --- /dev/null +++ b/lib/util/util_ldb.c @@ -0,0 +1,114 @@ +/* + Unix SMB/CIFS implementation. + + common share info functions + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Tim Potter 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include <ldb.h> +#include "lib/util/util_ldb.h" +#include "lib/util/debug.h" + +/* + * search the LDB for the specified attributes - va_list variant + */ +int gendb_search_v(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *basedn, + struct ldb_message ***msgs, + const char * const *attrs, + const char *format, + va_list ap) +{ + enum ldb_scope scope = LDB_SCOPE_SUBTREE; + struct ldb_result *res; + char *expr = NULL; + int ret; + + if (format) { + expr = talloc_vasprintf(mem_ctx, format, ap); + if (expr == NULL) { + return -1; + } + } else { + scope = LDB_SCOPE_BASE; + } + + res = NULL; + + ret = ldb_search(ldb, mem_ctx, &res, basedn, scope, attrs, + expr?"%s":NULL, expr); + + if (ret == LDB_SUCCESS) { + DBG_DEBUG("%s %s -> %d\n", + basedn?ldb_dn_get_linearized(basedn):"NULL", + expr?expr:"NULL", res->count); + + ret = res->count; + if (msgs != NULL) { + *msgs = talloc_steal(mem_ctx, res->msgs); + } + talloc_free(res); + } else if (scope == LDB_SCOPE_BASE && ret == LDB_ERR_NO_SUCH_OBJECT) { + ret = 0; + if (msgs != NULL) *msgs = NULL; + } else { + DBG_INFO("search failed: %s\n", + ldb_errstring(ldb)); + ret = -1; + if (msgs != NULL) *msgs = NULL; + } + + talloc_free(expr); + + return ret; +} + +/* + * search the LDB for the specified attributes - varargs variant + */ +int gendb_search(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *basedn, + struct ldb_message ***res, + const char * const *attrs, + const char *format, ...) +{ + va_list ap; + int count; + + va_start(ap, format); + count = gendb_search_v(ldb, mem_ctx, basedn, res, attrs, format, ap); + va_end(ap); + + return count; +} + +/* + * search the LDB for a specified record (by DN) + */ +int gendb_search_dn(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct ldb_message ***res, + const char * const *attrs) +{ + return gendb_search(ldb, mem_ctx, dn, res, attrs, NULL); +} + diff --git a/lib/util/util_ldb.h b/lib/util/util_ldb.h new file mode 100644 index 0000000..6691644 --- /dev/null +++ b/lib/util/util_ldb.h @@ -0,0 +1,50 @@ +/* + Unix SMB/CIFS implementation. + + common share info functions + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Tim Potter 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef __LIB_UTIL_UTIL_LDB_H__ +#define __LIB_UTIL_UTIL_LDB_H__ + +struct ldb_dn; + +/* The following definitions come from lib/util/util_ldb.c */ + +int gendb_search_v(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *basedn, + struct ldb_message ***msgs, + const char * const *attrs, + const char *format, + va_list ap) PRINTF_ATTRIBUTE(6,0); +int gendb_search(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *basedn, + struct ldb_message ***res, + const char * const *attrs, + const char *format, ...) PRINTF_ATTRIBUTE(6,7); +int gendb_search_dn(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct ldb_message ***res, + const char * const *attrs); + +#endif /* __LIB_UTIL_UTIL_LDB_H__ */ diff --git a/lib/util/util_net.c b/lib/util/util_net.c new file mode 100644 index 0000000..48c9552 --- /dev/null +++ b/lib/util/util_net.c @@ -0,0 +1,1240 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008 + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1992-2007 + Copyright (C) Simo Sorce 2001 + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + Copyright (C) James J Myers 2003 + Copyright (C) Tim Potter 2000-2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "system/network.h" +#include "system/locale.h" +#include "system/filesys.h" +#include "system/select.h" +#include "lib/util/select.h" +#include "lib/util/util_net.h" + +#undef strcasecmp +#undef strncasecmp + +/******************************************************************* + Set an address to INADDR_ANY. +******************************************************************/ + +void zero_sockaddr(struct sockaddr_storage *pss) +{ + /* Ensure we're at least a valid sockaddr-storage. */ + *pss = (struct sockaddr_storage) { .ss_family = AF_INET }; +} + +static char *normalize_ipv6_literal(const char *str, char *buf, size_t *_len) +{ +#define IPv6_LITERAL_NET ".ipv6-literal.net" + const size_t llen = sizeof(IPv6_LITERAL_NET) - 1; + size_t len = *_len; + int cmp; + size_t i; + size_t idx_chars = 0; + size_t cnt_delimiter = 0; + size_t cnt_chars = 0; + + if (len <= llen) { + return NULL; + } + + /* ignore a trailing '.' */ + if (str[len - 1] == '.') { + len -= 1; + } + + len -= llen; + if (len >= INET6_ADDRSTRLEN) { + return NULL; + } + if (len < 2) { + return NULL; + } + + cmp = strncasecmp(&str[len], IPv6_LITERAL_NET, llen); + if (cmp != 0) { + return NULL; + } + + for (i = 0; i < len; i++) { + if (idx_chars != 0) { + break; + } + + switch (str[i]) { + case '-': + buf[i] = ':'; + cnt_chars = 0; + cnt_delimiter += 1; + break; + case 's': + buf[i] = SCOPE_DELIMITER; + idx_chars += 1; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'a': + case 'A': + case 'b': + case 'B': + case 'c': + case 'C': + case 'd': + case 'D': + case 'e': + case 'E': + case 'f': + case 'F': + buf[i] = str[i]; + cnt_chars += 1; + break; + default: + return NULL; + } + if (cnt_chars > 4) { + return NULL; + } + if (cnt_delimiter > 7) { + return NULL; + } + } + + if (cnt_delimiter < 2) { + return NULL; + } + + for (; idx_chars != 0 && i < len; i++) { + switch (str[i]) { + case SCOPE_DELIMITER: + case ':': + return NULL; + default: + buf[i] = str[i]; + idx_chars += 1; + break; + } + } + + if (idx_chars == 1) { + return NULL; + } + + buf[i] = '\0'; + *_len = len; + return buf; +} + +/** + * Wrap getaddrinfo... + */ +bool interpret_string_addr_internal(struct addrinfo **ppres, + const char *str, int flags) +{ + int ret; + struct addrinfo hints; +#if defined(HAVE_IPV6) + char addr[INET6_ADDRSTRLEN*2] = { 0, }; + unsigned int scope_id = 0; + size_t len = strlen(str); +#endif + + ZERO_STRUCT(hints); + + /* By default make sure it supports TCP. */ + hints.ai_socktype = SOCK_STREAM; + + /* always try as a numeric host first. This prevents unnecessary name + * lookups, and also ensures we accept IPv6 addresses */ + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + +#if defined(HAVE_IPV6) + if (len < sizeof(addr)) { + char *p = NULL; + + p = normalize_ipv6_literal(str, addr, &len); + if (p != NULL) { + hints.ai_family = AF_INET6; + str = p; + } + } + + if (strchr_m(str, ':')) { + char *p = strchr_m(str, SCOPE_DELIMITER); + + /* + * Cope with link-local. + * This is IP:v6:addr%ifname. + */ + + if (p && (p > str) && ((scope_id = if_nametoindex(p+1)) != 0)) { + /* Length of string we want to copy. + This is IP:v6:addr (removing the %ifname). + */ + len = PTR_DIFF(p,str); + + if (len+1 > sizeof(addr)) { + /* string+nul too long for array. */ + return false; + } + if (str != addr) { + memcpy(addr, str, len); + } + addr[len] = '\0'; + + str = addr; + } + } +#endif + + ret = getaddrinfo(str, NULL, &hints, ppres); + if (ret == 0) { +#if defined(HAVE_IPV6) + struct sockaddr_in6 *ps6 = NULL; + + if (scope_id == 0) { + return true; + } + if (ppres == NULL) { + return true; + } + if ((*ppres) == NULL) { + return true; + } + if ((*ppres)->ai_addr->sa_family != AF_INET6) { + return true; + } + + ps6 = (struct sockaddr_in6 *)(*ppres)->ai_addr; + + if (IN6_IS_ADDR_LINKLOCAL(&ps6->sin6_addr) && + ps6->sin6_scope_id == 0) { + ps6->sin6_scope_id = scope_id; + } +#endif + + return true; + } + + hints.ai_flags = flags; + + /* Linux man page on getaddrinfo() says port will be + uninitialized when service string is NULL */ + + ret = getaddrinfo(str, NULL, + &hints, + ppres); + + if (ret) { + DEBUG(3, ("interpret_string_addr_internal: " + "getaddrinfo failed for name %s (flags %d) [%s]\n", + str, flags, gai_strerror(ret))); + return false; + } + return true; +} + +/******************************************************************* + Map a text hostname or IP address (IPv4 or IPv6) into a + struct sockaddr_storage. Takes a flag which allows it to + prefer an IPv4 address (needed for DC's). +******************************************************************/ + +static bool interpret_string_addr_pref(struct sockaddr_storage *pss, + const char *str, + int flags, + bool prefer_ipv4) +{ + struct addrinfo *res = NULL; + int int_flags; + + zero_sockaddr(pss); + + if (flags & AI_NUMERICHOST) { + int_flags = flags; + } else { + int_flags = flags|AI_ADDRCONFIG; + } + + if (!interpret_string_addr_internal(&res, str, int_flags)) { + return false; + } + if (!res) { + return false; + } + + if (prefer_ipv4) { + struct addrinfo *p; + + for (p = res; p; p = p->ai_next) { + if (p->ai_family == AF_INET) { + memcpy(pss, p->ai_addr, p->ai_addrlen); + break; + } + } + if (p == NULL) { + /* Copy the first sockaddr. */ + memcpy(pss, res->ai_addr, res->ai_addrlen); + } + } else { + /* Copy the first sockaddr. */ + memcpy(pss, res->ai_addr, res->ai_addrlen); + } + + freeaddrinfo(res); + return true; +} + +/******************************************************************* + Map a text hostname or IP address (IPv4 or IPv6) into a + struct sockaddr_storage. Address agnostic version. +******************************************************************/ + +bool interpret_string_addr(struct sockaddr_storage *pss, + const char *str, + int flags) +{ + return interpret_string_addr_pref(pss, + str, + flags, + false); +} + +/******************************************************************* + Map a text hostname or IP address (IPv4 or IPv6) into a + struct sockaddr_storage. Version that prefers IPv4. +******************************************************************/ + +bool interpret_string_addr_prefer_ipv4(struct sockaddr_storage *pss, + const char *str, + int flags) +{ + return interpret_string_addr_pref(pss, + str, + flags, + true); +} + +/** + * Interpret an internet address or name into an IP address in 4 byte form. + * RETURNS IN NETWORK BYTE ORDER (big endian). + */ + +uint32_t interpret_addr(const char *str) +{ + uint32_t ret; + + /* If it's in the form of an IP address then + * get the lib to interpret it */ + if (is_ipaddress_v4(str)) { + struct in_addr dest; + + if (inet_pton(AF_INET, str, &dest) <= 0) { + /* Error - this shouldn't happen ! */ + DEBUG(0,("interpret_addr: inet_pton failed " + "host %s\n", + str)); + return 0; + } + ret = dest.s_addr; /* NETWORK BYTE ORDER ! */ + } else { + /* Otherwise assume it's a network name of some sort and use + getaddrinfo. */ + struct addrinfo *res = NULL; + struct addrinfo *res_list = NULL; + if (!interpret_string_addr_internal(&res_list, + str, + AI_ADDRCONFIG)) { + DEBUG(3,("interpret_addr: Unknown host. %s\n",str)); + return 0; + } + + /* Find the first IPv4 address. */ + for (res = res_list; res; res = res->ai_next) { + if (res->ai_family != AF_INET) { + continue; + } + if (res->ai_addr == NULL) { + continue; + } + break; + } + if(res == NULL) { + DEBUG(3,("interpret_addr: host address is " + "invalid for host %s\n",str)); + if (res_list) { + freeaddrinfo(res_list); + } + return 0; + } + memcpy((char *)&ret, + &((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr, + sizeof(ret)); + if (res_list) { + freeaddrinfo(res_list); + } + } + + /* This is so bogus - all callers need fixing... JRA. */ + if (ret == (uint32_t)-1) { + return 0; + } + + return ret; +} + +/** + A convenient addition to interpret_addr(). +**/ +_PUBLIC_ struct in_addr interpret_addr2(const char *str) +{ + struct in_addr ret; + uint32_t a = interpret_addr(str); + ret.s_addr = a; + return ret; +} + +/** + Check if an IP is the 0.0.0.0. +**/ + +_PUBLIC_ bool is_zero_ip_v4(struct in_addr ip) +{ + return ip.s_addr == 0; +} + +/** + Are two IPs on the same subnet? +**/ + +_PUBLIC_ bool same_net_v4(struct in_addr ip1, struct in_addr ip2, struct in_addr mask) +{ + uint32_t net1,net2,nmask; + + nmask = ntohl(mask.s_addr); + net1 = ntohl(ip1.s_addr); + net2 = ntohl(ip2.s_addr); + + return((net1 & nmask) == (net2 & nmask)); +} + +/** + * Return true if a string could be an IPv4 address. + */ + +bool is_ipaddress_v4(const char *str) +{ + int ret = -1; + struct in_addr dest; + + ret = inet_pton(AF_INET, str, &dest); + if (ret > 0) { + return true; + } + return false; +} + +bool is_ipv6_literal(const char *str) +{ +#if defined(HAVE_IPV6) + char buf[INET6_ADDRSTRLEN*2] = { 0, }; + size_t len = strlen(str); + char *p = NULL; + + if (len >= sizeof(buf)) { + return false; + } + + p = normalize_ipv6_literal(str, buf, &len); + if (p == NULL) { + return false; + } + + return true; +#else + return false; +#endif +} + +/** + * Return true if a string could be a IPv6 address. + */ + +bool is_ipaddress_v6(const char *str) +{ +#if defined(HAVE_IPV6) + int ret = -1; + char *p = NULL; + char buf[INET6_ADDRSTRLEN] = { 0, }; + size_t len; + const char *addr = str; + const char *idxs = NULL; + unsigned int idx = 0; + struct in6_addr ip6; + + p = strchr_m(str, ':'); + if (p == NULL) { + return is_ipv6_literal(str); + } + + p = strchr_m(str, SCOPE_DELIMITER); + if (p && (p > str)) { + len = PTR_DIFF(p, str); + idxs = p + 1; + } else { + len = strlen(str); + } + + if (len >= sizeof(buf)) { + return false; + } + if (idxs != NULL) { + strncpy(buf, str, len); + addr = buf; + } + + /* + * Cope with link-local. + * This is IP:v6:addr%ifidx. + */ + if (idxs != NULL) { + char c; + + ret = sscanf(idxs, "%5u%c", &idx, &c); + if (ret != 1) { + idx = 0; + } + + if (idx > 0 && idx < UINT16_MAX) { + /* a valid index */ + idxs = NULL; + } + } + + /* + * Cope with link-local. + * This is IP:v6:addr%ifname. + */ + if (idxs != NULL) { + idx = if_nametoindex(idxs); + + if (idx > 0) { + /* a valid index */ + idxs = NULL; + } + } + + if (idxs != NULL) { + return false; + } + + ret = inet_pton(AF_INET6, addr, &ip6); + if (ret <= 0) { + return false; + } + + return true; +#else + return false; +#endif +} + +/** + * Return true if a string could be an IPv4 or IPv6 address. + */ + +bool is_ipaddress(const char *str) +{ + return is_ipaddress_v4(str) || is_ipaddress_v6(str); +} + +/** + * Is a sockaddr a broadcast address ? + */ + +bool is_broadcast_addr(const struct sockaddr *pss) +{ +#if defined(HAVE_IPV6) + if (pss->sa_family == AF_INET6) { + const struct in6_addr *sin6 = + &((const struct sockaddr_in6 *)pss)->sin6_addr; + return IN6_IS_ADDR_MULTICAST(sin6); + } +#endif + if (pss->sa_family == AF_INET) { + uint32_t addr = + ntohl(((const struct sockaddr_in *)pss)->sin_addr.s_addr); + return addr == INADDR_BROADCAST; + } + return false; +} + +/** + * Check if an IPv7 is 127.0.0.1 + */ +bool is_loopback_ip_v4(struct in_addr ip) +{ + struct in_addr a; + a.s_addr = htonl(INADDR_LOOPBACK); + return(ip.s_addr == a.s_addr); +} + +/** + * Check if a struct sockaddr is the loopback address. + */ +bool is_loopback_addr(const struct sockaddr *pss) +{ +#if defined(HAVE_IPV6) + if (pss->sa_family == AF_INET6) { + const struct in6_addr *pin6 = + &((const struct sockaddr_in6 *)pss)->sin6_addr; + return IN6_IS_ADDR_LOOPBACK(pin6); + } +#endif + if (pss->sa_family == AF_INET) { + const struct in_addr *pin = &((const struct sockaddr_in *)pss)->sin_addr; + return is_loopback_ip_v4(*pin); + } + return false; +} + +/** + * Check if a struct sockaddr has an unspecified address. + */ +bool is_zero_addr(const struct sockaddr_storage *pss) +{ +#if defined(HAVE_IPV6) + if (pss->ss_family == AF_INET6) { + const struct in6_addr *pin6 = + &((const struct sockaddr_in6 *)pss)->sin6_addr; + return IN6_IS_ADDR_UNSPECIFIED(pin6); + } +#endif + if (pss->ss_family == AF_INET) { + const struct in_addr *pin = &((const struct sockaddr_in *)pss)->sin_addr; + return is_zero_ip_v4(*pin); + } + if (pss->ss_family == AF_UNSPEC) { + return true; + } + return false; +} + +/** + * Set an IP to 0.0.0.0. + */ +void zero_ip_v4(struct in_addr *ip) +{ + ZERO_STRUCTP(ip); +} + +bool is_linklocal_addr(const struct sockaddr_storage *pss) +{ +#ifdef HAVE_IPV6 + if (pss->ss_family == AF_INET6) { + const struct in6_addr *pin6 = + &((const struct sockaddr_in6 *)pss)->sin6_addr; + return IN6_IS_ADDR_LINKLOCAL(pin6); + } +#endif + if (pss->ss_family == AF_INET) { + const struct in_addr *pin = + &((const struct sockaddr_in *)pss)->sin_addr; + struct in_addr ll_addr; + struct in_addr mask_addr; + + /* 169.254.0.0/16, is link local, see RFC 3927 */ + ll_addr.s_addr = 0xa9fe0000; + mask_addr.s_addr = 0xffff0000; + return same_net_v4(*pin, ll_addr, mask_addr); + } + return false; +} + +/** + * Convert an IPv4 struct in_addr to a struct sockaddr_storage. + */ +void in_addr_to_sockaddr_storage(struct sockaddr_storage *ss, + struct in_addr ip) +{ + struct sockaddr_in *sa = (struct sockaddr_in *)ss; + ZERO_STRUCTP(ss); + sa->sin_family = AF_INET; + sa->sin_addr = ip; +} + +#if defined(HAVE_IPV6) +/** + * Convert an IPv6 struct in_addr to a struct sockaddr_storage. + */ +void in6_addr_to_sockaddr_storage(struct sockaddr_storage *ss, + struct in6_addr ip) +{ + struct sockaddr_in6 *sa = (struct sockaddr_in6 *)ss; + memset(ss, '\0', sizeof(*ss)); + sa->sin6_family = AF_INET6; + sa->sin6_addr = ip; +} +#endif + +/** + * Are two IPs on the same subnet? + */ +bool same_net(const struct sockaddr *ip1, + const struct sockaddr *ip2, + const struct sockaddr *mask) +{ + if (ip1->sa_family != ip2->sa_family) { + /* Never on the same net. */ + return false; + } + +#if defined(HAVE_IPV6) + if (ip1->sa_family == AF_INET6) { + struct sockaddr_in6 ip1_6 = *(const struct sockaddr_in6 *)ip1; + struct sockaddr_in6 ip2_6 = *(const struct sockaddr_in6 *)ip2; + struct sockaddr_in6 mask_6 = *(const struct sockaddr_in6 *)mask; + char *p1 = (char *)&ip1_6.sin6_addr; + char *p2 = (char *)&ip2_6.sin6_addr; + char *m = (char *)&mask_6.sin6_addr; + size_t i; + + for (i = 0; i < sizeof(struct in6_addr); i++) { + *p1++ &= *m; + *p2++ &= *m; + m++; + } + return (memcmp(&ip1_6.sin6_addr, + &ip2_6.sin6_addr, + sizeof(struct in6_addr)) == 0); + } +#endif + if (ip1->sa_family == AF_INET) { + return same_net_v4(((const struct sockaddr_in *)ip1)->sin_addr, + ((const struct sockaddr_in *)ip2)->sin_addr, + ((const struct sockaddr_in *)mask)->sin_addr); + } + return false; +} + +/** + * Are two sockaddr 's the same family and address ? Ignore port etc. + */ + +bool sockaddr_equal(const struct sockaddr *ip1, + const struct sockaddr *ip2) +{ + if (ip1->sa_family != ip2->sa_family) { + /* Never the same. */ + return false; + } + +#if defined(HAVE_IPV6) + if (ip1->sa_family == AF_INET6) { + return (memcmp(&((const struct sockaddr_in6 *)ip1)->sin6_addr, + &((const struct sockaddr_in6 *)ip2)->sin6_addr, + sizeof(struct in6_addr)) == 0); + } +#endif + if (ip1->sa_family == AF_INET) { + return (memcmp(&((const struct sockaddr_in *)ip1)->sin_addr, + &((const struct sockaddr_in *)ip2)->sin_addr, + sizeof(struct in_addr)) == 0); + } + return false; +} + +/** + * Is an IP address the INADDR_ANY or in6addr_any value ? + */ +bool is_address_any(const struct sockaddr *psa) +{ +#if defined(HAVE_IPV6) + if (psa->sa_family == AF_INET6) { + const struct sockaddr_in6 *si6 = (const struct sockaddr_in6 *)psa; + if (memcmp(&in6addr_any, + &si6->sin6_addr, + sizeof(in6addr_any)) == 0) { + return true; + } + return false; + } +#endif + if (psa->sa_family == AF_INET) { + const struct sockaddr_in *si = (const struct sockaddr_in *)psa; + if (si->sin_addr.s_addr == INADDR_ANY) { + return true; + } + return false; + } + return false; +} + +void set_sockaddr_port(struct sockaddr *psa, uint16_t port) +{ +#if defined(HAVE_IPV6) + if (psa->sa_family == AF_INET6) { + ((struct sockaddr_in6 *)psa)->sin6_port = htons(port); + } +#endif + if (psa->sa_family == AF_INET) { + ((struct sockaddr_in *)psa)->sin_port = htons(port); + } +} + + +/**************************************************************************** + Get a port number in host byte order from a sockaddr_storage. +****************************************************************************/ + +uint16_t get_sockaddr_port(const struct sockaddr_storage *pss) +{ + uint16_t port = 0; + + if (pss->ss_family != AF_INET) { +#if defined(HAVE_IPV6) + /* IPv6 */ + const struct sockaddr_in6 *sa6 = + (const struct sockaddr_in6 *)pss; + port = ntohs(sa6->sin6_port); +#endif + } else { + const struct sockaddr_in *sa = + (const struct sockaddr_in *)pss; + port = ntohs(sa->sin_port); + } + return port; +} + +/**************************************************************************** + Print out an IPv4 or IPv6 address from a struct sockaddr_storage. +****************************************************************************/ + +char *print_sockaddr_len(char *dest, + size_t destlen, + const struct sockaddr *psa, + socklen_t psalen) +{ + if (destlen > 0) { + dest[0] = '\0'; + } + (void)sys_getnameinfo(psa, + psalen, + dest, destlen, + NULL, 0, + NI_NUMERICHOST); + return dest; +} + +/**************************************************************************** + Print out an IPv4 or IPv6 address from a struct sockaddr_storage. +****************************************************************************/ + +char *print_sockaddr(char *dest, + size_t destlen, + const struct sockaddr_storage *psa) +{ + return print_sockaddr_len(dest, destlen, (const struct sockaddr *)psa, + sizeof(struct sockaddr_storage)); +} + +/**************************************************************************** + Print out a canonical IPv4 or IPv6 address from a struct sockaddr_storage. +****************************************************************************/ + +char *print_canonical_sockaddr(TALLOC_CTX *ctx, + const struct sockaddr_storage *pss) +{ + char addr[INET6_ADDRSTRLEN]; + char *dest = NULL; + int ret; + + /* Linux getnameinfo() man pages says port is uninitialized if + service name is NULL. */ + + ret = sys_getnameinfo((const struct sockaddr *)pss, + sizeof(struct sockaddr_storage), + addr, sizeof(addr), + NULL, 0, + NI_NUMERICHOST); + if (ret != 0) { + return NULL; + } + + if (pss->ss_family != AF_INET) { +#if defined(HAVE_IPV6) + dest = talloc_asprintf(ctx, "[%s]", addr); +#else + return NULL; +#endif + } else { + dest = talloc_asprintf(ctx, "%s", addr); + } + + return dest; +} + +enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON}; + +typedef struct smb_socket_option { + const char *name; + int level; + int option; + int value; + int opttype; +} smb_socket_option; + +static const smb_socket_option socket_options[] = { + {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL}, + {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL}, + {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL}, +#ifdef TCP_NODELAY + {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL}, +#endif +#ifdef TCP_KEEPCNT + {"TCP_KEEPCNT", IPPROTO_TCP, TCP_KEEPCNT, 0, OPT_INT}, +#endif +#ifdef TCP_KEEPIDLE + {"TCP_KEEPIDLE", IPPROTO_TCP, TCP_KEEPIDLE, 0, OPT_INT}, +#endif +#ifdef TCP_KEEPINTVL + {"TCP_KEEPINTVL", IPPROTO_TCP, TCP_KEEPINTVL, 0, OPT_INT}, +#endif +#ifdef IPTOS_LOWDELAY + {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON}, +#endif +#ifdef IPTOS_THROUGHPUT + {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON}, +#endif +#ifdef SO_REUSEPORT + {"SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, 0, OPT_BOOL}, +#endif +#ifdef SO_SNDBUF + {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT}, +#endif +#ifdef SO_RCVBUF + {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT}, +#endif +#ifdef SO_SNDLOWAT + {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT}, +#endif +#ifdef SO_RCVLOWAT + {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT}, +#endif +#ifdef SO_SNDTIMEO + {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT}, +#endif +#ifdef SO_RCVTIMEO + {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT}, +#endif +#ifdef TCP_FASTACK + {"TCP_FASTACK", IPPROTO_TCP, TCP_FASTACK, 0, OPT_INT}, +#endif +#ifdef TCP_QUICKACK + {"TCP_QUICKACK", IPPROTO_TCP, TCP_QUICKACK, 0, OPT_BOOL}, +#endif +#ifdef TCP_NODELAYACK + {"TCP_NODELAYACK", IPPROTO_TCP, TCP_NODELAYACK, 0, OPT_BOOL}, +#endif +#ifdef TCP_KEEPALIVE_THRESHOLD + {"TCP_KEEPALIVE_THRESHOLD", IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD, 0, OPT_INT}, +#endif +#ifdef TCP_KEEPALIVE_ABORT_THRESHOLD + {"TCP_KEEPALIVE_ABORT_THRESHOLD", IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, 0, OPT_INT}, +#endif +#ifdef TCP_DEFER_ACCEPT + {"TCP_DEFER_ACCEPT", IPPROTO_TCP, TCP_DEFER_ACCEPT, 0, OPT_INT}, +#endif +#ifdef TCP_USER_TIMEOUT + {"TCP_USER_TIMEOUT", IPPROTO_TCP, TCP_USER_TIMEOUT, 0, OPT_INT}, +#endif + {NULL,0,0,0,0}}; + +/**************************************************************************** + Print socket options. +****************************************************************************/ + +static void print_socket_options(TALLOC_CTX *ctx, int s) +{ + const smb_socket_option *p = &socket_options[0]; + char *str = NULL; + + if (DEBUGLEVEL < 5) { + return; + } + + str = talloc_strdup(ctx, ""); + if (str == NULL) { + DBG_WARNING("talloc failed\n"); + goto done; + } + + for (; p->name != NULL; p++) { + int ret, val; + socklen_t vlen = sizeof(val); + + ret = getsockopt(s, p->level, p->option, (void *)&val, &vlen); + if (ret == -1) { + DBG_INFO("Could not test socket option %s: %s.\n", + p->name, strerror(errno)); + continue; + } + + talloc_asprintf_addbuf( + &str, + "%s%s=%d", + str[0] != '\0' ? ", " : "", + p->name, + val); + } + + DEBUG(5, ("socket options: %s\n", str)); +done: + TALLOC_FREE(str); + } + +/**************************************************************************** + Set user socket options. +****************************************************************************/ + +void set_socket_options(int fd, const char *options) +{ + TALLOC_CTX *ctx = talloc_new(NULL); + char *tok; + + while (next_token_talloc(ctx, &options, &tok," \t,")) { + int ret=0,i; + int value = 1; + char *p; + bool got_value = false; + + if ((p = strchr_m(tok,'='))) { + *p = 0; + value = atoi(p+1); + got_value = true; + } + + for (i=0;socket_options[i].name;i++) + if (strequal(socket_options[i].name,tok)) + break; + + if (!socket_options[i].name) { + DEBUG(0,("Unknown socket option %s\n",tok)); + continue; + } + + switch (socket_options[i].opttype) { + case OPT_BOOL: + case OPT_INT: + ret = setsockopt(fd,socket_options[i].level, + socket_options[i].option, + (char *)&value,sizeof(int)); + break; + + case OPT_ON: + if (got_value) + DEBUG(0,("syntax error - %s " + "does not take a value\n",tok)); + + { + int on = socket_options[i].value; + ret = setsockopt(fd,socket_options[i].level, + socket_options[i].option, + (char *)&on,sizeof(int)); + } + break; + } + + if (ret != 0) { + /* be aware that some systems like Solaris return + * EINVAL to a setsockopt() call when the client + * sent a RST previously - no need to worry */ + DEBUG(2,("Failed to set socket option %s (Error %s)\n", + tok, strerror(errno) )); + } + } + + print_socket_options(ctx, fd); + TALLOC_FREE(ctx); +} + +/* + * Utility function that copes only with AF_INET and AF_INET6 + * as that's all we're going to get out of DNS / NetBIOS / WINS + * name resolution functions. + */ + +bool sockaddr_storage_to_samba_sockaddr( + struct samba_sockaddr *sa, const struct sockaddr_storage *ss) +{ + sa->u.ss = *ss; + + switch (ss->ss_family) { + case AF_INET: + sa->sa_socklen = sizeof(struct sockaddr_in); + break; +#ifdef HAVE_IPV6 + case AF_INET6: + sa->sa_socklen = sizeof(struct sockaddr_in6); + break; +#endif + default: + return false; + } + return true; +} + +bool samba_sockaddr_set_port(struct samba_sockaddr *sa, uint16_t port) +{ + if (sa->u.sa.sa_family == AF_INET) { + sa->u.in.sin_port = htons(port); + return true; + } +#ifdef HAVE_IPV6 + if (sa->u.sa.sa_family == AF_INET6) { + sa->u.in6.sin6_port = htons(port); + return true; + } +#endif + return false; +} + +bool samba_sockaddr_get_port(const struct samba_sockaddr *sa, uint16_t *port) +{ + if (sa->u.sa.sa_family == AF_INET) { + *port = ntohs(sa->u.in.sin_port); + return true; + } +#ifdef HAVE_IPV6 + if (sa->u.sa.sa_family == AF_INET6) { + *port = ntohs(sa->u.in6.sin6_port); + return true; + } +#endif + return false; +} + +int samba_socket_poll_error(int fd) +{ + struct pollfd pfd = { + .fd = fd, +#ifdef POLLRDHUP + .events = POLLRDHUP, /* POLLERR and POLLHUP are not needed */ +#endif + }; + int ret; + + errno = 0; + ret = sys_poll_intr(&pfd, 1, 0); + if (ret == 0) { + return 0; + } + if (ret != 1) { + return POLLNVAL; + } + + if (pfd.revents & POLLERR) { + return POLLERR; + } + if (pfd.revents & POLLHUP) { + return POLLHUP; + } +#ifdef POLLRDHUP + if (pfd.revents & POLLRDHUP) { + return POLLRDHUP; + } +#endif + + /* should never be reached! */ + return POLLNVAL; +} + +int samba_socket_sock_error(int fd) +{ + int ret, error = 0; + socklen_t len = sizeof(error); + + /* + * if no data is available check if the socket is in error state. For + * dgram sockets it's the way to return ICMP error messages of + * connected sockets to the caller. + */ + ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len); + if (ret == -1) { + return ret; + } + if (error != 0) { + errno = error; + return -1; + } + return 0; +} + +int samba_socket_poll_or_sock_error(int fd) +{ + int ret; + int poll_error = 0; + + poll_error = samba_socket_poll_error(fd); + if (poll_error == 0) { + return 0; + } + +#ifdef POLLRDHUP + if (poll_error == POLLRDHUP) { + errno = ECONNRESET; + return -1; + } +#endif + + if (poll_error == POLLHUP) { + errno = EPIPE; + return -1; + } + + /* + * POLLERR and POLLNVAL fallback to + * getsockopt(fd, SOL_SOCKET, SO_ERROR) + * and force EPIPE as fallback. + */ + + errno = 0; + ret = samba_socket_sock_error(fd); + if (ret == 0) { + errno = EPIPE; + } + + if (errno == 0) { + errno = EPIPE; + } + + return -1; +} diff --git a/lib/util/util_net.h b/lib/util/util_net.h new file mode 100644 index 0000000..1aed45a --- /dev/null +++ b/lib/util/util_net.h @@ -0,0 +1,145 @@ +/* + Unix SMB/CIFS implementation. + Utility functions for Samba + Copyright (C) Andrew Tridgell 1992-1999 + Copyright (C) Jelmer Vernooij 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_UTIL_NET_H_ +#define _SAMBA_UTIL_NET_H_ + +#include "system/network.h" + +struct samba_sockaddr { + socklen_t sa_socklen; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifdef HAVE_IPV6 + struct sockaddr_in6 in6; +#endif + struct sockaddr_un un; + struct sockaddr_storage ss; + } u; +}; + +/* The following definitions come from lib/util/util_net.c */ + +void zero_sockaddr(struct sockaddr_storage *pss); + +bool interpret_string_addr_internal(struct addrinfo **ppres, + const char *str, int flags); + +bool interpret_string_addr(struct sockaddr_storage *pss, + const char *str, + int flags); + +/******************************************************************* + Map a text hostname or IP address (IPv4 or IPv6) into a + struct sockaddr_storage. Version that prefers IPv4. +******************************************************************/ + +bool interpret_string_addr_prefer_ipv4(struct sockaddr_storage *pss, + const char *str, + int flags); + +void set_sockaddr_port(struct sockaddr *psa, uint16_t port); + +/** + Check if an IP is the 0.0.0.0. +**/ +_PUBLIC_ bool is_zero_ip_v4(struct in_addr ip); + +void in_addr_to_sockaddr_storage(struct sockaddr_storage *ss, + struct in_addr ip); +#if defined(HAVE_IPV6) +/** + * Convert an IPv6 struct in_addr to a struct sockaddr_storage. + */ +void in6_addr_to_sockaddr_storage(struct sockaddr_storage *ss, + struct in6_addr ip); +#endif +/** + Are two IPs on the same subnet? +**/ +_PUBLIC_ bool same_net_v4(struct in_addr ip1,struct in_addr ip2,struct in_addr mask); + +/** + Return true if a string could be a pure IP address. +**/ +_PUBLIC_ bool is_ipaddress(const char *str); + +bool is_broadcast_addr(const struct sockaddr *pss); +bool is_loopback_ip_v4(struct in_addr ip); +bool is_loopback_addr(const struct sockaddr *pss); +bool is_zero_addr(const struct sockaddr_storage *pss); +void zero_ip_v4(struct in_addr *ip); +bool is_linklocal_addr(const struct sockaddr_storage *pss); +/** + Interpret an internet address or name into an IP address in 4 byte form. +**/ +_PUBLIC_ uint32_t interpret_addr(const char *str); + +/** + A convenient addition to interpret_addr(). +**/ +_PUBLIC_ struct in_addr interpret_addr2(const char *str); + +_PUBLIC_ bool is_ipaddress_v4(const char *str); +_PUBLIC_ bool is_ipv6_literal(const char *str); +_PUBLIC_ bool is_ipaddress_v6(const char *str); + +bool is_address_any(const struct sockaddr *psa); +bool same_net(const struct sockaddr *ip1, + const struct sockaddr *ip2, + const struct sockaddr *mask); +bool sockaddr_equal(const struct sockaddr *ip1, + const struct sockaddr *ip2); + +bool is_address_any(const struct sockaddr *psa); +uint16_t get_sockaddr_port(const struct sockaddr_storage *pss); +char *print_sockaddr_len(char *dest, + size_t destlen, + const struct sockaddr *psa, + socklen_t psalen); +char *print_sockaddr(char *dest, + size_t destlen, + const struct sockaddr_storage *psa); +char *print_canonical_sockaddr(TALLOC_CTX *ctx, + const struct sockaddr_storage *pss); + +void set_socket_options(int fd, const char *options); + +bool sockaddr_storage_to_samba_sockaddr( + struct samba_sockaddr *sa, const struct sockaddr_storage *ss); +bool samba_sockaddr_set_port(struct samba_sockaddr *sa, uint16_t port); +bool samba_sockaddr_get_port(const struct samba_sockaddr *sa, uint16_t *port); + +/* + * check for POLLERR or POLL*HUP + */ +int samba_socket_poll_error(int fd); +/* + * getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) + */ +int samba_socket_sock_error(int fd); +/* + * check for POLL*HUP and fallback to + * getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) + */ +int samba_socket_poll_or_sock_error(int fd); + +#endif /* _SAMBA_UTIL_NET_H_ */ diff --git a/lib/util/util_paths.c b/lib/util/util_paths.c new file mode 100644 index 0000000..ce93028 --- /dev/null +++ b/lib/util/util_paths.c @@ -0,0 +1,170 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001-2007 + Copyright (C) Simo Sorce 2001 + Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 + Copyright (C) James Peach 2006 + Copyright (c) 2020 Andreas Schneider <asn@samba.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "dynconfig/dynconfig.h" +#include "lib/util/util_paths.h" +#include "system/passwd.h" +#include "system/filesys.h" + +/** + * @brief Returns an absolute path to a file in the Samba modules directory. + * + * @param name File to find, relative to MODULESDIR. + * + * @retval Pointer to a string containing the full path. + **/ + +char *modules_path(TALLOC_CTX *mem_ctx, const char *name) +{ + return talloc_asprintf(mem_ctx, "%s/%s", get_dyn_MODULESDIR(), name); +} + +/** + * @brief Returns an absolute path to a file in the Samba data directory. + * + * @param name File to find, relative to CODEPAGEDIR. + * + * @retval Pointer to a talloc'ed string containing the full path. + **/ + +char *data_path(TALLOC_CTX *mem_ctx, const char *name) +{ + return talloc_asprintf(mem_ctx, "%s/%s", get_dyn_CODEPAGEDIR(), name); +} + +/** + * @brief Returns the platform specific shared library extension. + * + * @retval Pointer to a const char * containing the extension. + **/ + +const char *shlib_ext(void) +{ + return get_dyn_SHLIBEXT(); +} + +static char *get_user_home_dir(TALLOC_CTX *mem_ctx) +{ + struct passwd pwd = {0}; + struct passwd *pwdbuf = NULL; + char *buf = NULL; + char *out = NULL; + long int initlen; + size_t len; + int rc; + + initlen = sysconf(_SC_GETPW_R_SIZE_MAX); + if (initlen == -1) { + len = 1024; + } else { + len = (size_t)initlen; + } + buf = talloc_size(mem_ctx, len); + if (buf == NULL) { + return NULL; + } + + rc = getpwuid_r(getuid(), &pwd, buf, len, &pwdbuf); + while (rc == ERANGE) { + size_t newlen = 2 * len; + if (newlen < len) { + /* Overflow */ + goto done; + } + len = newlen; + buf = talloc_realloc_size(mem_ctx, buf, len); + if (buf == NULL) { + goto done; + } + rc = getpwuid_r(getuid(), &pwd, buf, len, &pwdbuf); + } + if (rc != 0 || pwdbuf == NULL ) { + const char *szPath = getenv("HOME"); + if (szPath == NULL) { + goto done; + } + len = strnlen(szPath, PATH_MAX); + if (len >= PATH_MAX) { + goto done; + } + out = talloc_strdup(mem_ctx, szPath); + goto done; + } + + out = talloc_strdup(mem_ctx, pwd.pw_dir); +done: + TALLOC_FREE(buf); + return out; +} + +char *path_expand_tilde(TALLOC_CTX *mem_ctx, const char *d) +{ + char *h = NULL, *r = NULL; + const char *p = NULL; + struct stat sb = {0}; + int rc; + + if (d[0] != '~') { + return talloc_strdup(mem_ctx, d); + } + d++; + + /* handle ~user/path */ + p = strchr(d, '/'); + if (p != NULL && p > d) { + struct passwd *pw; + size_t s = p - d; + char u[128]; + + if (s >= sizeof(u)) { + return NULL; + } + memcpy(u, d, s); + u[s] = '\0'; + + pw = getpwnam(u); + if (pw == NULL) { + return NULL; + } + h = talloc_strdup(mem_ctx, pw->pw_dir); + } else { + p = d; + h = get_user_home_dir(mem_ctx); + } + if (h == NULL) { + return NULL; + } + + rc = stat(h, &sb); + if (rc != 0) { + TALLOC_FREE(h); + return NULL; + } + + r = talloc_asprintf(mem_ctx, "%s%s", h, p); + TALLOC_FREE(h); + + return r; +} diff --git a/lib/util/util_paths.h b/lib/util/util_paths.h new file mode 100644 index 0000000..cf34f69 --- /dev/null +++ b/lib/util/util_paths.h @@ -0,0 +1,63 @@ +/* + * Unix SMB/CIFS implementation. + * Samba utility functions + * Copyright (C) Andrew Tridgell 1992-1998 + * Copyright (C) Jeremy Allison 2001-2007 + * Copyright (C) Simo Sorce 2001 + * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 + * Copyright (C) James Peach 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LIB_UTIL_PATHS_H__ +#define __LIB_UTIL_PATHS_H__ + +#include <talloc.h> + +/** + * @brief Returns an absolute path to a file in the Samba modules directory. + * + * @param name File to find, relative to MODULESDIR. + * + * @retval Pointer to a string containing the full path. + **/ +char *modules_path(TALLOC_CTX *mem_ctx, const char *name); + +/** + * @brief Returns an absolute path to a file in the Samba data directory. + * + * @param name File to find, relative to CODEPAGEDIR. + * + * @retval Pointer to a talloc'ed string containing the full path. + **/ +char *data_path(TALLOC_CTX *mem_ctx, const char *name); + +/** + * @brief Returns the platform specific shared library extension. + * + * @retval Pointer to a const char * containing the extension. + **/ +const char *shlib_ext(void); + +/** + * @brief Expand a directory starting with a tilde '~' + * + * @param[in] d The directory to expand. + * + * @return The expanded directory, NULL on error. + */ +char *path_expand_tilde(TALLOC_CTX *mem_ctx, const char *d); + +#endif diff --git a/lib/util/util_process.c b/lib/util/util_process.c new file mode 100644 index 0000000..a10b85c --- /dev/null +++ b/lib/util/util_process.c @@ -0,0 +1,101 @@ +/* + * Unix SMB/CIFS implementation. + * + * Process utils. + * + * Copyright (c) 2013 Andreas Schneider <asn@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "util_process.h" +#include "replace.h" + +#ifdef HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif + +/* + * These variables are static so that we can access them + * with process_get_short_title() and process_get_long_title(). The + * purpose of this is to allow smb_panic_log() to print them. + */ +static char short_comment[16] = {0,}; +static char long_comment[256] = {0,}; +static char binary_name[256]; + +void process_set_title(const char *short_format, const char *long_format, ...) +{ +#if defined(HAVE_PRCTL) && defined(PR_SET_NAME) + if (short_format != NULL) { + va_list ap; + + va_start(ap, long_format); + vsnprintf(short_comment, sizeof(short_comment), short_format, ap); + va_end(ap); + + prctl(PR_SET_NAME, (unsigned long) short_comment, 0, 0, 0); + } +#endif + + if (long_format != NULL) { + va_list ap; + + va_start(ap, long_format); + vsnprintf(long_comment, sizeof(long_comment), long_format, ap); + va_end(ap); + + setproctitle("%s", long_comment); + } +} + +const char *process_get_short_title(void) +{ + return short_comment; +} + +const char *process_get_long_title(void) +{ + return long_comment; +} + +/* + * This is just for debugging in a panic, so we don't want to do + * anything more than return a fixed pointer, so we save a copy to a + * static variable. + */ +void process_save_binary_name(const char *progname) +{ + strlcpy(binary_name, progname, sizeof(binary_name)); +} + +/* Samba binaries will set this during popt handling */ +const char *process_get_saved_binary_name(void) +{ + return binary_name; +} + + +int prctl_set_comment(const char *comment_format, ...) +{ + char comment[16]; + va_list ap; + + va_start(ap, comment_format); + vsnprintf(comment, sizeof(comment), comment_format, ap); + va_end(ap); + + process_set_title("%s", "%s", comment); + return 0; +} diff --git a/lib/util/util_process.h b/lib/util/util_process.h new file mode 100644 index 0000000..4da135b --- /dev/null +++ b/lib/util/util_process.h @@ -0,0 +1,84 @@ +/* + * Unix SMB/CIFS implementation. + * + * Process utils. + * + * Copyright (c) 2013 Andreas Schneider <asn@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SAMBA_UTIL_PROCESS_H +#define _SAMBA_UTIL_PROCESS_H + +#include "replace.h" + +/** + * @brief Set the process comment name. + * + * @param[in] comment The comment to set which shouldn't be longer than 16 + * 16 characters (including \0). + * + * @return -1 on error, 0 on success. + */ +int prctl_set_comment(const char *comment_format, ...) PRINTF_ATTRIBUTE(1,2); + +/** + * @brief Set the process comment name and longname + * + * @param[in] short_format The comment to set which shouldn't be longer than 16 + * 16 characters (including \0). + * @param[in] long_format The format string and arguments to produce the long + * form of the process name. + * + * @return -1 on error, 0 on success. + */ +void process_set_title(const char *short_format, const char *long_format, ...) + PRINTF_ATTRIBUTE(1,3) PRINTF_ATTRIBUTE(2,3); + +/** + * @brief Get the process comment name set from process_set_title() + * + * @return process comment name + */ +const char *process_get_short_title(void); + +/** + * @brief Get the process longname set from process_set_title() + * + * @return process longname + */ +const char *process_get_long_title(void); + +/* + * @brief Save the binary name for later printing in smb_panic() + * + * @param[in] progname The binary name at process startup + * + * This is just for debugging in a panic, so we don't want to do + * anything more than return a fixed pointer, so we save a copy to a + * static variable. + */ +void process_save_binary_name(const char *progname); + +/** + * @brief Get the binary name set at startup process_save_binary_name() + * + * @return binary name set at startup + */ +/* Samba binaries will set this during popt handling */ +const char *process_get_saved_binary_name(void); + + +#endif diff --git a/lib/util/util_pw.c b/lib/util/util_pw.c new file mode 100644 index 0000000..8035de4 --- /dev/null +++ b/lib/util/util_pw.c @@ -0,0 +1,99 @@ +/* + Unix SMB/CIFS implementation. + + Safe versions of getpw* calls + + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-2005 + Copyright (C) Andrew Bartlett 2002 + Copyright (C) Timur Bakeyev 2005 + Copyright (C) Bjoern Jacke 2006-2007 + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include <talloc.h> +#include "system/passwd.h" +#include "lib/util/util_pw.h" + +struct passwd *tcopy_passwd(TALLOC_CTX *mem_ctx, + const struct passwd *from) +{ + struct passwd *ret; + size_t len = 0; + + len += strlen(from->pw_name)+1; + len += strlen(from->pw_passwd)+1; + len += strlen(from->pw_gecos)+1; + len += strlen(from->pw_dir)+1; + len += strlen(from->pw_shell)+1; + + ret = talloc_pooled_object(mem_ctx, struct passwd, 5, len); + + if (ret == NULL) { + return NULL; + } + + ret->pw_name = talloc_strdup(ret, from->pw_name); + ret->pw_passwd = talloc_strdup(ret, from->pw_passwd); + ret->pw_uid = from->pw_uid; + ret->pw_gid = from->pw_gid; + ret->pw_gecos = talloc_strdup(ret, from->pw_gecos); + ret->pw_dir = talloc_strdup(ret, from->pw_dir); + ret->pw_shell = talloc_strdup(ret, from->pw_shell); + + return ret; +} + +struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name) +{ + struct passwd *temp; + + temp = getpwnam(name); + + if (!temp) { +#if 0 + if (errno == ENOMEM) { + /* what now? */ + } +#endif + return NULL; + } + + return tcopy_passwd(mem_ctx, temp); +} + +/**************************************************************************** + talloc'ed version of getpwuid. +****************************************************************************/ + +struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid) +{ + struct passwd *temp; + + temp = getpwuid(uid); + + if (!temp) { +#if 0 + if (errno == ENOMEM) { + /* what now? */ + } +#endif + return NULL; + } + + return tcopy_passwd(mem_ctx, temp); +} diff --git a/lib/util/util_pw.h b/lib/util/util_pw.h new file mode 100644 index 0000000..fae4da9 --- /dev/null +++ b/lib/util/util_pw.h @@ -0,0 +1,32 @@ +/* + Unix SMB/CIFS implementation. + + Safe versions of getpw* calls + + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1997-2001. + Copyright (C) Andrew Bartlett 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __LIB_UTIL_UTIL_PW_H__ +#define __LIB_UTIL_UTIL_PW_H__ + +struct passwd *tcopy_passwd(TALLOC_CTX *mem_ctx, + const struct passwd *from); +struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name); +struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid); + +#endif /* __LIB_UTIL_UTIL_PW_H__ */ diff --git a/lib/util/util_runcmd.c b/lib/util/util_runcmd.c new file mode 100644 index 0000000..ea2e8ee --- /dev/null +++ b/lib/util/util_runcmd.c @@ -0,0 +1,379 @@ +/* + Unix SMB/CIFS implementation. + + run a child command + + Copyright (C) Andrew Tridgell 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +/* + this runs a child command with stdout and stderr going to the Samba + log + */ + +#include "replace.h" +#include "system/filesys.h" +#include "system/wait.h" +#include <tevent.h> +#include "lib/util/samba_util.h" +#include "lib/util/debug.h" +#include "../lib/util/tevent_unix.h" +#include "../lib/util/tfork.h" +#include "../lib/util/sys_rw.h" + +struct samba_runcmd_state { + int stdout_log_level; + int stderr_log_level; + struct tevent_fd *fde_stdout; + struct tevent_fd *fde_stderr; + struct tevent_fd *fde_status; + int fd_stdin, fd_stdout, fd_stderr, fd_status; + char *arg0; + pid_t pid; + struct tfork *tfork; + char buf[1024]; + uint16_t buf_used; +}; + +static void samba_runcmd_cleanup_fn(struct tevent_req *req, + enum tevent_req_state req_state) +{ + struct samba_runcmd_state *state = tevent_req_data( + req, struct samba_runcmd_state); + + if (state->tfork != NULL) { + tfork_destroy(&state->tfork); + } + state->pid = -1; + + if (state->fd_stdin != -1) { + close(state->fd_stdin); + state->fd_stdin = -1; + } +} + +int samba_runcmd_export_stdin(struct tevent_req *req) +{ + struct samba_runcmd_state *state = tevent_req_data(req, + struct samba_runcmd_state); + int ret = state->fd_stdin; + + state->fd_stdin = -1; + + return ret; +} + +static void samba_runcmd_io_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data); + +/* + run a command as a child process, with a timeout. + + any stdout/stderr from the child will appear in the Samba logs with + the specified log levels + */ +struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct timeval endtime, + int stdout_log_level, + int stderr_log_level, + const char * const *argv0, ...) +{ + struct tevent_req *req; + struct samba_runcmd_state *state; + int p1[2], p2[2], p3[2]; + char **argv; + va_list ap; + + if (argv0 == NULL) { + return NULL; + } + + req = tevent_req_create(mem_ctx, &state, + struct samba_runcmd_state); + if (req == NULL) { + return NULL; + } + + state->stdout_log_level = stdout_log_level; + state->stderr_log_level = stderr_log_level; + state->fd_stdin = -1; + + state->arg0 = talloc_strdup(state, argv0[0]); + if (tevent_req_nomem(state->arg0, req)) { + return tevent_req_post(req, ev); + } + + if (pipe(p1) != 0) { + tevent_req_error(req, errno); + return tevent_req_post(req, ev); + } + if (pipe(p2) != 0) { + close(p1[0]); + close(p1[1]); + tevent_req_error(req, errno); + return tevent_req_post(req, ev); + } + if (pipe(p3) != 0) { + close(p1[0]); + close(p1[1]); + close(p2[0]); + close(p2[1]); + tevent_req_error(req, errno); + return tevent_req_post(req, ev); + } + + state->tfork = tfork_create(); + if (state->tfork == NULL) { + close(p1[0]); + close(p1[1]); + close(p2[0]); + close(p2[1]); + close(p3[0]); + close(p3[1]); + tevent_req_error(req, errno); + return tevent_req_post(req, ev); + } + state->pid = tfork_child_pid(state->tfork); + if (state->pid != 0) { + /* the parent */ + close(p1[1]); + close(p2[1]); + close(p3[0]); + state->fd_stdout = p1[0]; + state->fd_stderr = p2[0]; + state->fd_stdin = p3[1]; + state->fd_status = tfork_event_fd(state->tfork); + + set_blocking(state->fd_stdout, false); + set_blocking(state->fd_stderr, false); + set_blocking(state->fd_stdin, false); + set_blocking(state->fd_status, false); + + smb_set_close_on_exec(state->fd_stdin); + smb_set_close_on_exec(state->fd_stdout); + smb_set_close_on_exec(state->fd_stderr); + smb_set_close_on_exec(state->fd_status); + + tevent_req_set_cleanup_fn(req, samba_runcmd_cleanup_fn); + + state->fde_stdout = tevent_add_fd(ev, state, + state->fd_stdout, + TEVENT_FD_READ, + samba_runcmd_io_handler, + req); + if (tevent_req_nomem(state->fde_stdout, req)) { + close(state->fd_stdout); + close(state->fd_stderr); + close(state->fd_status); + return tevent_req_post(req, ev); + } + tevent_fd_set_auto_close(state->fde_stdout); + + state->fde_stderr = tevent_add_fd(ev, state, + state->fd_stderr, + TEVENT_FD_READ, + samba_runcmd_io_handler, + req); + if (tevent_req_nomem(state->fde_stdout, req)) { + close(state->fd_stdout); + close(state->fd_stderr); + close(state->fd_status); + return tevent_req_post(req, ev); + } + tevent_fd_set_auto_close(state->fde_stderr); + + state->fde_status = tevent_add_fd(ev, state, + state->fd_status, + TEVENT_FD_READ, + samba_runcmd_io_handler, + req); + if (tevent_req_nomem(state->fde_stdout, req)) { + close(state->fd_stdout); + close(state->fd_stderr); + close(state->fd_status); + return tevent_req_post(req, ev); + } + tevent_fd_set_auto_close(state->fde_status); + + if (!timeval_is_zero(&endtime)) { + tevent_req_set_endtime(req, ev, endtime); + } + + return req; + } + + /* the child */ + close(p1[0]); + close(p2[0]); + close(p3[1]); + close(0); + close(1); + close(2); + + /* we want to ensure that all of the network sockets we had + open are closed */ + tevent_re_initialise(ev); + + /* setup for logging to go to the parents debug log */ + dup2(p3[0], 0); + dup2(p1[1], 1); + dup2(p2[1], 2); + + close(p1[1]); + close(p2[1]); + close(p3[0]); + + argv = str_list_copy(state, discard_const_p(const char *, argv0)); + if (!argv) { + fprintf(stderr, "Out of memory in child\n"); + _exit(255); + } + + va_start(ap, argv0); + while (1) { + const char **l; + char *arg = va_arg(ap, char *); + if (arg == NULL) break; + l = discard_const_p(const char *, argv); + l = str_list_add(l, arg); + if (l == NULL) { + fprintf(stderr, "Out of memory in child\n"); + _exit(255); + } + argv = discard_const_p(char *, l); + } + va_end(ap); + + (void)execvp(state->arg0, argv); + fprintf(stderr, "Failed to exec child - %s\n", strerror(errno)); + _exit(255); + return NULL; +} + +/* + handle stdout/stderr from the child + */ +static void samba_runcmd_io_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + struct tevent_req *req = talloc_get_type_abort(private_data, + struct tevent_req); + struct samba_runcmd_state *state = tevent_req_data(req, + struct samba_runcmd_state); + int level; + char *p; + int n, fd; + + if (!(flags & TEVENT_FD_READ)) { + return; + } + + if (fde == state->fde_stdout) { + level = state->stdout_log_level; + fd = state->fd_stdout; + } else if (fde == state->fde_stderr) { + level = state->stderr_log_level; + fd = state->fd_stderr; + } else { + int status; + + status = tfork_status(&state->tfork, false); + if (status == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + return; + } + DBG_ERR("Bad read on status pipe\n"); + tevent_req_error(req, errno); + return; + } + state->pid = -1; + TALLOC_FREE(fde); + + if (WIFEXITED(status)) { + status = WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + status = WTERMSIG(status); + } else { + status = ECHILD; + } + + DBG_NOTICE("Child %s exited %d\n", state->arg0, status); + if (status != 0) { + tevent_req_error(req, status); + return; + } + + tevent_req_done(req); + return; + } + + n = read(fd, &state->buf[state->buf_used], + sizeof(state->buf) - state->buf_used); + if (n > 0) { + state->buf_used += n; + } else if (n == 0) { + if (fde == state->fde_stdout) { + talloc_free(fde); + state->fde_stdout = NULL; + return; + } + if (fde == state->fde_stderr) { + talloc_free(fde); + state->fde_stderr = NULL; + return; + } + return; + } + + while (state->buf_used > 0 && + (p = (char *)memchr(state->buf, '\n', state->buf_used)) != NULL) { + int n1 = (p - state->buf)+1; + int n2 = n1 - 1; + /* swallow \r from child processes */ + if (n2 > 0 && state->buf[n2-1] == '\r') { + n2--; + } + DEBUG(level,("%s: %*.*s\n", state->arg0, n2, n2, state->buf)); + memmove(state->buf, p+1, sizeof(state->buf) - n1); + state->buf_used -= n1; + } + + /* the buffer could have completely filled - unfortunately we have + no choice but to dump it out straight away */ + if (state->buf_used == sizeof(state->buf)) { + DEBUG(level,("%s: %*.*s\n", + state->arg0, state->buf_used, + state->buf_used, state->buf)); + state->buf_used = 0; + } +} + +int samba_runcmd_recv(struct tevent_req *req, int *perrno) +{ + if (tevent_req_is_unix_error(req, perrno)) { + tevent_req_received(req); + return -1; + } + + tevent_req_received(req); + return 0; +} diff --git a/lib/util/util_str.c b/lib/util/util_str.c new file mode 100644 index 0000000..7c1d15d --- /dev/null +++ b/lib/util/util_str.c @@ -0,0 +1,307 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Simo Sorce 2001-2002 + Copyright (C) Martin Pool 2003 + Copyright (C) James Peach 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "lib/util/samba_util.h" +#include "system/locale.h" +#include "smb_strtox.h" +#undef strncasecmp +#undef strcasemp + +/** + * @file + * @brief String utilities. + **/ + +/** + * Parse a string containing a boolean value. + * + * val will be set to the read value. + * + * @retval true if a boolean value was parsed, false otherwise. + */ +_PUBLIC_ bool conv_str_bool(const char * str, bool * val) +{ + char * end = NULL; + long lval; + + if (str == NULL || *str == '\0') { + return false; + } + + lval = strtol(str, &end, 10 /* base */); + if (end == NULL || *end != '\0' || end == str) { + return set_boolean(str, val); + } + + *val = (lval) ? true : false; + return true; +} + +/** + * Convert a size specification like 16K into an integral number of bytes. + **/ +_PUBLIC_ bool conv_str_size_error(const char * str, uint64_t * val) +{ + char * end = NULL; + unsigned long long lval; + int error = 0; + + if (str == NULL || *str == '\0') { + return false; + } + + lval = smb_strtoull(str, &end, 10, &error, SMB_STR_STANDARD); + if (error != 0) { + return false; + } + + if (*end) { + if (strwicmp(end, "K") == 0) { + lval *= 1024ULL; + } else if (strwicmp(end, "M") == 0) { + lval *= (1024ULL * 1024ULL); + } else if (strwicmp(end, "G") == 0) { + lval *= (1024ULL * 1024ULL * 1024ULL); + } else if (strwicmp(end, "T") == 0) { + lval *= (1024ULL * 1024ULL * 1024ULL * 1024ULL); + } else if (strwicmp(end, "P") == 0) { + lval *= (1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL); + } else { + return false; + } + } + + *val = (uint64_t)lval; + return true; +} + +/** + * Parse a uint64_t value from a string + * + * val will be set to the value read. + * + * @retval true if parsing was successful, false otherwise + */ +_PUBLIC_ bool conv_str_u64(const char * str, uint64_t * val) +{ + unsigned long long lval; + int error = 0; + + if (str == NULL || *str == '\0') { + return false; + } + + lval = smb_strtoull(str, NULL, 10, &error, SMB_STR_FULL_STR_CONV); + if (error != 0) { + return false; + } + + *val = (uint64_t)lval; + return true; +} + +/** + * Compare 2 strings. + * + * @note The comparison is case-insensitive. + **/ +_PUBLIC_ bool strequal(const char *s1, const char *s2) +{ + if (s1 == s2) + return true; + if (!s1 || !s2) + return false; + + return strcasecmp_m(s1,s2) == 0; +} + +/** + * @file + * @brief String utilities. + **/ + +static bool next_token_internal_talloc(TALLOC_CTX *ctx, + const char **ptr, + char **pp_buff, + const char *sep, + bool ltrim) +{ + const char *s; + const char *saved_s; + char *pbuf; + bool quoted; + size_t len=1; + + *pp_buff = NULL; + if (!ptr) { + return(false); + } + + s = *ptr; + + /* default to simple separators */ + if (!sep) { + sep = " \t\n\r"; + } + + /* find the first non sep char, if left-trimming is requested */ + if (ltrim) { + while (*s && strchr_m(sep,*s)) { + s++; + } + } + + /* nothing left? */ + if (!*s) { + return false; + } + + /* When restarting we need to go from here. */ + saved_s = s; + + /* Work out the length needed. */ + for (quoted = false; *s && + (quoted || !strchr_m(sep,*s)); s++) { + if (*s == '\"') { + quoted = !quoted; + } else { + len++; + } + } + + /* We started with len = 1 so we have space for the nul. */ + *pp_buff = talloc_array(ctx, char, len); + if (!*pp_buff) { + return false; + } + + /* copy over the token */ + pbuf = *pp_buff; + s = saved_s; + for (quoted = false; *s && + (quoted || !strchr_m(sep,*s)); s++) { + if ( *s == '\"' ) { + quoted = !quoted; + } else { + *pbuf++ = *s; + } + } + + *ptr = (*s) ? s+1 : s; + *pbuf = 0; + + return true; +} + +bool next_token_talloc(TALLOC_CTX *ctx, + const char **ptr, + char **pp_buff, + const char *sep) +{ + return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true); +} + +/* + * Get the next token from a string, return false if none found. Handles + * double-quotes. This version does not trim leading separator characters + * before looking for a token. + */ + +bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx, + const char **ptr, + char **pp_buff, + const char *sep) +{ + return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false); +} + +/** + * Get the next token from a string, return False if none found. + * Handles double-quotes. + * + * Based on a routine by GJC@VILLAGE.COM. + * Extensively modified by Andrew.Tridgell@anu.edu.au + **/ +_PUBLIC_ bool next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) +{ + const char *s; + bool quoted; + size_t len=1; + + if (!ptr) + return false; + + s = *ptr; + + /* default to simple separators */ + if (!sep) + sep = " \t\n\r"; + + /* find the first non sep char */ + while (*s && strchr_m(sep,*s)) + s++; + + /* nothing left? */ + if (!*s) + return false; + + /* copy over the token */ + for (quoted = false; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) { + if (*s == '\"') { + quoted = !quoted; + } else { + len++; + *buff++ = *s; + } + } + + *ptr = (*s) ? s+1 : s; + *buff = 0; + + return true; +} + +/** + Set a boolean variable from the text value stored in the passed string. + Returns true in success, false if the passed string does not correctly + represent a boolean. +**/ + +_PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean) +{ + if (strwicmp(boolean_string, "yes") == 0 || + strwicmp(boolean_string, "true") == 0 || + strwicmp(boolean_string, "on") == 0 || + strwicmp(boolean_string, "1") == 0) { + *boolean = true; + return true; + } else if (strwicmp(boolean_string, "no") == 0 || + strwicmp(boolean_string, "false") == 0 || + strwicmp(boolean_string, "off") == 0 || + strwicmp(boolean_string, "0") == 0) { + *boolean = false; + return true; + } + return false; +} diff --git a/lib/util/util_str_common.c b/lib/util/util_str_common.c new file mode 100644 index 0000000..bf66647 --- /dev/null +++ b/lib/util/util_str_common.c @@ -0,0 +1,154 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Simo Sorce 2001-2002 + Copyright (C) Martin Pool 2003 + Copyright (C) James Peach 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/locale.h" +#include "lib/util/samba_util.h" + +/** +Do a case-insensitive, whitespace-ignoring ASCII string compare. +**/ +_PUBLIC_ int strwicmp(const char *psz1, const char *psz2) +{ + /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */ + /* appropriate value. */ + if (psz1 == psz2) + return (0); + else if (psz1 == NULL) + return (-1); + else if (psz2 == NULL) + return (1); + + /* sync the strings on first non-whitespace */ + while (1) { + while (isspace((int)*psz1)) + psz1++; + while (isspace((int)*psz2)) + psz2++; + + /* + * This does not do a genuine multi-byte comparison, + * instead it just uses the fast-path for ASCII in + * these common routines + */ + if (toupper_m((unsigned char)*psz1) != toupper_m((unsigned char)*psz2) + || *psz1 == '\0' + || *psz2 == '\0') + break; + psz1++; + psz2++; + } + return (*psz1 - *psz2); +} + +/** + String replace. + NOTE: oldc and newc must be 7 bit characters +**/ +void string_replace( char *s, char oldc, char newc ) +{ + while (*s != '\0') { + size_t c_size; + next_codepoint(s, &c_size); + + if (c_size == 1) { + if (*s == oldc) { + *s = newc; + } + } + s += c_size; + } +} + + +/** + Paranoid strcpy into a buffer of given length (includes terminating + zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars + and replaces with '_'. Deliberately does *NOT* check for multibyte + characters. Treats src as an array of bytes, not as a multibyte + string. Any byte >0x7f is automatically converted to '_'. + other_safe_chars must also contain an ascii string (bytes<0x7f). +**/ + +char *alpha_strcpy(char *dest, + const char *src, + const char *other_safe_chars, + size_t maxlength) +{ + size_t len, i; + + if (!dest) { + smb_panic("ERROR: NULL dest in alpha_strcpy"); + } + + if (!src) { + *dest = 0; + return dest; + } + + len = strlen(src); + if (len >= maxlength) + len = maxlength - 1; + + if (!other_safe_chars) + other_safe_chars = ""; + + for(i = 0; i < len; i++) { + int val = (src[i] & 0xff); + if (val > 0x7f) { + dest[i] = '_'; + continue; + } + if (isupper(val) || islower(val) || + isdigit(val) || strchr(other_safe_chars, val)) + dest[i] = src[i]; + else + dest[i] = '_'; + } + + dest[i] = '\0'; + + return dest; +} + +char *talloc_alpha_strcpy(TALLOC_CTX *mem_ctx, + const char *src, + const char *other_safe_chars) +{ + char *dest = NULL; + size_t slen; + + if (src == NULL) { + return NULL; + } + + slen = strlen(src); + + dest = talloc_zero_size(mem_ctx, slen + 1); + if (dest == NULL) { + return NULL; + } + + alpha_strcpy(dest, src, other_safe_chars, slen + 1); + return dest; +} diff --git a/lib/util/util_str_escape.c b/lib/util/util_str_escape.c new file mode 100644 index 0000000..750d64b --- /dev/null +++ b/lib/util/util_str_escape.c @@ -0,0 +1,127 @@ +/* + Samba string escaping routines + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "lib/util/debug.h" +#include "lib/util/util_str_escape.h" + + +/* + * Calculate the encoded length of a character for log_escape + * + */ +static size_t encoded_length(char c) +{ + if (c != '\\' && c > 0x1F) { + return 1; + } else { + switch (c) { + case '\a': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + case '\v': + case '\\': + return 2; /* C escape sequence */ + default: + return 4; /* hex escape \xhh */ + } + } +} + +/* + * Escape any control characters in the inputs to prevent them from + * interfering with the log output. + */ +char *log_escape(TALLOC_CTX *frame, const char *in) +{ + size_t size = 0; /* Space to allocate for the escaped data */ + char *encoded = NULL; /* The encoded string */ + const char *c; + char *e; + + if (in == NULL) { + return NULL; + } + + /* Calculate the size required for the escaped array */ + c = in; + while (*c) { + size += encoded_length( *c); + c++; + } + size++; + + encoded = talloc_array( frame, char, size); + if (encoded == NULL) { + DBG_ERR( "Out of memory allocating encoded string\n"); + return NULL; + } + + c = in; + e = encoded; + while (*c) { + if (*c != '\\' && *c > 0x1F) { + *e++ = *c++; + } else { + switch (*c) { + case '\a': + *e++ = '\\'; + *e++ = 'a'; + break; + case '\b': + *e++ = '\\'; + *e++ = 'b'; + break; + case '\f': + *e++ = '\\'; + *e++ = 'f'; + break; + case '\n': + *e++ = '\\'; + *e++ = 'n'; + break; + case '\r': + *e++ = '\\'; + *e++ = 'r'; + break; + case '\t': + *e++ = '\\'; + *e++ = 't'; + break; + case '\v': + *e++ = '\\'; + *e++ = 'v'; + break; + case '\\': + *e++ = '\\'; + *e++ = '\\'; + break; + default: + snprintf(e, 5, "\\x%02X", *c); + e += 4; + } + c++; + } + } + *e = '\0'; + return encoded; +} diff --git a/lib/util/util_str_escape.h b/lib/util/util_str_escape.h new file mode 100644 index 0000000..0b4c596 --- /dev/null +++ b/lib/util/util_str_escape.h @@ -0,0 +1,27 @@ +/* + Samba string escaping routines + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_UTIL_STR_ESCAPE_H +#define _SAMBA_UTIL_STR_ESCAPE_H + +#include <talloc.h> + +char *log_escape(TALLOC_CTX *frame, const char *in); + +#endif diff --git a/lib/util/util_str_hex.c b/lib/util/util_str_hex.c new file mode 100644 index 0000000..553fb30 --- /dev/null +++ b/lib/util/util_str_hex.c @@ -0,0 +1,69 @@ +#include "replace.h" +#include "util_str_hex.h" +#include "lib/util/data_blob.h" +#include "librpc/gen_ndr/misc.h" + +static bool hex_uint16(const char *in, uint16_t *out) +{ + uint8_t hi=0, lo=0; + bool ok = hex_byte(in, &hi) && hex_byte(in+2, &lo); + *out = (((uint16_t)hi)<<8) + lo; + return ok; +} + +bool hex_uint32(const char *in, uint32_t *out) +{ + uint16_t hi=0, lo=0; + bool ok = hex_uint16(in, &hi) && hex_uint16(in+4, &lo); + *out = (((uint32_t)hi)<<16) + lo; + return ok; +} + +bool parse_guid_string(const char *s, struct GUID *guid) +{ + bool ok; + int i; + /* "e12b56b6-0a95-11d1-adbb-00c04fd8d5cd" + | | | | | + | | | | \ node[6] + | | | \_____ clock_seq[2] + | | \__________ time_hi_and_version + | \_______________ time_mid + \_____________________ time_low + */ + + ok = hex_uint32(s, &guid->time_low); + if (!ok || (s[8] != '-')) { + return false; + } + s += 9; + + ok = hex_uint16(s, &guid->time_mid); + if (!ok || (s[4] != '-')) { + return false; + } + s += 5; + + ok = hex_uint16(s, &guid->time_hi_and_version); + if (!ok || (s[4] != '-')) { + return false; + } + s += 5; + + ok = hex_byte(s, &guid->clock_seq[0]) && + hex_byte(s+2, &guid->clock_seq[1]); + if (!ok || (s[4] != '-')) { + return false; + } + s += 5; + + for (i = 0; i < 6; i++) { + ok = hex_byte(s, &guid->node[i]); + if (!ok) { + return false; + } + s += 2; + } + + return true; +} diff --git a/lib/util/util_str_hex.h b/lib/util/util_str_hex.h new file mode 100644 index 0000000..7dd527f --- /dev/null +++ b/lib/util/util_str_hex.h @@ -0,0 +1,5 @@ +#include "replace.h" + +bool hex_uint32(const char *in, uint32_t *out); +struct GUID; +bool parse_guid_string(const char *s, struct GUID *guid); diff --git a/lib/util/util_strlist.c b/lib/util/util_strlist.c new file mode 100644 index 0000000..e102002 --- /dev/null +++ b/lib/util/util_strlist.c @@ -0,0 +1,561 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "debug.h" +#include "tsort.h" + +#include "util_strlist.h" + +#undef strcasecmp + +/** + * @file + * @brief String list manipulation + */ + +/** + build an empty (only NULL terminated) list of strings (for expansion with str_list_add() etc) +*/ +_PUBLIC_ char **str_list_make_empty(TALLOC_CTX *mem_ctx) +{ + char **ret = talloc_zero_array(mem_ctx, char *, 1); + return ret; +} + +/** + place the only element 'entry' into a new, NULL terminated string list +*/ +_PUBLIC_ char **str_list_make_single(TALLOC_CTX *mem_ctx, const char *entry) +{ + char **ret = NULL; + + ret = talloc_array(mem_ctx, char *, 2); + if (ret == NULL) { + return NULL; + } + + ret[0] = talloc_strdup(ret, entry); + if (!ret[0]) { + talloc_free(ret); + return NULL; + } + ret[1] = NULL; + + return ret; +} + +/** + build a null terminated list of strings from a input string and a + separator list. The separator list must contain characters less than + or equal to 0x2f for this to work correctly on multi-byte strings +*/ +_PUBLIC_ char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep) +{ + int num_elements = 0; + char **ret = NULL; + + if (sep == NULL) { + sep = LIST_SEP; + } + + ret = talloc_array(mem_ctx, char *, 1); + if (ret == NULL) { + return NULL; + } + + while (string && *string) { + size_t len = strcspn(string, sep); + char **ret2; + + if (len == 0) { + string += strspn(string, sep); + continue; + } + + ret2 = talloc_realloc(mem_ctx, ret, char *, + num_elements+2); + if (ret2 == NULL) { + talloc_free(ret); + return NULL; + } + ret = ret2; + + ret[num_elements] = talloc_strndup(ret, string, len); + if (ret[num_elements] == NULL) { + talloc_free(ret); + return NULL; + } + + num_elements++; + string += len; + } + + ret[num_elements] = NULL; + + return ret; +} + +/** + * build a null terminated list of strings from an argv-like input string + * Entries are separated by spaces and can be enclosed by quotes. + * Does NOT support escaping + */ +_PUBLIC_ char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string, const char *sep) +{ + int num_elements = 0; + char **ret = NULL; + + ret = talloc_array(mem_ctx, char *, 1); + if (ret == NULL) { + return NULL; + } + + if (sep == NULL) + sep = " \t\n\r"; + + while (string && *string) { + size_t len = strcspn(string, sep); + char *element; + char **ret2; + + if (len == 0) { + string += strspn(string, sep); + continue; + } + + if (*string == '\"') { + string++; + len = strcspn(string, "\""); + element = talloc_strndup(ret, string, len); + string += len + 1; + } else { + element = talloc_strndup(ret, string, len); + string += len; + } + + if (element == NULL) { + talloc_free(ret); + return NULL; + } + + ret2 = talloc_realloc(mem_ctx, ret, char *, num_elements+2); + if (ret2 == NULL) { + talloc_free(ret); + return NULL; + } + ret = ret2; + + ret[num_elements] = element; + + num_elements++; + } + + ret[num_elements] = NULL; + + return ret; + +} + +/** + * join a list back to one string + */ +_PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char separator) +{ + char *ret = NULL; + int i; + + if (list[0] == NULL) + return talloc_strdup(mem_ctx, ""); + + ret = talloc_strdup(mem_ctx, list[0]); + + for (i = 1; list[i]; i++) { + talloc_asprintf_addbuf(&ret, "%c%s", separator, list[i]); + } + + return ret; +} + +/** join a list back to one (shell-like) string; entries + * separated by spaces, using quotes where necessary */ +_PUBLIC_ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep) +{ + char *ret = NULL; + int i; + + if (list[0] == NULL) + return talloc_strdup(mem_ctx, ""); + + if (strchr(list[0], ' ') || strlen(list[0]) == 0) + ret = talloc_asprintf(mem_ctx, "\"%s\"", list[0]); + else + ret = talloc_strdup(mem_ctx, list[0]); + + for (i = 1; list[i]; i++) { + if (strchr(list[i], ' ') || strlen(list[i]) == 0) { + talloc_asprintf_addbuf(&ret, "%c\"%s\"", sep, list[i]); + } else { + talloc_asprintf_addbuf(&ret, "%c%s", sep, list[i]); + } + } + + return ret; +} + +/** + return the number of elements in a string list +*/ +_PUBLIC_ size_t str_list_length(const char * const *list) +{ + size_t ret; + for (ret=0;list && list[ret];ret++) /* noop */ ; + return ret; +} + + +/** + copy a string list +*/ +_PUBLIC_ char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list) +{ + int i; + char **ret; + + if (list == NULL) + return NULL; + + ret = talloc_array(mem_ctx, char *, str_list_length(list)+1); + if (ret == NULL) + return NULL; + + for (i=0;list && list[i];i++) { + ret[i] = talloc_strdup(ret, list[i]); + if (ret[i] == NULL) { + talloc_free(ret); + return NULL; + } + } + ret[i] = NULL; + return ret; +} + +/** + Return true if all the elements of the list match exactly. + */ +_PUBLIC_ bool str_list_equal(const char * const *list1, + const char * const *list2) +{ + int i; + + if (list1 == NULL || list2 == NULL) { + return (list1 == list2); + } + + for (i=0;list1[i] && list2[i];i++) { + if (strcmp(list1[i], list2[i]) != 0) { + return false; + } + } + if (list1[i] || list2[i]) { + return false; + } + return true; +} + + +/** + add an entry to a string list +*/ +_PUBLIC_ const char **str_list_add(const char **list, const char *s) +{ + size_t len = str_list_length(list); + const char **ret; + + ret = talloc_realloc(NULL, list, const char *, len+2); + if (ret == NULL) return NULL; + + ret[len] = talloc_strdup(ret, s); + if (ret[len] == NULL) return NULL; + + ret[len+1] = NULL; + + return ret; +} + +/** + * @brief Extend a talloc'ed string list with a printf'ed string + * + * str_list_add_printf() does nothing if *plist is NULL and it sets + * *plist to NULL on failure. It is designed to avoid intermediate + * NULL checks: + * + * argv = str_list_make_empty(ctx); + * str_list_add_printf(&argv, "smbstatus"); + * str_list_add_printf(&argv, "--configfile=%s", config); + * if (argv == NULL) { + * goto nomem; + * } + * + * @param[in,out] plist The talloc'ed list to extend + * @param[in] fmt The format string + */ +void str_list_add_printf(char ***plist, const char *fmt, ...) +{ + char **list = *plist; + size_t len; + char **tmp = NULL; + va_list ap; + + if (list == NULL) { + return; + } + len = str_list_length((const char * const *)list); + + tmp = talloc_realloc(NULL, list, char *, len+2); + if (tmp == NULL) { + goto fail; + } + list = tmp; + list[len+1] = NULL; + + va_start(ap, fmt); + list[len] = talloc_vasprintf(list, fmt, ap); + va_end(ap); + + if (list[len] == NULL) { + goto fail; + } + *plist = list; + + return; +fail: + TALLOC_FREE(list); + *plist = NULL; +} + +/** + remove an entry from a string list +*/ +_PUBLIC_ void str_list_remove(const char **list, const char *s) +{ + int i; + + for (i=0;list[i];i++) { + if (strcmp(list[i], s) == 0) break; + } + if (!list[i]) return; + + for (;list[i];i++) { + list[i] = list[i+1]; + } +} + + +/** + return true if a string is in a list +*/ +_PUBLIC_ bool str_list_check(const char **list, const char *s) +{ + int i; + + for (i=0; list != NULL && list[i] != NULL; i++) { + if (strcmp(list[i], s) == 0) return true; + } + return false; +} + +/** + return true if a string is in a list, case insensitively +*/ +_PUBLIC_ bool str_list_check_ci(const char **list, const char *s) +{ + int i; + + for (i=0; list != NULL && list[i] != NULL; i++) { + if (strcasecmp(list[i], s) == 0) return true; + } + return false; +} + + +/** + append one list to another - expanding list1 +*/ +_PUBLIC_ const char **str_list_append(const char **list1, + const char * const *list2) +{ + size_t len1 = str_list_length(list1); + size_t len2 = str_list_length(list2); + const char **ret; + size_t i; + + ret = talloc_realloc(NULL, list1, const char *, len1+len2+1); + if (ret == NULL) return NULL; + + for (i=len1;i<len1+len2;i++) { + ret[i] = talloc_strdup(ret, list2[i-len1]); + if (ret[i] == NULL) { + return NULL; + } + } + ret[i] = NULL; + + return ret; +} + +static int list_cmp(const char **el1, const char **el2) +{ + return strcmp(*el1, *el2); +} + +/* + return a list that only contains the unique elements of a list, + removing any duplicates + */ +_PUBLIC_ const char **str_list_unique(const char **list) +{ + size_t len = str_list_length(list); + const char **list2; + size_t i, j; + if (len < 2) { + return list; + } + list2 = (const char **)talloc_memdup(list, list, + sizeof(list[0])*(len+1)); + TYPESAFE_QSORT(list2, len, list_cmp); + list[0] = list2[0]; + for (i=j=1;i<len;i++) { + if (strcmp(list2[i], list[j-1]) != 0) { + list[j] = list2[i]; + j++; + } + } + list[j] = NULL; + list = talloc_realloc(NULL, list, const char *, j + 1); + talloc_free(list2); + return list; +} + +/* + very useful when debugging complex list related code + */ +_PUBLIC_ void str_list_show(const char **list) +{ + int i; + DEBUG(0,("{ ")); + for (i=0;list && list[i];i++) { + DEBUG(0,("\"%s\", ", list[i])); + } + DEBUG(0,("}\n")); +} + + + +/** + append one list to another - expanding list1 + this assumes the elements of list2 are const pointers, so we can re-use them +*/ +_PUBLIC_ const char **str_list_append_const(const char **list1, + const char **list2) +{ + size_t len1 = str_list_length(list1); + size_t len2 = str_list_length(list2); + const char **ret; + size_t i; + + ret = talloc_realloc(NULL, list1, const char *, len1+len2+1); + if (ret == NULL) return NULL; + + for (i=len1;i<len1+len2;i++) { + ret[i] = list2[i-len1]; + } + ret[i] = NULL; + + return ret; +} + +/** + * Add a string to an array of strings. + * + * num should be a pointer to an integer that holds the current + * number of elements in strings. It will be updated by this function. + */ +_PUBLIC_ bool add_string_to_array(TALLOC_CTX *mem_ctx, + const char *str, const char ***strings, size_t *num) +{ + char *dup_str = talloc_strdup(mem_ctx, str); + + *strings = talloc_realloc(mem_ctx, + *strings, + const char *, ((*num)+1)); + + if ((*strings == NULL) || (dup_str == NULL)) { + *num = 0; + return false; + } + + (*strings)[*num] = dup_str; + *num += 1; + + return true; +} + +/** + add an entry to a string list + this assumes s will not change +*/ +_PUBLIC_ const char **str_list_add_const(const char **list, const char *s) +{ + size_t len = str_list_length(list); + const char **ret; + + ret = talloc_realloc(NULL, list, const char *, len+2); + if (ret == NULL) return NULL; + + ret[len] = s; + ret[len+1] = NULL; + + return ret; +} + +/** + copy a string list + this assumes list will not change +*/ +_PUBLIC_ const char **str_list_copy_const(TALLOC_CTX *mem_ctx, + const char **list) +{ + int i; + const char **ret; + + if (list == NULL) + return NULL; + + ret = talloc_array(mem_ctx, const char *, str_list_length(list)+1); + if (ret == NULL) + return NULL; + + for (i=0;list && list[i];i++) { + ret[i] = list[i]; + } + ret[i] = NULL; + return ret; +} diff --git a/lib/util/util_strlist.h b/lib/util/util_strlist.h new file mode 100644 index 0000000..5c3a7ee --- /dev/null +++ b/lib/util/util_strlist.h @@ -0,0 +1,156 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SAMBA_UTIL_STRLIST_H +#define _SAMBA_UTIL_STRLIST_H + +#include <talloc.h> + +/* separators for lists */ +#ifndef LIST_SEP +#define LIST_SEP " \t,\n\r" +#endif + +/** + build an empty (only NULL terminated) list of strings (for expansion with str_list_add() etc) +*/ +char **str_list_make_empty(TALLOC_CTX *mem_ctx); + +/** + place the only element 'entry' into a new, NULL terminated string list +*/ +char **str_list_make_single(TALLOC_CTX *mem_ctx, + const char *entry); + +/** + build a null terminated list of strings from a input string and a + separator list. The separator list must contain characters less than + or equal to 0x2f for this to work correctly on multi-byte strings +*/ +char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, + const char *sep); + +/** + * build a null terminated list of strings from an argv-like input string + * Entries are separated by spaces and can be enclosed by quotes. + * Does NOT support escaping + */ +char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string, + const char *sep); + +/** + * join a list back to one string + */ +char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, + char separator); + +/** join a list back to one (shell-like) string; entries + * separated by spaces, using quotes where necessary */ +char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, + char sep); + +/** + return the number of elements in a string list +*/ +size_t str_list_length(const char * const *list); + +/** + copy a string list +*/ +char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list); + +/** + Return true if all the elements of the list match exactly. + */ +bool str_list_equal(const char * const *list1, + const char * const *list2); + +/** + add an entry to a string list +*/ +const char **str_list_add(const char **list, const char *s); + +/* + * Extend a list with a printf'ed string + */ +void str_list_add_printf(char ***plist, const char *fmt, ...) + PRINTF_ATTRIBUTE(2,3); + +/** + remove an entry from a string list +*/ +void str_list_remove(const char **list, const char *s); + +/** + return true if a string is in a list +*/ +bool str_list_check(const char **list, const char *s); + +/** + return true if a string is in a list, case insensitively +*/ +bool str_list_check_ci(const char **list, const char *s); +/** + append one list to another - expanding list1 +*/ +const char **str_list_append(const char **list1, + const char * const *list2); + +/** + remove duplicate elements from a list +*/ +const char **str_list_unique(const char **list); + +/* + very useful when debugging complex list related code + */ +void str_list_show(const char **list); + + +/** + append one list to another - expanding list1 + this assumes the elements of list2 are const pointers, so we can re-use them +*/ +const char **str_list_append_const(const char **list1, + const char **list2); + +/** + Add a string to an array of strings. + + num should be a pointer to an integer that holds the current + number of elements in strings. It will be updated by this function. + */ +bool add_string_to_array(TALLOC_CTX *mem_ctx, + const char *str, const char ***strings, size_t *num); + +/** + add an entry to a string list + this assumes s will not change +*/ +const char **str_list_add_const(const char **list, const char *s); + +/** + copy a string list + this assumes list will not change +*/ +const char **str_list_copy_const(TALLOC_CTX *mem_ctx, + const char **list); + +#endif /* _SAMBA_UTIL_STRLIST_H */ diff --git a/lib/util/util_strlist_v3.c b/lib/util/util_strlist_v3.c new file mode 100644 index 0000000..75973f2 --- /dev/null +++ b/lib/util/util_strlist_v3.c @@ -0,0 +1,128 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "system/locale.h" +#include "lib/util/tsort.h" + +#undef strcasecmp + +/** + * @file + * @brief String list manipulation v3 + */ + +/** + * Needed for making an "unconst" list "const" + */ +_PUBLIC_ const char **const_str_list(char **list) +{ + return discard_const_p(const char *, list); +} + +/** + * str_list_make, v3 version. The v4 version does not + * look at quoted strings with embedded blanks, so + * do NOT merge this function please! + */ +#define S_LIST_ABS 16 /* List Allocation Block Size */ + +char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string, + const char *sep) +{ + char **list; + const char *str; + char *s, *tok; + int num, lsize; + + if (!string || !*string) + return NULL; + + list = talloc_array(mem_ctx, char *, S_LIST_ABS+1); + if (list == NULL) { + return NULL; + } + lsize = S_LIST_ABS; + + s = talloc_strdup(list, string); + if (s == NULL) { + DEBUG(0,("str_list_make: Unable to allocate memory\n")); + TALLOC_FREE(list); + return NULL; + } + + /* + * DON'T REPLACE THIS BY "LIST_SEP". The common version of + * LIST_SEP does not contain the ;, which used to be accepted + * by Samba 4.0 before param merges. It would be the far + * better solution to split the _v3 version again to source3/ + * where it belongs, see the _v3 in its name. + * + * Unfortunately it is referenced in /lib/param/loadparm.c, + * which depends on the version that the AD-DC mandates, + * namely without the ; as part of the list separator. I am + * missing the waf fu to properly work around the wrong + * include paths here for this defect. + */ + if (sep == NULL) { + sep = " \t,;\n\r"; + } + + num = 0; + str = s; + + while (next_token_talloc(list, &str, &tok, sep)) { + + if (num == lsize) { + char **tmp; + + lsize += S_LIST_ABS; + + tmp = talloc_realloc(mem_ctx, list, char *, + lsize + 1); + if (tmp == NULL) { + DEBUG(0,("str_list_make: " + "Unable to allocate memory\n")); + TALLOC_FREE(list); + return NULL; + } + + list = tmp; + + memset (&list[num], 0, + ((sizeof(char*)) * (S_LIST_ABS +1))); + } + + list[num] = tok; + num += 1; + } + + list[num] = NULL; + + TALLOC_FREE(s); + return list; +} + +const char **str_list_make_v3_const(TALLOC_CTX *mem_ctx, + const char *string, + const char *sep) +{ + return const_str_list(str_list_make_v3(mem_ctx, string, sep)); +} diff --git a/lib/util/util_tdb.c b/lib/util/util_tdb.c new file mode 100644 index 0000000..d8672c3 --- /dev/null +++ b/lib/util/util_tdb.c @@ -0,0 +1,525 @@ +/* + Unix SMB/CIFS implementation. + + tdb utility functions + + Copyright (C) Andrew Tridgell 1992-2006 + Copyright (C) Volker Lendecke 2007-2011 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include <talloc.h> +#include "libcli/util/ntstatus.h" +#include "lib/util/memory.h" +#include "lib/util/byteorder.h" +#include "system/filesys.h" +#include "../lib/tdb/include/tdb.h" +#include "../lib/util/util_tdb.h" + +/* these are little tdb utility functions that are meant to make + dealing with a tdb database a little less cumbersome in Samba */ + +/*************************************************************** + Make a TDB_DATA and keep the const warning in one place +****************************************************************/ + +TDB_DATA make_tdb_data(const uint8_t *dptr, size_t dsize) +{ + TDB_DATA ret; + ret.dptr = discard_const_p(uint8_t, dptr); + ret.dsize = dsize; + return ret; +} + +bool tdb_data_equal(TDB_DATA t1, TDB_DATA t2) +{ + if (t1.dsize != t2.dsize) { + return false; + } + return (memcmp(t1.dptr, t2.dptr, t1.dsize) == 0); +} + +bool tdb_data_is_empty(TDB_DATA d) +{ + return (d.dsize == 0) || (d.dptr == NULL); +} + +TDB_DATA string_tdb_data(const char *string) +{ + return make_tdb_data((const uint8_t *)string, string ? strlen(string) : 0 ); +} + +TDB_DATA string_term_tdb_data(const char *string) +{ + return make_tdb_data((const uint8_t *)string, string ? strlen(string) + 1 : 0); +} + +TDB_DATA tdb_data_talloc_copy(TALLOC_CTX* mem_ctx, TDB_DATA data) { + TDB_DATA ret = { + .dptr = (uint8_t *)talloc_size(mem_ctx, data.dsize+1), + .dsize = data.dsize + }; + if (ret.dptr == NULL) { + ret.dsize = 0; + } else { + memcpy(ret.dptr, data.dptr, data.dsize); + ret.dptr[ret.dsize] = '\0'; + } + return ret; +} + + +/**************************************************************************** + Lock a chain by string. Return non-zero if lock failed. +****************************************************************************/ + +int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval) +{ + TDB_DATA key = string_term_tdb_data(keyval); + + return tdb_chainlock(tdb, key); +} + +/**************************************************************************** + Unlock a chain by string. +****************************************************************************/ + +void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval) +{ + TDB_DATA key = string_term_tdb_data(keyval); + + tdb_chainunlock(tdb, key); +} + +/**************************************************************************** + Read lock a chain by string. Return non-zero if lock failed. +****************************************************************************/ + +int tdb_read_lock_bystring(struct tdb_context *tdb, const char *keyval) +{ + TDB_DATA key = string_term_tdb_data(keyval); + + return tdb_chainlock_read(tdb, key); +} + +/**************************************************************************** + Read unlock a chain by string. +****************************************************************************/ + +void tdb_read_unlock_bystring(struct tdb_context *tdb, const char *keyval) +{ + TDB_DATA key = string_term_tdb_data(keyval); + + tdb_chainunlock_read(tdb, key); +} + + +/**************************************************************************** + Fetch a int32_t value by a arbitrary blob key, return -1 if not found. + Output is int32_t in native byte order. +****************************************************************************/ + +static int fetch_int32_parser(TDB_DATA key, TDB_DATA data, void *private_data) +{ + if (data.dsize == sizeof(int32_t)) { + *((int32_t *)private_data) = PULL_LE_I32(data.dptr, 0); + } + return 0; +} + +static int32_t tdb_fetch_int32_byblob(struct tdb_context *tdb, TDB_DATA key) +{ + int32_t v = -1; + int32_t ret = tdb_parse_record(tdb, key, fetch_int32_parser, &v); + if (ret == -1) { + return ret; + } + return v; +} + +/**************************************************************************** + Fetch a int32_t value by string key, return -1 if not found. + Output is int32_t in native byte order. +****************************************************************************/ + +int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr) +{ + return tdb_fetch_int32_byblob(tdb, string_term_tdb_data(keystr)); +} + +/**************************************************************************** + Store a int32_t value by an arbitrary blob key, return 0 on success, -ve on failure. + Input is int32_t in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +static int tdb_store_int32_byblob(struct tdb_context *tdb, TDB_DATA key, + int32_t v) +{ + TDB_DATA data; + int32_t v_store; + + SIVAL(&v_store,0,v); + data.dptr = (unsigned char *)&v_store; + data.dsize = sizeof(int32_t); + + return tdb_store(tdb, key, data, TDB_REPLACE); +} + +/**************************************************************************** + Store a int32_t value by string key, return 0 on success, -ve on failure. + Input is int32_t in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v) +{ + return tdb_store_int32_byblob(tdb, string_term_tdb_data(keystr), v); +} + +/**************************************************************************** + Fetch a uint32_t value by a arbitrary blob key, return false if not found. + Output is uint32_t in native byte order. +****************************************************************************/ + +static int fetch_uint32_parser(TDB_DATA key, TDB_DATA data, void *private_data) +{ + if (data.dsize != sizeof(uint32_t)) { + return -1; + } + *((uint32_t *)private_data) = PULL_LE_U32(data.dptr, 0); + return 0; +} + +static bool tdb_fetch_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, + uint32_t *value) +{ + int ret = tdb_parse_record(tdb, key, fetch_uint32_parser, value); + + if (ret == -1) { + return false; + } + + return true; +} + +/**************************************************************************** + Fetch a uint32_t value by string key, return false if not found. + Output is uint32_t in native byte order. +****************************************************************************/ + +bool tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value) +{ + return tdb_fetch_uint32_byblob(tdb, string_term_tdb_data(keystr), value); +} + +/**************************************************************************** + Store a uint32_t value by an arbitrary blob key, return true on success, false on failure. + Input is uint32_t in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +static bool tdb_store_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, + uint32_t value) +{ + TDB_DATA data; + uint32_t v_store; + bool ret = true; + + SIVAL(&v_store, 0, value); + data.dptr = (unsigned char *)&v_store; + data.dsize = sizeof(uint32_t); + + if (tdb_store(tdb, key, data, TDB_REPLACE) != 0) + ret = false; + + return ret; +} + +/**************************************************************************** + Store a uint32_t value by string key, return true on success, false on failure. + Input is uint32_t in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +bool tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value) +{ + return tdb_store_uint32_byblob(tdb, string_term_tdb_data(keystr), value); +} +/**************************************************************************** + Store a buffer by a null terminated string key. Return 0 on success, -ve + on failure. +****************************************************************************/ + +int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags) +{ + TDB_DATA key = string_term_tdb_data(keystr); + + return tdb_store(tdb, key, data, flags); +} + +/**************************************************************************** + Fetch a buffer using a null terminated string key. Don't forget to call + free() on the result dptr. +****************************************************************************/ + +TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr) +{ + TDB_DATA key = string_term_tdb_data(keystr); + + return tdb_fetch(tdb, key); +} + +/**************************************************************************** + Delete an entry using a null terminated string key. +****************************************************************************/ + +int tdb_delete_bystring(struct tdb_context *tdb, const char *keystr) +{ + TDB_DATA key = string_term_tdb_data(keystr); + + return tdb_delete(tdb, key); +} + +/**************************************************************************** + Atomic integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val) +{ + int32_t val; + int32_t ret = -1; + + if (tdb_lock_bystring(tdb, keystr) != 0) + return -1; + + if ((val = tdb_fetch_int32(tdb, keystr)) == -1) { + /* The lookup failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* but not because it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* It worked, set return value (oldval) to tdb data */ + *oldval = val; + } + + /* Increment value for storage and return next time */ + val += change_val; + + if (tdb_store_int32(tdb, keystr, val) != 0) + goto err_out; + + ret = 0; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +bool tdb_change_uint32_atomic(struct tdb_context *tdb, const char *keystr, uint32_t *oldval, uint32_t change_val) +{ + uint32_t val; + bool ret = false; + + if (tdb_lock_bystring(tdb, keystr) != 0) + return false; + + if (!tdb_fetch_uint32(tdb, keystr, &val)) { + /* It failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* and not because it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* it worked, set return value (oldval) to tdb data */ + *oldval = val; + + } + + /* get a new value to store */ + val += change_val; + + if (!tdb_store_uint32(tdb, keystr, val)) + goto err_out; + + ret = true; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Return an NTSTATUS from a TDB_ERROR +****************************************************************************/ + +NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err) +{ + NTSTATUS result; + + switch (err) { + case TDB_SUCCESS: + result = NT_STATUS_OK; + break; + case TDB_ERR_CORRUPT: + result = NT_STATUS_INTERNAL_DB_CORRUPTION; + break; + case TDB_ERR_IO: + result = NT_STATUS_UNEXPECTED_IO_ERROR; + break; + case TDB_ERR_OOM: + result = NT_STATUS_NO_MEMORY; + break; + case TDB_ERR_EXISTS: + result = NT_STATUS_OBJECT_NAME_COLLISION; + break; + + case TDB_ERR_LOCK: + /* + * TDB_ERR_LOCK is very broad, we could for example + * distinguish between fcntl locks and invalid lock + * sequences. So NT_STATUS_FILE_LOCK_CONFLICT is a + * compromise. + */ + result = NT_STATUS_FILE_LOCK_CONFLICT; + break; + + case TDB_ERR_NOLOCK: + case TDB_ERR_LOCK_TIMEOUT: + /* + * These two ones in the enum are not actually used + */ + result = NT_STATUS_FILE_LOCK_CONFLICT; + break; + case TDB_ERR_NOEXIST: + result = NT_STATUS_NOT_FOUND; + break; + case TDB_ERR_EINVAL: + result = NT_STATUS_INVALID_PARAMETER; + break; + case TDB_ERR_RDONLY: + result = NT_STATUS_ACCESS_DENIED; + break; + case TDB_ERR_NESTING: + result = NT_STATUS_INTERNAL_ERROR; + break; + default: + result = NT_STATUS_INTERNAL_ERROR; + break; + }; + return result; +} + +int map_unix_error_from_tdb(enum TDB_ERROR err) +{ + int result = EINVAL; + + switch (err) { + case TDB_SUCCESS: + result = 0; + break; + case TDB_ERR_CORRUPT: + result = EILSEQ; + break; + case TDB_ERR_IO: + result = EIO; + break; + case TDB_ERR_OOM: + result = ENOMEM; + break; + case TDB_ERR_EXISTS: + result = EEXIST; + break; + + case TDB_ERR_LOCK: + /* + * TDB_ERR_LOCK is very broad, we could for example + * distinguish between fcntl locks and invalid lock + * sequences. EWOULDBLOCK is wrong, but there is no real + * generic lock error code in errno.h + */ + result = EWOULDBLOCK; + break; + + case TDB_ERR_NOLOCK: + case TDB_ERR_LOCK_TIMEOUT: + /* + * These two ones in the enum are not actually used + */ + result = ENOLCK; + break; + case TDB_ERR_NOEXIST: + result = ENOENT; + break; + case TDB_ERR_EINVAL: + result = EINVAL; + break; + case TDB_ERR_RDONLY: + result = EROFS; + break; + case TDB_ERR_NESTING: + /* + * Well, this db is already busy... + */ + result = EBUSY; + break; + }; + return result; +} + +struct tdb_fetch_talloc_state { + TALLOC_CTX *mem_ctx; + uint8_t *buf; +}; + +static int tdb_fetch_talloc_parser(TDB_DATA key, TDB_DATA data, + void *private_data) +{ + struct tdb_fetch_talloc_state *state = private_data; + state->buf = talloc_memdup(state->mem_ctx, data.dptr, data.dsize); + return 0; +} + +int tdb_fetch_talloc(struct tdb_context *tdb, TDB_DATA key, + TALLOC_CTX *mem_ctx, uint8_t **buf) +{ + struct tdb_fetch_talloc_state state = { .mem_ctx = mem_ctx }; + int ret; + + ret = tdb_parse_record(tdb, key, tdb_fetch_talloc_parser, &state); + if (ret == -1) { + enum TDB_ERROR err = tdb_error(tdb); + return map_unix_error_from_tdb(err); + } + + if (state.buf == NULL) { + return ENOMEM; + } + + *buf = state.buf; + return 0; +} diff --git a/lib/util/util_tdb.h b/lib/util/util_tdb.h new file mode 100644 index 0000000..010521d --- /dev/null +++ b/lib/util/util_tdb.h @@ -0,0 +1,125 @@ +/* + Unix SMB/CIFS implementation. + + tdb utility functions + + Copyright (C) Andrew Tridgell 1992-2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _____LIB_UTIL_UTIL_TDB_H__ +#define _____LIB_UTIL_UTIL_TDB_H__ + +#include "replace.h" +#include <tdb.h> +#include "libcli/util/ntstatus.h" + +/*************************************************************** + Make a TDB_DATA and keep the const warning in one place +****************************************************************/ +TDB_DATA make_tdb_data(const uint8_t *dptr, size_t dsize); +bool tdb_data_equal(TDB_DATA t1, TDB_DATA t2); +bool tdb_data_is_empty(TDB_DATA d); +TDB_DATA string_tdb_data(const char *string); +TDB_DATA string_term_tdb_data(const char *string); +TDB_DATA tdb_data_talloc_copy(TALLOC_CTX* mem_ctx, TDB_DATA data); + +/**************************************************************************** + Lock a chain by string. Return non-zero if lock failed. +****************************************************************************/ +int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval); + +/**************************************************************************** + Unlock a chain by string. +****************************************************************************/ +void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval); + +/**************************************************************************** + Read lock a chain by string. Return non-zero if lock failed. +****************************************************************************/ +int tdb_read_lock_bystring(struct tdb_context *tdb, const char *keyval); + +/**************************************************************************** + Read unlock a chain by string. +****************************************************************************/ +void tdb_read_unlock_bystring(struct tdb_context *tdb, const char *keyval); + +/**************************************************************************** + Fetch a int32_t value by string key, return -1 if not found. + Output is int32_t in native byte order. +****************************************************************************/ +int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr); + +/**************************************************************************** + Store a int32_t value by string key, return 0 on success, -ve on failure. + Input is int32_t in native byte order. Output in tdb is in little-endian. +****************************************************************************/ +int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v); + +/**************************************************************************** + Fetch a uint32_t value by string key, return -1 if not found. + Output is uint32_t in native byte order. +****************************************************************************/ +bool tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value); + +/**************************************************************************** + Store a uint32_t value by string key, return true on success, false on failure. + Input is uint32_t in native byte order. Output in tdb is in little-endian. +****************************************************************************/ +bool tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value); + +/**************************************************************************** + Store a buffer by a null terminated string key. Return 0 on success, -ve + on failure. +****************************************************************************/ +int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags); + +/**************************************************************************** + Fetch a buffer using a null terminated string key. Don't forget to call + free() on the result dptr. +****************************************************************************/ +TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr); + +/**************************************************************************** + Delete an entry using a null terminated string key. 0 on success, -ve on err. +****************************************************************************/ +int tdb_delete_bystring(struct tdb_context *tdb, const char *keystr); + +/**************************************************************************** + Atomic integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ +int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val); + +/**************************************************************************** + Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ +bool tdb_change_uint32_atomic(struct tdb_context *tdb, const char *keystr, uint32_t *oldval, uint32_t change_val); + +/**************************************************************************** + Return an NTSTATUS from a TDB_ERROR +****************************************************************************/ + +NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err); + +/**************************************************************************** + Return an errno from a TDB_ERROR +****************************************************************************/ + +int map_unix_error_from_tdb(enum TDB_ERROR err); + +int tdb_fetch_talloc(struct tdb_context *tdb, TDB_DATA key, + TALLOC_CTX *mem_ctx, uint8_t **buf); + +#endif /* _____LIB_UTIL_UTIL_TDB_H__ */ diff --git a/lib/util/wscript b/lib/util/wscript new file mode 100644 index 0000000..425f659 --- /dev/null +++ b/lib/util/wscript @@ -0,0 +1,32 @@ +def options(opt): + ''' This is a bit strange, but disable is the flag, not enable. ''' + opt.add_option('--disable-fault-handling', action='store_true', dest='disable_fault_handling', help=('disable the fault handlers'), default=False) + + # We do not want libunwind by default (backtrace_symbols() in + # glibc is better) but allow (eg) IA-64 to build with it where it + # might be better (per old comment in fault.c) + opt.samba_add_onoff_option('libunwind', + default=None, + help='''Use libunwind instead of the default backtrace_symbols() + from libc, for example on IA-64 where it might give a better + backtrace.''') + + opt.add_option('--with-systemd', + help=("Enable systemd integration"), + action='store_true', dest='enable_systemd') + + opt.add_option('--without-systemd', + help=("Disable systemd integration"), + action='store_false', dest='enable_systemd') + + opt.add_option('--with-lttng', + help=("Enable lttng integration"), + action='store_true', dest='enable_lttng') + + opt.add_option('--without-lttng', + help=("Disable lttng integration"), + action='store_false', dest='enable_lttng') + + opt.add_option('--with-gpfs', + help=("Directory under which gpfs headers are installed"), + action="store", dest='gpfs_headers_dir') diff --git a/lib/util/wscript_build b/lib/util/wscript_build new file mode 100644 index 0000000..b4fcfea --- /dev/null +++ b/lib/util/wscript_build @@ -0,0 +1,415 @@ +#!/usr/bin/env python + +# Please add any new SAMBA_SUBSYSTEM/SAMBA_LIBRARY to the bottom of the file +# unless they are also required to build standalone ctdb. + +bld.SAMBA_LIBRARY('time-basic', + source='time_basic.c', + deps='replace', + private_library=True, + local_include=False) + +bld.SAMBA_SUBSYSTEM('tini', + source='tini.c', + provide_builtin_linking=True, + local_include=False) + +bld.SAMBA_SUBSYSTEM('tiniparser', + source='tiniparser.c', + deps='tini', + provide_builtin_linking=True, + local_include=False) + +bld.SAMBA_SUBSYSTEM('strv', + source='strv.c', + deps='talloc', + local_include=False) + +bld.SAMBA_SUBSYSTEM('close-low-fd', + source='close_low_fd.c', + deps='replace', + local_include=False) + +bld.SAMBA_LIBRARY('sys_rw', + source='sys_rw.c sys_rw_data.c', + deps='replace iov_buf', + local_include=False, + private_library=True) + +samba_debug_add_deps = '' +samba_debug_add_inc = '' + +if bld.CONFIG_SET('HAVE_GPFS'): + bld.SAMBA_SUBSYSTEM('gpfswrap', + source='gpfswrap.c', + deps='replace', + local_include=False, + includes=bld.CONFIG_GET('CPPPATH_GPFS')) + samba_debug_add_deps += ' gpfswrap' + samba_debug_add_inc += bld.CONFIG_GET('CPPPATH_GPFS') + +bld.SAMBA_LIBRARY('samba-debug', + source='debug.c', + deps='replace time-basic close-low-fd talloc socket-blocking' + samba_debug_add_deps, + public_deps='systemd systemd-journal lttng-ust', + local_include=False, + includes='lib/util/debug-classes ' + samba_debug_add_inc, + private_library=True) + +bld.SAMBA_LIBRARY('socket-blocking', + source='blocking.c', + local_include=False, + private_library=True) + +bld.SAMBA_LIBRARY('talloc_report', + source='talloc_report.c', + local_include=False, + public_deps='talloc', + private_library=True + ) + +bld.SAMBA_LIBRARY('talloc_report_printf', + source='talloc_report_printf.c', + local_include=False, + public_deps='talloc', + private_library=True + ) + +bld.SAMBA_SUBSYSTEM('smb-panic', + source=''' + fault.c + signal.c + util_process.c + ''', + deps=''' + replace + samba-debug + LIBUNWIND + execinfo + ''', + local_include=False) + +bld.SAMBA_SUBSYSTEM('samba-util-core', + source=''' + data_blob.c + util_file.c + sys_popen.c + time.c + util.c + idtree.c + substitute.c + util_strlist.c + strv_util.c + bitmap.c + select.c + pidfile.c + become_daemon.c + mkdir_p.c + ''', + deps=''' + time-basic + samba-debug + socket-blocking + talloc + tevent + execinfo + pthread + strv + tini + smb_strtox + smb-panic + gnutls + ''', + public_deps='systemd systemd-daemon sys_rw', + local_include=False) + +bld.SAMBA_SUBSYSTEM('smb_strtox', + source='smb_strtox.c', + provide_builtin_linking=True, + local_include=False) + + +bld.SAMBA_LIBRARY('iov_buf', + source='iov_buf.c', + deps='talloc', + local_include=False, + private_library=True) + +bld.SAMBA_LIBRARY('msghdr', + source='msghdr.c', + deps='replace iov_buf', + local_include=False, + private_library=True) + +bld.SAMBA_LIBRARY('genrand', + source='genrand.c', + deps='replace gnutls smb-panic', + local_include=False, + private_library=True) + +bld.SAMBA_LIBRARY('stable_sort', + source='stable_sort.c', + deps='replace', + public_deps='talloc', + local_include=False, + private_library=True) + +if bld.env.SAMBA_UTIL_CORE_ONLY: + + bld.SAMBA_LIBRARY('tevent-util', + source='tevent_unix.c', + local_include=False, + deps='tevent', + private_library=True) + +else: + + bld.env.public_headers_skip.append('charset_compat.h') + + bld.SAMBA_BINARY('genrandperf', + source='tests/genrandperf.c', + deps='genrand replace', + local_include=False, + install=False) + + # TODO: Rewrite ms_fnmatch_core() for a better API. + ms_fnmatch_cflags='' + if bld.CONFIG_SET('HAVE_WNO_ERROR_ARRAY_BOUNDS'): + ms_fnmatch_cflags='-Wno-error=array-bounds' + bld.SAMBA_SUBSYSTEM('SAMBA_UTIL_MS_FNMATCH', + source='ms_fnmatch.c', + deps='talloc', + cflags=ms_fnmatch_cflags, + local_include=False) + + bld.SAMBA_LIBRARY('samba-util', + source=''' + base64.c + dprintf.c + fsusage.c + genrand_util.c + getpass.c + idtree_random.c + memcache.c + params.c + rbtree.c + rfc1738.c + server_id.c + smb_threads.c + system.c + talloc_keep_secret.c + talloc_stack.c + tevent_debug.c + tfork.c + tftw.c + unix_match.c + util_id.c + util_net.c + util_paths.c + util_str.c + util_str_common.c + util_strlist_v3.c + ''', + deps=''' + samba-util-core + DYNCONFIG + close-low-fd + tiniparser + genrand + util_str_hex + SAMBA_UTIL_MS_FNMATCH + ''', + public_deps='talloc tevent execinfo pthread LIBCRYPTO charset util_setid', + public_headers=''' + attr.h + data_blob.h + debug.h + discard.h + time.h + idtree.h + idtree_random.h + blocking.h + signal.h + substitute.h + fault.h + genrand.h + tfork.h + ''', + header_path= [ ('dlinklist.h samba_util.h', '.'), ('*', 'util') ], + local_include=False, + vnum='0.0.1', + pc_files='samba-util.pc' + ) + + bld.SAMBA_LIBRARY('samba-modules', + source='modules.c', + deps='samba-errors samba-util', + local_include=False, + private_library=True) + + bld.SAMBA_LIBRARY('asn1util', + source='asn1.c', + deps='talloc samba-util', + private_library=True, + local_include=False) + + + bld.SAMBA_SUBSYSTEM('UNIX_PRIVS', + source='unix_privs.c', + autoproto='unix_privs.h', + deps='replace talloc', + local_include=False, + ) + + + bld.SAMBA_LIBRARY('util_tdb', + source='util_tdb.c', + local_include=False, + public_deps='tdb talloc', + private_library=True + ) + + bld.SAMBA_LIBRARY('tevent-util', + source=''' + tevent_unix.c + tevent_ntstatus.c + tevent_werror.c + tevent_req_profile.c + ''', + local_include=False, + public_deps='tevent samba-errors', + public_headers='tevent_ntstatus.h tevent_unix.h tevent_werror.h', + header_path=[ ('*', 'util') ], + pc_files=[], + vnum='0.0.1' + ) + + bld.SAMBA_LIBRARY('util_setid', + source='setid.c', + local_include=False, + private_library=True + ) + + bld.SAMBA_SUBSYSTEM('util_ldb', + source='util_ldb.c', + local_include=False, + public_deps='ldb', + public_headers='util_ldb.h' + ) + + + bld.SAMBA_SUBSYSTEM('UTIL_RUNCMD', + source='util_runcmd.c', + local_include=False, + public_deps='tevent' + ) + + bld.SAMBA_SUBSYSTEM('UTIL_PW', + source='util_pw.c', + local_include=False, + public_deps='talloc' + ) + + bld.SAMBA_LIBRARY('server_id_db', + source='server_id_db.c', + deps='talloc tdb strv util_tdb tdb-wrap samba-util', + local_include=False, + private_library=True) + + bld.SAMBA_SUBSYSTEM('access', + source='access.c', + deps='interfaces samba-util', + local_include=False) + + bld.SAMBA_SUBSYSTEM('util_str_escape', + source='util_str_escape.c', + deps='talloc', + local_include=False) + + bld.SAMBA_SUBSYSTEM('util_str_hex', + source='util_str_hex.c', + deps='talloc', + local_include=False) + + bld.SAMBA_BINARY('test_rfc1738', + source='tests/rfc1738.c', + deps='cmocka replace samba-util', + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_ms_fnmatch', + source='tests/test_ms_fnmatch.c', + deps='cmocka replace samba-util', + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_talloc_keep_secret', + source='tests/test_talloc_keep_secret.c', + deps='cmocka replace samba-util', + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_byteorder', + source='tests/test_byteorder.c', + deps='cmocka replace samba-util', + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_bytearray', + source='tests/test_bytearray.c', + deps='cmocka replace samba-util', + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_byteorder_verify', + source='tests/test_byteorder_verify.c', + deps='cmocka replace samba-util', + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_util_paths', + source='tests/test_util_paths.c', + deps='cmocka replace talloc samba-util', + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_util', + source='tests/test_util.c', + deps='cmocka replace talloc samba-util', + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_memcache', + source='tests/test_memcache.c', + deps='cmocka replace talloc samba-util', + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_sys_rw', + source='tests/test_sys_rw.c', + deps='cmocka replace samba-util', + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_s4_logging', + source='tests/test_logging.c', + deps=' '.join(['CMDLINE_S4', + 'samba-util', + 'popt']), + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_s3_logging', + source='tests/test_logging.c', + deps=' '.join(['CMDLINE_S3', + 'samba-util', + 'popt']), + cflags="-D USING_CMDLINE_S3", + local_include=False, + for_selftest=True) + + bld.SAMBA_BINARY('test_stable_sort', + source='tests/test_stable_sort.c', + deps='cmocka replace talloc stable_sort', + local_include=False, + for_selftest=True) diff --git a/lib/util/wscript_configure b/lib/util/wscript_configure new file mode 100644 index 0000000..27206e0 --- /dev/null +++ b/lib/util/wscript_configure @@ -0,0 +1,189 @@ +#!/usr/bin/env python +from waflib import Logs, Options, Errors + +import os, sys + +if Options.options.disable_fault_handling: + conf.DEFINE('HAVE_DISABLE_FAULT_HANDLING',1) + +# backtrace could be in libexecinfo or in libc. +# This is our preferred backtrace handler (more useful output than libunwind as at Ubuntu 20.04 x86_64) +conf.CHECK_FUNCS_IN('backtrace backtrace_symbols', 'execinfo', checklibc=True, headers='execinfo.h') +conf.CHECK_HEADERS('execinfo.h') + +conf.SET_TARGET_TYPE('LIBUNWIND', 'EMPTY') +if Options.options.with_libunwind: + if conf.check_cfg(package='libunwind-generic', + args='--cflags --libs', + msg='Checking for libunwind', + uselib_store='LIBUNWIND', + mandatory=False): + if conf.CHECK_HEADERS('libunwind.h'): + conf.SET_TARGET_TYPE('LIBUNWIND', 'SYSLIB') + else: + raise Errors.WafError('--with-libunwind specified but libunwind not found') +elif Options.options.with_libunwind == None: + if not conf.CONFIG_SET('HAVE_BACKTRACE_SYMBOLS') \ + and not Options.options.disable_fault_handling: + raise Errors.WafError( +'''backtrace_symbols() not found but +--with-libunwind not specified. +Use --without-libunwind to build without internal backtrace support or +--disable-fault-handling to totally defer fault handling to the OS.''') + +conf.CHECK_STRUCTURE_MEMBER('struct statvfs', 'f_frsize', define='HAVE_FRSIZE', headers='sys/statvfs.h') + +# all the different ways of doing statfs +statfs_types = [ + ( 'STAT_STATVFS', + 'statvfs (SVR4)', + 'struct statvfs fsd; exit(statvfs(0, &fsd))', + 'sys/statvfs.h' ), + + ( 'STAT_STATFS3_OSF1', + '3-argument statfs function (DEC OSF/1)', + 'struct statfs fsd; fsd.f_fsize = 0; exit(statfs(".", &fsd, sizeof(struct statfs)))', + 'sys/param.h sys/mount.h' ), + + ( 'STAT_STATFS2_BSIZE', + 'two-argument statfs with statfs.bsize', + 'struct statfs fsd; fsd.f_bsize = 0; exit(statfs(".", &fsd))', + 'sys/param.h sys/mount.h sys/vfs.h' ), + + ( 'STAT_STATFS4', + 'four-argument statfs (AIX-3.2.5, SVR3)', + 'struct statfs fsd; exit(statfs(".", &fsd, sizeof fsd, 0))', + 'sys/statfs.h' ), + + ( 'STAT_STATFS2_FSIZE', + 'two-argument statfs with statfs.fsize', + 'struct statfs fsd; fsd.f_fsize = 0; exit(statfs(".", &fsd))', + 'sys/param.h sys/mount.h' ), + + ( 'STAT_STATFS2_FS_DATA', + 'two-argument statfs with struct fs_data (Ultrix)', + 'struct fs_data fsd; exit(statfs(".", &fsd) != 1)', + 'sys/param.h sys/mount.h sys/fs_types.h' ) +] + +found_statfs=False +for (define, msg, code, headers) in statfs_types: + if conf.CHECK_CODE(code, + define=define, + headers=headers, + msg='Checking for %s' % msg, + local_include=False): + found_statfs=True + break + +if not found_statfs: + print("FATAL: Failed to find a statfs method") + raise + +conf.CHECK_CODE("""struct statfs fsd; + fsd.f_bsize = 0; + fsd.f_iosize = 0; + return (statfs (".", &fsd)); + """, + headers='sys/param.h sys/mount.h sys/vfs.h', + define='BSD_STYLE_STATVFS', + msg='Checking for *bsd style statfs with statfs.f_iosize', + execute=True, + local_include=False) + +conf.CHECK_CODE('struct statvfs buf; buf.f_fsid = 0', + define='HAVE_FSID_INT', + msg='Checking if f_fsid is an integer', + execute=False, + local_include=False, + headers='sys/statvfs.h') + +# fsusage.c assumes that statvfs has an f_frsize entry. Some weird +# systems use f_bsize. +conf.CHECK_CODE('struct statvfs buf; buf.f_frsize = 0', + define='HAVE_FRSIZE', + msg='Checking that statvfs.f_frsize works', + headers='sys/statvfs.h', + execute=False, + local_include=False) + +# Some systems use f_flag in struct statvfs while others use f_flags +conf.CHECK_CODE('struct statvfs buf; buf.f_flag = 0', + define='HAVE_STATVFS_F_FLAG', + msg='Checking whether statvfs.f_flag exists', + headers='sys/statvfs.h', + local_include=False, + execute=False) + +conf.CHECK_CODE('struct statvfs buf; buf.f_flags = 0', + define='HAVE_STATVFS_F_FLAGS', + msg='Checking whether statvfs.f_flags exists', + headers='sys/statvfs.h', + local_include=False, + execute=False) + +# Check for mallinfo2() first and fallback to mallinfo() if not found +body = '''mi.arena + mi.ordblks + mi.smblks + mi.hblks + mi.hblkhd + + mi.usmblks + mi.fsmblks + mi.uordblks + mi.fordblks + mi.keepcost''' +if not conf.CHECK_CODE('''struct mallinfo2 mi = mallinfo2(); return %s;''' + % body, 'HAVE_MALLINFO2', + msg="Checking for mallinfo2()", + headers='malloc.h'): + conf.CHECK_CODE('''struct mallinfo mi = mallinfo(); return %s;''' + % body, 'HAVE_MALLINFO', + msg="Checking for mallinfo()", + headers='malloc.h') + +# +# systemd removed the libsystemd-daemon and libsystemd-journal libraries. In newer +# versions it is only libsystemd. As waf pkg-config handling does not provide +# targets which could be used as a dependency based on the package name we need +# to look for them on our own. This enabled one of the library targets based on +# which version we detect. +# +conf.SET_TARGET_TYPE('systemd-daemon', 'EMPTY') +conf.SET_TARGET_TYPE('systemd-journal', 'EMPTY') +conf.SET_TARGET_TYPE('systemd', 'EMPTY') + +if Options.options.enable_systemd != False: + r_daemon = conf.CHECK_CFG(package='libsystemd-daemon', args='--cflags --libs', + msg='Checking for libsystemd-daemon') + r_journal = conf.CHECK_CFG(package='libsystemd-journal', args='--cflags --libs', + msg='Checking for libsystemd-journal') + if r_daemon is None and r_journal is None: + conf.CHECK_CFG(package='libsystemd', args='--cflags --libs', + msg='Checking for libsystemd') + conf.CHECK_LIB('systemd', shlib=True) + else: + conf.CHECK_LIB('systemd-daemon', shlib=True) + conf.CHECK_LIB('systemd-journal', shlib=True) + +conf.SET_TARGET_TYPE('lttng-ust', 'EMPTY') + +if Options.options.enable_lttng != False: + conf.CHECK_CFG(package='lttng-ust', args='--cflags --libs', + msg='Checking for lttng-ust', uselib_store="LTTNG-UST") + conf.CHECK_HEADERS('lttng/tracef.h', lib='lttng-st') + conf.CHECK_LIB('lttng-ust', shlib=True) + +if (conf.CONFIG_SET('HAVE_LTTNG_TRACEF_H') and + conf.CONFIG_SET('HAVE_LTTNG_UST')): + conf.DEFINE('HAVE_LTTNG_TRACEF', '1') + conf.env['HAVE_LTTNG_TRACEF'] = True + +if Options.options.gpfs_headers_dir: + conf.env['CPPPATH_GPFS'] = Options.options.gpfs_headers_dir + if conf.CHECK_HEADERS('gpfs.h', False, False, "gpfs"): + Logs.info('Using gpfs.h from %s' % Options.options.gpfs_headers_dir) + conf.DEFINE('HAVE_GPFS', '1') +else: + conf.env['CPPPATH_GPFS'] = "/usr/lpp/mmfs/include/" + if conf.CHECK_HEADERS('gpfs.h', False, False, "gpfs"): + Logs.info('Using gpfs.h from installed gpfs package.') + conf.DEFINE('HAVE_GPFS', '1') + else: + if sys.platform.startswith('linux'): + conf.env['CPPPATH_GPFS'] = os.path.abspath("third_party/gpfs") + if conf.CHECK_HEADERS('gpfs.h', False, False, "gpfs"): + Logs.info('Using gpfs.h from third_party directory.') + conf.DEFINE('HAVE_GPFS', '1') |