#At file:///home/bar/mysql-bzr/mysql-trunk-bugfixing.w5624v2/ based on revid:vasil.dimov@stripped-gmz6fjwqrytgees8
3447 Alexander Barkov 2010-12-20
WL#5624 Collation customization improvements
@ include/m_ctype.h
- Extending MY_UCA_MAX_CONTRACTION to 6
- Adding "with_context" indicator
- Adding logical positions
- Introducing new MY_CHARSET_LOADER type, a combination
of error message, memory management functions,
warning reporter routine and collation adding routine.
- Changing parameters to initialization functions to
use MY_CHARSET_LOADER
@ include/my_getopt.h
Moving type definition to my_sys.h, to share in charset related code.
@ include/my_global.h
Adding enum loglevel definition, to share in /strings
@ include/my_sys.h
Moving enum loglevel definition to my_global.h
@ mysql-test/r/ctype_ldml.result
@ mysql-test/std_data/Index.xml
@ mysql-test/t/ctype_ldml.test
Adding tests
@ mysys/charset.c
Adding my_charset_get_by_name() and my_collation_get_by_name() -
extended versions of get_charset_by_name() and get_get_charset_by_csname,
to return error message to the caller.
@ sql/item_strfunc.cc
Using new function mysqld_collation_get_by_name()
@ sql/mysqld.cc
More verbosity at mysqld startup - collation warnings are now displayed.
@ sql/sql_class.h
Adding new function mysqld_collation_get_by_name(),
to get collation and to report error to client on failure.
@ sql/sql_yacc.yy
Using new function mysqld_collation_get_by_name()
@ sql/sys_vars.cc
Using new function mysqld_collation_get_by_name()
@ strings/CMakeLists.txt
Adding coft_to_src to Makefile as an optional binary
(was missed during autotools to cmake transition)
@ strings/conf_to_src.c
Adding "libc" initializer to MY_CHARSET_LOADER.
Changing parameters to use MY_CHARSET_LOADER.
@ strings/ctype-bin.c
Changing parameters to use MY_CHARSET_LOADER.
@ strings/ctype-simple.c
Changing parameters to use MY_CHARSET_LOADER.
@ strings/ctype-uca.c
Adding support for WL#5624 features.
Collation customization parser now works in look-ahead(1) mode.
@ strings/ctype.c
Adding new LDML tags.
modified:
include/m_ctype.h
include/my_getopt.h
include/my_global.h
include/my_sys.h
mysql-test/r/ctype_ldml.result
mysql-test/std_data/Index.xml
mysql-test/t/ctype_ldml.test
mysys/charset.c
sql/item_strfunc.cc
sql/mysqld.cc
sql/sql_class.h
sql/sql_yacc.yy
strings/CMakeLists.txt
strings/conf_to_src.c
strings/ctype-bin.c
strings/ctype-simple.c
strings/ctype-uca.c
strings/ctype.c
=== modified file 'include/m_ctype.h'
--- a/include/m_ctype.h 2010-12-14 13:26:35 +0000
+++ b/include/m_ctype.h 2010-12-20 08:30:44 +0000
@@ -75,13 +75,14 @@ extern MY_UNICASE_INFO my_unicase_defaul
extern MY_UNICASE_INFO my_unicase_turkish;
extern MY_UNICASE_INFO my_unicase_unicode520;
-#define MY_UCA_MAX_CONTRACTION 4
+#define MY_UCA_MAX_CONTRACTION 6
#define MY_UCA_MAX_WEIGHT_SIZE 8
typedef struct my_contraction_t
{
my_wc_t ch[MY_UCA_MAX_CONTRACTION]; /* Character sequence */
uint16 weight[MY_UCA_MAX_WEIGHT_SIZE];/* Its weight string, 0-terminated */
+ my_bool with_context;
} MY_CONTRACTION;
@@ -101,6 +102,21 @@ typedef struct uca_info_st
uchar *lengths;
uint16 **weights;
MY_CONTRACTIONS contractions;
+
+ /* Logical positions */
+ my_wc_t first_non_ignorable;
+ my_wc_t last_non_ignorable;
+ my_wc_t first_primary_ignorable;
+ my_wc_t last_primary_ignorable;
+ my_wc_t first_secondary_ignorable;
+ my_wc_t last_secondary_ignorable;
+ my_wc_t first_tertiary_ignorable;
+ my_wc_t last_tertiary_ignorable;
+ my_wc_t first_trailing;
+ my_wc_t last_trailing;
+ my_wc_t first_variable;
+ my_wc_t last_variable;
+
} MY_UCA_INFO;
@@ -227,12 +243,22 @@ enum my_lex_states
struct charset_info_st;
+typedef struct my_charset_loader_st
+{
+ char error[128];
+ void *(*once_alloc)(size_t);
+ void *(*malloc)(size_t);
+ void *(*realloc)(void *, size_t);
+ void (*free)(void *);
+ void (*reporter)(enum loglevel, const char *format, ...);
+ int (*add_collation)(struct charset_info_st *cs);
+} MY_CHARSET_LOADER;
+
/* See strings/CHARSET_INFO.txt for information about this structure */
typedef struct my_collation_handler_st
{
- my_bool (*init)(struct charset_info_st *, void *(*alloc)(size_t),
- char *error, size_t errsize);
+ my_bool (*init)(struct charset_info_st *, MY_CHARSET_LOADER *);
/* Collation routines */
int (*strnncoll)(struct charset_info_st *,
const uchar *, size_t, const uchar *, size_t, my_bool);
@@ -284,8 +310,7 @@ typedef size_t (*my_charset_conv_case)(s
/* See strings/CHARSET_INFO.txt about information on this structure */
typedef struct my_charset_handler_st
{
- my_bool (*init)(struct charset_info_st *, void *(*alloc)(size_t),
- char *error, size_t errsize);
+ my_bool (*init)(struct charset_info_st *, MY_CHARSET_LOADER *loader);
/* Multibyte routines */
uint (*ismbchar)(struct charset_info_st *, const char *, const char *);
uint (*mbcharlen)(struct charset_info_st *, uint c);
@@ -632,9 +657,8 @@ int my_wildcmp_unicode(CHARSET_INFO *cs,
int escape, int w_one, int w_many,
MY_UNICASE_INFO *weights);
-extern my_bool my_parse_charset_xml(const char *bug, size_t len,
- int (*add)(CHARSET_INFO *cs),
- char *error, size_t errsize);
+extern my_bool my_parse_charset_xml(MY_CHARSET_LOADER *loader,
+ const char *buf, size_t buflen);
extern char *my_strchr(CHARSET_INFO *cs, const char *str, const char *end,
pchar c);
extern size_t my_strcspn(CHARSET_INFO *cs, const char *str, const char *end,
=== modified file 'include/my_getopt.h'
--- a/include/my_getopt.h 2010-10-25 12:30:07 +0000
+++ b/include/my_getopt.h 2010-12-20 08:30:44 +0000
@@ -86,7 +86,6 @@ struct my_option
typedef my_bool (*my_get_one_option)(int, const struct my_option *, char *);
-typedef void (*my_error_reporter)(enum loglevel level, const char *format, ...);
/**
Used to retrieve a reference to the object (variable) that holds the value
for the given option. For example, if var_type is GET_UINT, the function
=== modified file 'include/my_global.h'
--- a/include/my_global.h 2010-12-02 08:58:07 +0000
+++ b/include/my_global.h 2010-12-20 08:30:44 +0000
@@ -1507,4 +1507,12 @@ static inline double rint(double x)
#endif /* EMBEDDED_LIBRARY */
+
+enum loglevel {
+ ERROR_LEVEL= 0,
+ WARNING_LEVEL= 1,
+ INFORMATION_LEVEL= 2
+};
+
+
#endif /* my_global_h */
=== modified file 'include/my_sys.h'
--- a/include/my_sys.h 2010-12-07 07:53:39 +0000
+++ b/include/my_sys.h 2010-12-20 08:30:44 +0000
@@ -262,12 +262,6 @@ extern const char *my_defaults_file;
extern my_bool timed_mutexes;
-enum loglevel {
- ERROR_LEVEL,
- WARNING_LEVEL,
- INFORMATION_LEVEL
-};
-
enum cache_type
{
TYPE_NOT_SET= 0, READ_CACHE, WRITE_CACHE,
@@ -497,6 +491,10 @@ typedef struct st_io_cache /* Used when
typedef int (*qsort2_cmp)(const void *, const void *, const void *);
+typedef void (*my_error_reporter)(enum loglevel level, const char *format, ...);
+
+extern my_error_reporter my_charset_error_reporter;
+
/* defines for mf_iocache */
/* Test if buffer is inited */
@@ -912,15 +910,20 @@ int my_getpagesize(void);
int my_msync(int, void *, size_t, int);
/* character sets */
+extern void my_charset_loader_init_mysys(MY_CHARSET_LOADER *loader);
extern uint get_charset_number(const char *cs_name, uint cs_flags);
extern uint get_collation_number(const char *name);
extern const char *get_charset_name(uint cs_number);
extern CHARSET_INFO *get_charset(uint cs_number, myf flags);
extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags);
+extern CHARSET_INFO *my_collation_get_by_name(MY_CHARSET_LOADER *loader,
+ const char *name, myf flags);
extern CHARSET_INFO *get_charset_by_csname(const char *cs_name,
uint cs_flags, myf my_flags);
-
+extern CHARSET_INFO *my_charset_get_by_name(MY_CHARSET_LOADER *loader,
+ const char *name,
+ uint cs_flags, myf my_flags);
extern my_bool resolve_charset(const char *cs_name,
CHARSET_INFO *default_cs,
CHARSET_INFO **cs);
=== modified file 'mysql-test/r/ctype_ldml.result'
--- a/mysql-test/r/ctype_ldml.result 2010-06-25 12:00:49 +0000
+++ b/mysql-test/r/ctype_ldml.result 2010-12-20 08:30:44 +0000
@@ -457,10 +457,17 @@ COLLATION_NAME CHARACTER_SET_NAME ID IS_
utf8mb4_test_ci utf8mb4 326 8
utf16_test_ci utf16 327 8
utf8mb4_test_400_ci utf8mb4 328 8
+utf8_bengali_standard_ci utf8 336 8
+utf8_bengali_traditional_ci utf8 337 8
utf8_phone_ci utf8 352 8
utf8_test_ci utf8 353 8
+utf8_5624_1 utf8 354 8
+utf8_5624_2 utf8 355 8
+utf8_5624_3 utf8 356 8
+utf8_5624_4 utf8 357 8
ucs2_test_ci ucs2 358 8
ucs2_vn_ci ucs2 359 8
+ucs2_5624_1 ucs2 360 8
utf32_test_ci utf32 391 8
utf8_maxuserid_ci utf8 2047 8
show collation like '%test%';
@@ -514,3 +521,537 @@ E2B080 E2B080
SELECT hex(@a:=convert(_utf32 0x2C30 using utf8mb4) collate utf8mb4_test_400_ci), hex(upper(@a));
hex(@a:=convert(_utf32 0x2C30 using utf8mb4) collate utf8mb4_test_400_ci) hex(upper(@a))
E2B0B0 E2B0B0
+#
+# WL#5624 Collation customization improvements
+#
+SET NAMES utf8 COLLATE utf8_5624_1;
+CREATE TABLE t1 AS SELECT REPEAT(' ', 16) AS a LIMIT 0;
+INSERT INTO t1 VALUES ('012345'),('001234'),('000123'),('000012'),('000001');
+INSERT INTO t1 VALUES ('12345'),('01234'),('00123'),('00012'),('00001');
+INSERT INTO t1 VALUES ('1234'),('0123'),('0012'),('0001');
+INSERT INTO t1 VALUES ('123'),('012'),('001');
+INSERT INTO t1 VALUES ('12'),('01');
+INSERT INTO t1 VALUES ('1'),('9');
+INSERT INTO t1 VALUES ('ГАИ'),('ГИБДД');
+INSERT INTO t1 VALUES ('a'),('b'),('c'),('d'),('e');
+INSERT INTO t1 VALUES ('cz'),('Ċ'),('ċ');
+INSERT INTO t1 VALUES ('f'),('fz'),('g'),('Ġ'),('ġ');
+INSERT INTO t1 VALUES ('h'),('hz'),('GĦ'),('Għ'),('gĦ'),('għ');
+INSERT INTO t1 VALUES ('i'),('iz'),('Ħ'),('ħ');
+INSERT INTO t1 VALUES ('y'),('yz'),('z'),('Ż'),('ż');
+INSERT INTO t1 VALUES ('ā'),('Ā'),('á'),('Á'),('à'),('À');
+INSERT INTO t1 VALUES ('ē'),('é'),('ě'),('ê'),('Ē'),('É'),('Ě'),('Ê');
+INSERT INTO t1 VALUES ('a'),('~'),('!'),('@'),('#'),('$'),('%'),('^');
+INSERT INTO t1 VALUES ('('),(')'),('-'),('+'),('|'),('='),(':'),(';');
+INSERT INTO t1 VALUES ('"'),('\''),('?');
+INSERT INTO t1 VALUES ('ch'),('k'),('cs'),('ccs'),('cscs');
+INSERT INTO t1 VALUES ('aa-'),('ab-'),('ac-'),('ad-'),('ae-'),('af-'),('az-');
+INSERT INTO t1 VALUES ('lp-fni'),('lp-lni');
+INSERT INTO t1 VALUES ('lp-fpi'),('lp-lpi');
+INSERT INTO t1 VALUES ('lp-fsi'),('lp-lsi');
+INSERT INTO t1 VALUES ('lp-fti'),('lp-lti');
+INSERT INTO t1 VALUES ('lp-ft'),('lp-lt');
+INSERT INTO t1 VALUES ('lp-fv'),('lp-lv');
+INSERT INTO t1 VALUES ('lb-fni'),('lb-lni');
+INSERT INTO t1 VALUES ('lb-fv'),('lb-lv');
+INSERT INTO t1 VALUES (_ucs2 0x3106),(_ucs2 0x3110), (_ucs2 0x3111), (_ucs2 0x3112);
+INSERT INTO t1 VALUES (_ucs2 0x32A3), (_ucs2 0x3231);
+INSERT INTO t1 VALUES (_ucs2 0x84D9), (_ucs2 0x98F5), (_ucs2 0x7CF3), (_ucs2 0x5497);
+SELECT a, HEX(WEIGHT_STRING(a)) FROM t1 ORDER BY a, LENGTH(a), BINARY a;
+a HEX(WEIGHT_STRING(a))
+lp-ft 0001
+lp-lt 0001
+lp-fpi 0001
+lp-fsi 0001
+lp-fti 0001
+lp-lpi 0001
+lp-lsi 0001
+lp-lti 0001
+lb-fv 0200233E
+lb-fni 0200233E
+lp-fv 0202
+lp-fni 0202
+- 0221
+= 042D
+| 0430
+lb-lv 0DD9233E
+lp-lv 0DDB
+1 0E2A
+01 0E2A
+001 0E2A
+0001 0E2A
+00001 0E2A
+000001 0E2A
+12 0E2A0E2B
+012 0E2A0E2B
+0012 0E2A0E2B
+00012 0E2A0E2B
+000012 0E2A0E2B
+123 0E2A0E2B0E2C
+0123 0E2A0E2B0E2C
+00123 0E2A0E2B0E2C
+000123 0E2A0E2B0E2C
+1234 0E2A0E2B0E2C0E2D
+01234 0E2A0E2B0E2C0E2D
+001234 0E2A0E2B0E2C0E2D
+12345 0E2A0E2B0E2C0E2D0E2E
+012345 0E2A0E2B0E2C0E2D0E2E
+9 0E32
+~ 0E32233E
+! 0E32233F
+@ 0E322340
+# 0E322341
+$ 0E322342
+% 0E322343
+^ 0E322344
+( 0E322346
+) 0E322347
++ 0E322348
+: 0E322349
+; 0E32234A
+" 0E32234B
+' 0E32234C
+? 0E32234D
+a 0E33
+a 0E33
+aa- 0E330E330221
+ab- 0E330E4A0E34
+ac- 0E330E600E60
+ad- 0E330E6D0E6D
+ae- 0E330E8B0E8B
+af- 0E330EB90EB9
+az- 0E33106A0221
+b 0E4A
+À 0E4A
+Á 0E4A
+à 0E4A
+á 0E4A
+Ā 0E4A
+ā 0E4A
+c 0E60
+k 0E600EE1
+ch 0E600EE1
+cs 0E600FEA
+ccs 0E600FEA0E600FEA
+cscs 0E600FEA0E600FEA
+cz 0E60106A
+Ċ 0E6C233E
+ċ 0E6C233E
+d 0E6D
+É 0E6D
+Ê 0E6D
+é 0E6D
+ê 0E6D
+Ē 0E6D
+ē 0E6D
+Ě 0E6D
+ě 0E6D
+e 0E8B
+f 0EB9
+fz 0EB9106A
+Ġ 0EC0233E
+ġ 0EC0233E
+g 0EC1
+GĦ 0EE0233E
+Għ 0EE0233E
+gĦ 0EE0233E
+għ 0EE0233E
+h 0EE1
+hz 0EE1106A
+Ħ 0EFA233E
+ħ 0EFA233E
+i 0EFB
+iz 0EFB106A
+y 105E
+yz 105E106A
+Ż 1069233E
+ż 1069233E
+z 106A
+ГА+lp-lni 233E
+ㄆ 233F
+ㄐ 2349
+ㄑ 234A
+ㄒ 234B
+㊣ 7147
+㈱ 72D5
+蓙 753C
+飵 753D
+糳 753E
+咗 753F
+#
+# WL#5624, the same test with UCS2
+#
+ALTER TABLE t1 CONVERT TO CHARACTER SET ucs2 COLLATE ucs2_5624_1;
+SELECT a, HEX(WEIGHT_STRING(a)) FROM t1 ORDER BY a, LENGTH(a), BINARY(a);
+a HEX(WEIGHT_STRING(a))
+lp-ft 0001
+lp-lt 0001
+lp-fpi 0001
+lp-fsi 0001
+lp-fti 0001
+lp-lpi 0001
+lp-lsi 0001
+lp-lti 0001
+lb-fv 0200233E
+lb-fni 0200233E
+lp-fv 0202
+lp-fni 0202
+- 0221
+= 042D
+| 0430
+lb-lv 0DD9233E
+lp-lv 0DDB
+1 0E2A
+01 0E2A
+001 0E2A
+0001 0E2A
+00001 0E2A
+000001 0E2A
+12 0E2A0E2B
+012 0E2A0E2B
+0012 0E2A0E2B
+00012 0E2A0E2B
+000012 0E2A0E2B
+123 0E2A0E2B0E2C
+0123 0E2A0E2B0E2C
+00123 0E2A0E2B0E2C
+000123 0E2A0E2B0E2C
+1234 0E2A0E2B0E2C0E2D
+01234 0E2A0E2B0E2C0E2D
+001234 0E2A0E2B0E2C0E2D
+12345 0E2A0E2B0E2C0E2D0E2E
+012345 0E2A0E2B0E2C0E2D0E2E
+9 0E32
+~ 0E32233E
+! 0E32233F
+@ 0E322340
+# 0E322341
+$ 0E322342
+% 0E322343
+^ 0E322344
+( 0E322346
+) 0E322347
++ 0E322348
+: 0E322349
+; 0E32234A
+" 0E32234B
+' 0E32234C
+? 0E32234D
+a 0E33
+a 0E33
+aa- 0E330E330221
+ab- 0E330E4A0E34
+ac- 0E330E600E60
+ad- 0E330E6D0E6D
+ae- 0E330E8B0E8B
+af- 0E330EB90EB9
+az- 0E33106A0221
+b 0E4A
+À 0E4A
+Á 0E4A
+à 0E4A
+á 0E4A
+Ā 0E4A
+ā 0E4A
+c 0E60
+k 0E600EE1
+ch 0E600EE1
+cs 0E600FEA
+ccs 0E600FEA0E600FEA
+cscs 0E600FEA0E600FEA
+cz 0E60106A
+Ċ 0E6C233E
+ċ 0E6C233E
+d 0E6D
+É 0E6D
+Ê 0E6D
+é 0E6D
+ê 0E6D
+Ē 0E6D
+ē 0E6D
+Ě 0E6D
+ě 0E6D
+e 0E8B
+f 0EB9
+fz 0EB9106A
+Ġ 0EC0233E
+ġ 0EC0233E
+g 0EC1
+GĦ 0EE0233E
+Għ 0EE0233E
+gĦ 0EE0233E
+għ 0EE0233E
+h 0EE1
+hz 0EE1106A
+Ħ 0EFA233E
+ħ 0EFA233E
+i 0EFB
+iz 0EFB106A
+y 105E
+yz 105E106A
+Ż 1069233E
+ż 1069233E
+z 106A
+ГАИ 11341114117C
+ГИБДД 11341114117C
+lb-lni 233C233E
+lp-lni 233E
+ㄆ 233F
+ㄐ 2349
+ㄑ 234A
+ㄒ 234B
+㊣ 7147
+㈱ 72D5
+蓙 753C
+飵 753D
+ted features
+#
+SET NAMES utf8 COLLATE utf8_5624_2;
+ERROR HY000: Unknown collation: 'utf8_5624_2'
+SHOW WARNINGS;
+Level Code Message
+Error 1273 Unknown collation: 'utf8_5624_2'
+Warning 1273 Syntax error at '[strength tertiary]'
+#
+# WL#5624, reset before primary ignorable
+#
+SET NAMES utf8 COLLATE utf8_5624_3;
+ERROR HY000: Unknown collation: 'utf8_5624_3'
+SHOW WARNINGS;
+Level Code Message
+Error 1273 Unknown collation: 'utf8_5624_3'
+Warning 1273 Can't reset before a primary ignorable character U+A48C
+#
+# WL#5624, \u without hex digits is equal to {'\', 'u'}
+#
+SET NAMES utf8 COLLATE utf8_5624_4;
+CREATE TABLE t1 AS SELECT REPEAT(' ', 10) AS a LIMIT 0;
+INSERT INTO t1 VALUES ('\\'),('u'),('x'),('X');
+SELECT a, HEX(WEIGHT_STRING(a)) FROM t1 ORDER BY a, LENGTH(a), BINARY(a);
+a HEX(WEIGHT_STRING(a))
+\ 02CE
+x 02CE101F
+u 101F
+X 105A
+DROP TABLE t1;
+#
+# WL#5624, testing Bengali collations
+#
+SET NAMES utf8, collation_connection=utf8_bengali_standard_ci;
+CREATE TABLE t1 AS SELECT REPEAT (' ', 10) AS a LIMIT 0;
+INSERT INTO t1 VALUES (_ucs2 0x09FA), (_ucs2 0x09F8), (_ucs2 0x09F9), (_ucs2 0x09F2);
+INSERT INTO t1 VALUES (_ucs2 0x09DC), (_ucs2 0x09A109BC);
+INSERT INTO t1 VALUES (_ucs2 0x09A2), (_ucs2 0x09DD), (_ucs2 0x09A209BC);
+INSERT INTO t1 VALUES (_ucs2 0x09A3);
+SELECT HEX(WEIGHT_STRING(a)), HEX(CONVERT(a USING ucs2)), HEX(a)
+FROM t1 ORDER BY a, BINARY a;
+HEX(WEIGHT_STRING(a)) HEX(CONVERT(a USING ucs2)) HEX(a)
+0350 09FA E0A7BA
+0351 09F8 E0A7B8
+0352 09F9 E0A7B9
+0353 09F2 E0A7B2
+0374 09A109BC E0A6A1E0A6BC
+0374 09DC E0A79C
+0375 09A2 E0A6A2
+0376 09A209BC E0A6A2E0A6BC
+0376 09DD E0A79D
+0377 09A3 E0A6A3
+DROP TABLE t1;
+SET NAMES utf8, collation_connection=utf8_bengali_traditional_ci;
+CREATE TABLE t1 AS SELECT REPEAT (' ', 10) AS a LIMIT 0;
+INSERT INTO t1 VALUES
+(_ucs2 0x0985),(_ucs2 0x0986),(_ucs2 0x0987),(_ucs2 0x0988),
+(_ucs2 0x0989),(_ucs2 0x098A),(_ucs2 0x098B),(_ucs2 0x09E0),
+(_ucs2 0x098C),(_ucs2 0x09E1),(_ucs2 0x098F),(_ucs2 0x0990),
+(_ucs2 0x0993);
+INSERT INTO t1 VALUES
+(_ucs2 0x0994),(_ucs2 0x0982),(_ucs2 0x0983),(_ucs2 0x0981),
+(_ucs2 0x099509CD), (_ucs2 0x099609CD), (_ucs2 0x099709CD), (_ucs2 0x099809CD),
+(_ucs2 0x099909CD), (_ucs2 0x099A09CD), (_ucs2 0x099B09CD), (_ucs2 0x099C09CD),
+(_ucs2 0x099D09CD), (_ucs2 0x099E09CD), (_ucs2 0x099F09CD), (_ucs2 0x09A009CD),
+(_ucs2 0x09A109CD), (_ucs2 0x09A209CD), (_ucs2 0x09A309CD),
+(_ucs2 0x09CE), (_ucs2 0x09A409CD200D), (_ucs2 0x09A409CD),
+(_ucs2 0x09A509CD),(_ucs2 0x09A609CD),
+(_ucs2 0x09A709CD), (_ucs2 0x09A809CD), (_ucs2 0x09AA09CD), (_ucs2 0x09AB09CD),
+(_ucs2 0x09AC09CD), (_ucs2 0x09AD09CD), (_ucs2 0x09AE09CD), (_ucs2 0x09AF09CD),
+(_ucs2 0x09B009CD), (_ucs2 0x09F009CD), (_ucs2 0x09B209CD), (_ucs2 0x09F109CD),
+(_ucs2 0x09B609CD), (_ucs2 0x09B709CD), (_ucs2 0x09B809CD), (_ucs2 0x09B909CD);
+INSERT INTO t1 VALUES
+(_ucs2 0x099509CD0985),(_ucs2 0x0995),
+(_ucs2 0x099509CD0986),(_ucs2 0x099509BE),
+(_ucs2 0x099509CD0987),(_ucs2 0x099509BF),
+(_ucs2 0x099509CD0988),(_ucs2 0x099509C0),
+(_ucs2 0x099509CD0989),(_ucs2 0x099509C1),
+(_ucs2 0x099509CD098A),(_ucs2 0x099509C2),
+(_ucs2 0x099509CD098B),(_ucs2 0x099509C3),
+(_ucs2 0x099509CD09E0),(_ucs2 0x099509C4),
+(_ucs2 0x099509CD098C),(_ucs2 0x099509E2),
+(_ucs2 0x099509CD09E1),(_ucs2 0x099509E3),
+(_ucs2 0x099509CD098F),(_ucs2 0x099509C7),
+(_ucs2 0x099509CD0990),(_ucs2 0x099509C8),
+(_ucs2 0x099509CD0993),(_ucs2 0x099509CB),
+(_ucs2 0x099509CD0994),(_ucs2 0x099509CC);
+SELECT HEX(WEIGHT_STRING(a)), HEX(CONVERT(a USING ucs2)), HEX(a)
+FROM t1 ORDER BY a, BINARY(a);
+HEX(WEIGHT_STRING(a)) HEX(CONVERT(a USING ucs2)) HEX(a)
+15A2 0985 E0A685
+15A3 0986 E0A686
+15A4 0987 E0A687
+15A5 0988 E0A688
+15A6 0989 E0A689
+15A7 098A E0A68A
+15A8 098B E0A68B
+15A9 09E0 E0A7A0
+15AA 098C E0A68C
+15AB 09E1 E0A7A1
+15AC 098F E0A68F
+15AD 0990 E0A690
+15AE 0993 E0A693
+15AF 0994 E0A694
+15B0 0982 E0A682
+15B1 0983 E0A683
+15B2 0981 E0A681
+15B3 099509CD E0A695E0A78D
+15B315A2 0995 E0A695
+15B315A2 099509CD0985 E0A695E0A78DE0A685
+15B315A3 099509BE E0A695E0A6BE
+15B315A3 099509CD0986 E0A695E0A78DE0A686
+15B315A4 099509BF E0A695E0A6BF
+15B315A4 099509CD0987 E0A695E0A78DE0A687
+15B315A5 099509C0 E0A695E0A780
+15B315A5 099509CD0988 E0A695E0A78DE0A688
+15B315A6 099509C1 E0A695E0A781
+15B315A6 099509CD0989 E0A695E0A78DE0A689
+15B315A7 099509C2 E0A695E0A782
+15B315A7 099509CD098A E0A695E0A78DE0A68A
+15B315A8 099509C3 E0A695E0A783
+15B315A8 099509CD098B E0A695E0A78DE0A68B
+15B315A9 099509C4 E0A695E0A784
+15B315A9 099509CD09E0 E0A695E0A78DE0A7A0
+15B315AA 099509CD098C E0A695E0A78DE0A68C
+15B315AA 099509E2 E0A695E0A7A2
+15B315AB 099509CD09E1 E0A695E0A78DE0A7A1
+15B315AB 099509E3 E0A695E0A7A3
+15B315AC 099509C7 E0A695E0A787
+15B315AC 099509CD098F E0A695E0A78DE0A68F
+15B315AD 099509C8 E0A695E0A788
+15B315AD 099509CD0990 E0A695E0A78DE0A690
+15B315AE 099509CB E0A695E0A78B
+15B315AE 099509CD0993 E0A695E0A78DE0A693
+15B315AF 099509CC E0A695E0A78C
+15B315AF 099509CD0994 E0A695E0A78DE0A694
+15B4 099609CD E0A696E0A78D
+15B5 099709CD E0A697E0A78D
+15B6 099809CD E0A698E0A78D
+15B7 099909CD E0A699E0A78D
+15B8 099A09CD E0A69AE0A78D
+15B9 099B09CD E0A69BE0A78D
+15BA 099C09CD E0A69CE0A78D
+15BB 099D09CD E0A69DE0A78D
+15BC 099E09CD E0A69EE0A78D
+15BD 099F09CD E0A69FE0A78D
+15BE 09A009CD E0A6A0E0A78D
+15BF 09A109CD E0A6A1E0A78D
+15C0 09A209CD E0A6A2E0A78D
+15C1 09A309CD E0A6A3E0A78D
+15C2 09A409CD E0A6A4E0A78D
+15C2 09A409CD200D E0A6A4E0A78DE2808D
+15C2 09CE E0A78E
+15C3 09A509CD E0A6A5E0A78D
+15C4 09A609CD E0A6A6E0A78D
+15C5 09A709CD E0A6A7E0A78D
+15C6 09A809CD E0A6A8E0A78D
+15C7 09AA09CD E0A6AAE0A78D
+15C8 09AB09CD E0A6ABE0A78D
+15C9 09AC09CD E0A6ACE0A78D
+15CA 09AD09CD E0A6ADE0A78D
+15CB 09AE09CD E0A6AEE0A78D
+15CC 09AF09CD E0A6AFE0A78D
+15CD 09B009CD E0A6B0E0A78D
+15CE 09F009CD E0A7B0E0A78D
+15CF 09B209CD E0A6B2E0A78D
+15D0 09F109CD E0A7B1E0A78D
+15D1 09B609CD E0A6B6E0A78D
+15D2 09B709CD E0A6B7E0A78D
+15D3 09B809CD E0A6B8E0A78D
+15D4 09B909CD E0A6B9E0A78D
+SELECT HEX(WEIGHT_STRING(a)) as wa,
+GROUP_CONCAT(HEX(CONVERT(a USING ucs2)) ORDER BY LENGTH(a), BINARY a)
+FROM t1 GROUP BY a ORDER BY a;
+wa GROUP_CONCAT(HEX(CONVERT(a USING ucs2)) ORDER BY LENGTH(a), BINARY a)
+15A2 0985
+15A3 0986
+15A4 0987
+15A5 0988
+15A6 0989
+15A7 098A
+15A8 098B
+15A9 09E0
+15AA 098C
+15AB 09E1
+15AC 098F
+15AD 0990
+15AE 0993
+15AF 0994
+15B0 0982
+15B1 0983
+15B2 0981
+15B3 099509CD
+15B315A2 0995,099509CD0985
+15B315A3 099509BE,099509CD0986
+15B315A4 099509BF,099509CD0987
+15B315A5 099509C0,099509CD0988
+15B315A6 099509C1,099509CD0989
+15B315A7 099509C2,099509CD098A
+15B315A8 099509C3,099509CD098B
+15B315A9 099509C4,099509CD09E0
+15B315AA 099509E2,099509CD098C
+15B315AB 099509E3,099509CD09E1
+15B315AC 099509C7,099509CD098F
+15B315AD 099509C8,099509CD0990
+15B315AE 099509CB,099509CD0993
+15B315AF 099509CC,099509CD0994
+15B4 099609CD
+15B5 099709CD
+15B6 099809CD
+15B7 099909CD
+15B8 099A09CD
+15B9 099B09CD
+15BA 099C09CD
+15BB 099D09CD
+15BC 099E09CD
+15BD 099F09CD
+15BE 09A009CD
+15BF 09A109CD
+15C0 09A209CD
+15C1 09A309CD
+15C2 09CE,09A409CD,09A409CD200D
+15C3 09A509CD
+15C4 09A609CD
+15C5 09A709CD
+15C6 09A809CD
+15C7 09AA09CD
+15C8 09AB09CD
+15C9 09AC09CD
+15CA 09AD09CD
+15CB 09AE09CD
+15CC 09AF09CD
+15CD 09B009CD
+15CE 09F009CD
+15CF 09B209CD
+15D0 09F109CD
+15D1 09B609CD
+15D2 09B709CD
+15D3 09B809CD
+15D4 09B909CD
+DROP TABLE t1;
+#
+# End of WL#5624
+#
=== modified file 'mysql-test/std_data/Index.xml'
--- a/mysql-test/std_data/Index.xml 2010-06-25 12:00:49 +0000
+++ b/mysql-test/std_data/Index.xml 2010-12-20 08:30:44 +0000
@@ -18,6 +18,93 @@
</rules>
</collation>
+ <collation name="utf8_5624_1" id="354">
+ <rules>
+ <!-- long contractions and expansions -->
+ <reset>12345</reset><q>012345</q><q>12345</q>
+
> <reset>1234</reset><q>001234</q><q>01234</q>
+ <reset>123</reset><q>000123</q><q>00123</q><q>0123</q>
+ <reset>12</reset><q>000012</q><q>00012</q><q>0012</q><q>012</q>
+
> <reset>1</reset><q>000001</q><q>00001</q><q>0001</q><q>001</q><q>01</q>
+ <!-- some non-latin contractions and expansions -->
+ <reset>ГАИ</reset><i>ГИБДД</i>
+
+ <!-- reset before: Maltese -->
+ <reset before="primary">d</reset><p>Ċ</p><t>ċ</t>
+ <reset before="primary">g</reset><p>Ġ</p><t>ġ</t>
+ <reset before="primary">h</reset><p>GĦ</p><t>G">i</reset><p>Ħ</p><t>ħ</t>
+ <reset before="primary">z</reset><p>Ż</p><t>ż</t>
+ <!-- higher levels -->
+ <reset before="secondary">b</reset><s>ā</s><t>Ā</t>
+ <reset before="tertiary">b</reset><t>á</t><t>Á</t>
+ <reset
> before="quaternary">b</reset><q>à</q><q>À</q>
+
+ <!-- abbreviated syntax: put some punctuation immediately before a -->
+ <reset before="primary">a</reset><pc>~!@#$%^*()+:;"'?</pc>
+ <reset>d</reset><sc>ēé</sc>
+ <reset>d</reset><tc>ĒÉ</tc>
+
> <reset>d</reset><qc>ěê</qc>
+ <reset>d</reset><ic>ĚÊ</ic>
+
+ <!-- normal expansion syntax -->
+ <reset>c</reset><x><s>k</s><extend>h</extend></x>
+
> <reset>cs</reset><x><t>ccs</t><extend>cs</extend></x>
+
+ <!-- previous context -->
+ <reset>a</reset><x><context>b</context><p>-</p></x>
+
> <reset>c</reset><x><context>c</context><s>-</s></x>
+
> <reset>d</reset><x><context>d</context><t>-</t></x>
+ <reset>e</reset><x><context>e</context><q>-</q></x>
+
> <reset>f</reset><x><context>f</context><i>-</i></x>
+
+ <!-- logical reset positions -->
+ <reset><first_non_ignorable/></reset><p>lp-fni</p>
+ <reset><last_non_ignorable/></reset><p>lp-lni</p>
+ <reset><first_primary_ignorable/></reset><p>lp-fpi</p>
+ <reset><last_primary_ignorable/></reset><p>lp-lpi</p>
+ <reset><first_secondary_ignorable/></reset><p>lp-fsi</p>
+ <reset><last_secondary_ignorable/></reset><p>lp-lsi</p>
+ <reset><first_tertiary_ignorable/></reset><p>lp-fti</p>
+ <reset><last_tertiary_ignorable/></reset><p>lp-lti</p>
+ <reset><first_trailing/></reset><p>lp-ft</p>
+ <reset><last_trailing/></reset><p>lp-lt</p>
+ <reset><first_variable/></reset><p>lp-fv</p>
+
> <reset><last_variable/></reset><p>lp-lv</p>
+
+ <!-- logical positions and reset before -->
+ <reset before="primary"><first_non_ignorable/></reset><p>lb-fni</p>
+ <reset before="primary"><last_non_ignorable/></reset><p>lb-lni</p>
+ <reset before="primary"><first_variable/></reset><p>lb-fv</p>
+ <reset before="primary"><last_variable/></reset><p>lb-lv</p>
+
+ <!-- long tailoring: pinyin order from CLDR's zh.xml -->
+ <reset><last_non_ignorable/></reset>
+ <pc>ㄅㄆㄇㄈㄉㄊㄋㄌcollation>
+
+ <!-- some unsupported tags -->
+ <collation name="utf8_5624_2" id="355">
+ <settings strength="tertiary"/>
+ <rules>
+ </rules>
+ </collation>
+
+ <!-- reset before primary ignorable -->
+ <collation name="utf8_5624_3" id="356">
+ <rules>
+ <reset before="primary"><first_secondary_ignorable/></reset><p>lb-fsi</p>
+ </rules>
+ </collation>
+
+ <!-- \u without hex digits -->
+ <collation name="utf8_5624_4" id="357">
+ <rules>
+ <reset>\u</reset><i>x</i>
+ </rules>
+ </collation>
+
<collation name="utf8_hugeid_ci" id="2047000000">
<rules>
<reset>a</reset>
@@ -133,6 +220,74 @@
</collation>
+ <collation name="ucs2_5624_1" id="360">
+ <rules>
+ <!-- long contractions and expansions -->
+ <reset>12345</reset><q>012345</q><q>12345</q>
+
> <reset>1234</reset><q>001234</q><q>01234</q>
+ <reset>123</reset><q>000123</q><q>00123</q><q>0123</q>
+ <reset>12</reset><q>000012</q><q>00012</q><q>0012</q><q>012</q>
+ <reset>1</reset><q>000001</q><q>00001</q><q>0001</q><q>001</q><q>01</q>
+ <!-- some non-latin contractions and expansions -->
+ <reset>ГАИ</reset><i>ГИБД<reset before="primary">d</reset><p>Ċ</p><t>ċ</t>
+ <reset before="primary">g</reset><p>Ġ</p><t>ġ</t>
+ <reset before="primary">h</reset><p>GĦ</p><t>Għ</t><t>gĦ</t><t>għ</t>
+ <reset before="primary">i</reset><p>Ħ</p><t>ħ</t>
+ <reset
> before="primary">z</reset><p>Ż</p><t>ż</t>
+ <!-- higher levels -->
+ <reset before="secondary">b</reset><s>><t>á</t><t>Á</t>
+ <reset
> before="quaternary">b</reset><q>à</q><q>À</q>
+
+ <!-- abbreviated syntax: put some punctuation immediately before a -->
+ <reset before="primary">a</reset><pc>~!@#$%^*()+:;"'?</pc>
+ <reset>d</reset><sc>ēé</sc>
+ <reset>d</reset><tc>ĒÉ</tc>
+
> <reset>d</reset><qc> <!-- normal expansion syntax -->
+ <reset>c</reset><x><s>k</s><extend>h</extend></x>
+
> <reset>cs</reset><x><t>ccs</t><extend>cs</extend></x>
+
+
> <!-- previous context -->
+ <reset>a</reset><x><context>b</context><p>-</p></x>
+
> <reset>c</reset><x><context>c</context><s>-</s></x>
+
> <reset>d</reset><x><context>d</context><t>-</t></x>
+
> <reset>e</reset><x><context>e</context><q>-</q></x>
+
> <reset>f</reset><x><context>f</context><i>-</i></x>
+
+ <!-- logical reset positions -->
+ <reset><first_non_ignorable/></reset><p>lp-fni</p>
+ <reset><last_non_ignorable/></reset><p>lp-lni</p>
+ <reset><first_primary_ignorable/></reset><p>lp-fpi</p>
+ <reset><last_primary_ignorable/></reset><p>lp-lpi</p>
+ <reset><first_secondary_ignorable/></reset><p>lp-fsi</p>
+ <reset><last_secondary_ignorable/></reset><p>lp-lsi</p>
+ <reset><first_tertiary_ignorable/></reset><p>lp-fti</p>
+ <reset><last_tertiary_ignorable/></reset><p>lp-lti</p>
+
> <reset><first_trailing/></reset><p>lp-ft</p>
+ <reset><last_trailing/></reset><p>lp-lt</p>
+ <reset><first_variable/></reset><p>lp-fv</p>
+ <reset><last_variable/></reset><p>lp-lv</p>
+
+ <!-- logical positions and reset before -->
+ <reset before="primary"><first_non_ignorable/></reset><p>lb-fni</p>
+ <reset before="primary"><last_non_ignorable/></reset><p>lb-lni</p>
+ <reset before="primary"><first_variable/></reset><p>lb-fv</p>
+ <reset before="primary"><last_variable/></reset><p>lb-lv</p>
+
+ <!-- long tailoring: pinyin order from CLDR's zh.xml -->
+ <reset><last_non_ignorable/></reset>
+ <pc>ㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦㄧㄨㄩ吖阿啊锕錒嗄厑哎哀唉埃挨欸溾锿鎄啀捱皑凒嵦溰嘊敱敳皚癌毐昹娾嗳矮蔼躷噯濭﨟藹譪霭靄艾伌爱砹硋隘嗌塧嫒愛碍叆暧瑷僾壒嬡懓薆懝曖璦賹餲鴱皧瞹馤礙譺鑀鱫靉安侒峖桉氨庵菴谙媕萻葊痷腤鹌蓭誝鞌鞍盦諳闇馣鮟盫鵪韽鶕玵啽雸垵俺唵埯铵隌揞晻罯銨犴岸按洝荌案胺豻堓婩暗貋儑錌黯肮骯岇昂昻枊盎醠凹坳垇柪軪爊敖厫隞嗷嗸嶅廒滶獒獓遨摮熬璈蔜磝翱聱螯翶謷翺鳌鏖鰲鷔鼇抝芺拗袄媪镺媼襖岙扷岰傲奡奥嫯慠骜奧澚墺嶴澳懊擙謸鏊驁八仈巴叭扒朳玐吧夿岜芭疤哵捌笆粑紦羓蚆釟豝鲃魞叐犮抜坺妭拔茇炦癹胈釛菝詙跋軷颰魃墢鼥把钯鈀靶坝弝爸垻罢跁鲅罷鮁覇矲霸壩灞欛挀掰白百佰柏栢捭竡粨絔摆擺襬呗庍拝败拜唄敗猈稗粺鞁薭贁韛兡瓸扳攽朌班般颁斑搬斒頒瘢螁螌褩癍辬阪坂岅昄板版瓪钣粄舨鈑蝂魬闆办半伴扮姅怑拌绊秚湴絆鉡靽辦瓣邦峀垹帮捠梆浜邫幇幚縍幫鞤绑綁榜牓膀玤蚌傍棒棓硥谤塝徬稖蒡蜯磅镑艕謗鎊勹包佨孢苞胞剝笣煲龅蕔褒闁襃齙窇嫑雹宝怉饱保鸨珤堡堢媬葆寚飹飽褓駂鳵緥鴇賲藵寳寶靌勽报抱豹趵铇菢袌報鉋鲍靤骲暴髱虣鮑儤曓爆忁鑤萡陂卑杯盃桮悲揹碑鹎藣鵯喺北鉳贝狈貝邶备昁牬苝背钡俻倍悖狽被偝偹梖珼鄁備僃惫焙琲軰辈愂碚禙蓓蛽犕褙誖骳輩鋇憊糒鞴鐾奔泍贲倴渀逩犇賁锛錛本苯奙畚楍坌捹桳笨撪獖輽伻祊奟崩绷絣閍嵭痭嘣綳繃甭埄埲菶琣琫鞛泵迸逬跰塴甏镚蹦鏰皀屄偪毴逼豍螕鲾鎞鵖鰏柲荸鼻嬶匕比夶朼佊吡妣沘疕彼柀秕俾笔粃粊舭啚筆鄙聛貏匂币必毕闭佖坒庇诐邲妼怭枈畀畁苾哔毖珌疪胇荜陛毙狴畢袐铋婢庳敝梐萆萞閇閉堛弻弼愊愎湢皕禆筚詖貱赑嗶彃楅滗滭煏痹痺腷蓖蓽蜌裨跸辟鉍閟飶幣弊熚獙碧稫箅箆綼蔽鄪馝幤潷獘罼襅駜髲壁嬖廦篦篳縪薜觱避鮅斃濞臂蹕鞞髀奰璧鄨饆繴襞襣鏎鞸韠躃躄魓贔鐴驆鷝鷩鼊边砭笾猵编萹煸牑甂箯編蝙獱邉鍽鳊邊鞭鯾鯿籩炞贬扁窆匾貶惼碥稨褊糄鴘藊卞弁忭抃汳汴苄釆峅拚便变変昪覍徧揙缏遍閞辡緶艑頨辧辨辩辪辫辮辯變灬杓彪标飑骉髟淲猋脿墂幖滮蔈颮骠標熛膘麃瘭镖飙飚儦颷瀌藨謤爂臕贆鏢穮镳飆飇飈飊驃鑣驫表婊裱諘褾錶檦俵摽鳔鰾憋鳖鱉鼈虌龞別别咇莂蛂徶襒蟞蹩瘪癟彆汃邠砏宾彬傧斌椕滨缤槟瑸豩賓賔镔儐濒濱濵虨豳璸瀕霦繽蠙鑌顮氞摈殡膑髩擯鬂殯臏髌鬓髕鬢冫仌氷冰兵栟掤梹鋲檳丙邴陃怲抦秉苪昞昺柄炳饼眪窉蛃棅禀鈵鉼鞆餅餠燷并並併幷垪庰倂栤病竝偋傡寎摒誁鮩靐癶拨波癷玻剥盋砵袚袯钵饽啵紴缽脖菠袰碆鉢僠嶓撥播餑磻蹳驋鱍仢伯孛犻驳帛泊狛瓝苩侼勃柭胉郣亳挬浡瓟秡钹铂桲淿舶博渤湐葧鹁愽搏猼鈸鉑馎鲌僰煿牔箔膊艊馛駁踣鋍镈壆薄馞駮鮊襏豰嚗懪礡簙鎛餺鵓犦髆髉欂襮礴鑮蚾跛箥簸孹擘檗糪譒蘗蔔峬庯逋钸晡鈽誧餔轐醭卜卟补哺捕補鳪獛鵏鸔不布佈吥步咘怖歨歩钚勏埗悑捗荹部埠瓿鈈廍蔀踄郶篰餢簿嚓擦攃礤礸遪囃偲猜才材财財戝裁纔采倸埰婇寀彩採睬跴綵踩菜棌蔡縩乲参參叄飡骖叅喰湌傪嬠餐驂残蚕惭殘慚蝅慙蠶蠺惨朁慘噆憯穇黪黲灿粲儏澯薒燦璨謲爘仓仺伧沧苍鸧倉舱傖凔嵢滄獊蒼濸艙螥罉鶬匨蔵藏欌鑶賶撡操糙曺曹嘈嶆漕蓸槽褿艚螬鏪艹艸草愺懆騲肏鄵襙鼜冊册侧厕恻拺测荝敇畟側厠笧粣萗廁惻測策萴筞筴蓛墄箣憡簎嵾膥岑梣涔笒噌层層嶒竲驓蹭硛硳岾猠乽叉扠扱芆杈肞臿挿訍偛嗏插揷馇銟锸艖疀鍤鎈餷秅垞查査茬茶嵖搽猹靫槎詧察碴褨檫衩蹅镲鑔奼汊岔侘诧剎姹差紁詫拆钗釵犲侪柴祡豺喍儕茝虿勑袃瘥蠆囆辿觇梴掺搀覘裧摻鋓幨襜攙婵谗孱棎湹禅馋嬋煘缠僝獑蝉蝊誗鋋儃廛潹潺緾磛禪毚鄽镡瀍蟬儳劖繵蟾酁嚵壥巉瀺欃纏纒躔镵艬讒鑱饞产刬旵丳浐剗谄產産铲阐蒇剷嵼摌滻幝蕆諂閳燀簅冁繟醦譂鏟闡囅灛讇忏硟摲懴颤懺羼韂顫伥昌倀娼淐猖菖阊晿椙琩裮锠錩閶鲳鯧鼚长仧兏肠苌長镸尝偿常徜瓺萇甞腸嘗塲嫦瑺膓鋿償嚐蟐鲿鏛鱨厂场昶惝場敞僘厰廠氅鋹怅玚畅倡鬯唱悵瑒暢畼誯韔抄弨怊欩钞訬焯超鈔繛牊晁巢巣朝鄛鼌漅嘲樔潮窲罺轈鼂謿吵炒眧煼麨巐仦仯耖觘车伡車俥砗唓莗硨蛼扯偖撦奲屮彻坼迠烢烲聅掣硩頙徹撤澈勶瞮爡抻郴棽琛嗔綝瞋諃賝謓尘臣忱沉辰陈迧茞宸烥莀莐陳敐晨訦谌軙愖揨鈂煁蔯塵樄瘎霃螴諶薼麎曟鷐趻硶碜墋夦磣踸贂闯衬疢称龀趁趂榇稱齓齔儭嚫谶櫬襯讖阷泟虰柽爯棦浾偁蛏铛牚琤赪憆摚靗撐撑緽橕瞠赬頳檉竀穪蟶鏳鏿饓鐺丞成朾呈承枨诚郕乗城娍宬峸洆荿乘埕挰珹脀掁珵窚脭铖堘惩棖椉程筬絾裎塍塖溗碀誠畻酲鋮憕澂澄橙檙鯎瀓懲騬侱徎悜逞骋庱睈騁秤吃妛杘侙哧彨胵蚩鸱瓻眵笞粚喫訵嗤媸摛痴絺噄瞝誺螭鴟鵄癡魑齝攡麶彲黐弛池驰坘迟岻泜茌持竾荎俿歭匙淔耛蚳赿筂貾遅趍遟馳墀漦踟遲篪謘尺叺呎肔侈卶齿垑拸胣恥耻蚇袳豉欼歯袲裭鉹褫齒彳叱斥灻赤饬抶迣勅恜炽翄翅敕烾痓啻湁飭傺痸腟跮鉓雴憏翤遫銐慗瘛翨熾懘糦趩饎鶒鷘充冲忡沖茺浺珫翀舂嘃摏徸憃憧衝罿艟蹖虫崇崈隀漴褈緟蝩蟲爞宠埫寵铳揰銃抽紬搊瘳篘犨犫仇俦帱栦惆绸菗椆畴絒愁皗稠筹裯詶酧酬綢踌儔雔嬦幬懤薵燽雠疇籌躊醻讎讐丑丒吜杽侴偢瞅醜矁魗臭臰遚殠出岀初摴樗貙齣刍除芻厨滁蒢豠锄榋耡蒭蜍趎鉏雏犓蕏廚篨鋤橱懨幮櫉蟵躇雛櫥蹰鶵躕杵础椘储楮禇楚褚濋儲檚璴礎齭齼亍処处竌怵拀绌豖欪竐俶敊埱珿絀處傗琡鄐搐滀触踀閦儊嘼諔憷橻斶歜臅黜觸矗搋膗揣啜嘬踹巛川氚穿剶瑏传舡舩船圌猭遄傳椽歂暷篅輲舛荈喘僢汌串玔钏釧賗鶨刅囱疮窓窗牎摐牕瘡窻床牀噇傸漺磢闖创怆刱剏剙創愴吹炊龡垂倕埀桘陲捶菙搥棰腄槌锤箠錘鎚顀旾杶春萅堾媋暙椿槆瑃箺蝽橁輴櫄鰆鶞纯陙唇浱純莼淳脣湻犉滣蒓鹑漘蓴醇醕錞鯙鶉偆萶惷睶賰踳蠢踔戳辶辵娕娖惙涰绰逴腏辍酫綽趠輟龊擉磭歠嚽齪鑡齱呲玼疵趀偨縒骴词珁垐柌祠茈茨堲瓷詞辝慈甆辞鈶磁雌鹚糍辤飺餈嬨濨薋鴜礠蠀辭鶿鷀此佌泚皉跐朿次佽刺刾庛茦栨莿絘蛓赐螆賜嗭从匆囪苁忩枞茐怱從悤棇焧葱楤漗聡蓯蔥骢暰樅樬熜瑽璁緫聦聪瞛篵聰蟌繱鏦騘驄丛従婃孮徖悰淙琮慒漎潀潈潨誴賨賩樷藂叢灇欉爜憁謥凑湊楱腠辏輳粗觕麁麄麤徂殂促猝媨酢瘄蔟誎趗噈憱踧醋瘯簇縬蹙鼀蹴蹵顣汆撺镩蹿攛躥鑹攅櫕巑欑穳窜熶篡殩篹簒竄爨崔催凗缞墔嶉慛摧榱槯獕磪縗鏙乼漼璀趡皠伜忰疩倅紣翆脃脆啐啛悴淬萃毳焠瘁粹綷翠膵膬竁襊顇臎邨村皴墫澊竴存拵踆刌忖寸吋籿搓瑳遳磋撮蹉醝髊虘嵯嵳痤睉矬蒫蔖鹾鹺齹脞剉剒厝夎挫莝莡措逪棤锉蓌错銼錯咑哒耷畣搭嗒褡噠墶撘鎝达迏迖呾妲怛沓垯炟羍荅荙剳匒笪逹溚答詚達跶瘩靼薘鞑燵繨蟽鎉躂鐽韃龖龘打大亣眔橽呆呔獃懛歹傣代汏轪侢垈岱帒甙绐迨带待怠柋殆玳贷帯軑埭帶紿蚮袋軚逮貸軩瑇廗叇曃緿鮘鴏戴艜黛簤蹛瀻霴襶黱靆丹妉单担単眈砃耼耽郸聃躭酖單媅殚瘅匰箪褝鄲頕儋勯擔殫癉襌簞聸伔刐狚玬瓭胆衴疸紞掸亶馾撣澸黕膽旦但帎沊泹诞柦疍訑啖啗弹惮淡萏蛋啿氮腅蜑觛窞誕僤噉髧嘾彈憚憺澹禫餤駳鴠甔癚嚪贉霮饏当珰裆筜當儅噹澢璫襠簹艡蟷挡党谠擋譡黨攩灙欓讜氹凼圵宕砀垱荡档菪婸瓽逿雼潒碭瞊蕩趤壋檔璗盪礑簜蘯闣刀刂叨屶忉朷氘舠釖鱽魛捯导岛陦倒宲島捣祷禂搗隝嶋嶌槝導隯壔嶹擣蹈禱到悼焘盗菿椡盜道稲翢噵稻衜檤衟燾翿軇瓙纛恴得淂悳惪锝嘚徳德鍀的揼扥扽灯登豋噔嬁燈璒竳簦艠覴蹬等戥邓僜凳鄧隥墱嶝瞪磴镫櫈鐙仾低奃彽袛啲埞羝隄堤趆嘀滴镝磾鍉鞮鏑廸狄肑籴苖迪唙敌涤荻梑笛觌靮滌髢嫡蔋蔐頔魡敵篴嚁藡豴糴覿鸐氐厎诋邸阺呧坻底弤抵拞柢牴砥掋菧觝詆軧聜骶鯳地弚坔弟旳杕玓怟枤苐俤帝埊娣递逓偙啇梊焍眱祶第菂谛釱媂棣睇缔蒂僀禘腣遞鉪馰墑墬摕碲蔕蝃遰慸甋締嶳諦踶螮嗲敁掂傎厧嵮滇槙瘨颠蹎巅顚顛癫巓巔攧癲齻典奌点婰敟椣碘蒧蕇踮點电佃甸阽坫店垫扂玷钿唸婝惦淀奠琔殿蜔鈿電墊壂橂澱靛磹癜簟驔刁叼汈刟虭凋奝弴彫蛁琱貂碉鳭殦瞗雕鮉鲷簓鼦鯛鵰扚屌弔伄吊钓窎訋调掉釣铞鈟竨蓧銱雿調瘹窵鋽藋鑃爹跌褺苵迭垤峌恎挕绖胅瓞眣耊啑戜谍喋堞幉惵揲畳絰耋臷詄趃叠殜牃牒镻嵽碟蜨褋艓蝶疂諜蹀鲽曡曢鰈疉疊氎哋昳眰嚸丁仃叮帄玎甼疔盯钉耵酊釘靪奵顶頂鼎嵿鼑薡鐤订忊饤矴定訂飣啶萣椗腚碇锭碠聢聣錠磸顁丟丢铥颩銩东冬咚岽東苳昸氡倲鸫埬娻崬涷笗菄氭蝀鮗鼕鯟鶇鶫董墥嬞懂箽蕫諌动冻侗垌姛峒峝恫挏栋洞胨迵凍戙胴動崠硐棟湩腖働詷駧霘吺剅唗都兜兠蔸橷篼艔斗乧阧抖枓钭陡蚪鈄豆郖浢荳逗饾鬥梪毭脰酘痘閗窦鬦鋀餖斣闘竇鬪鬬鬭剢阇嘟督醏闍毒涜读渎椟牍犊裻読蝳獨錖凟匵嬻瀆櫝殰牘犢瓄皾騳黩讀豄贕韣髑鑟韇韥黷讟厾独笃堵帾琽赌睹覩賭篤芏妒杜肚妬度荰秺渡靯镀螙殬鍍蠧蠹耑偳媏端褍鍴短段断塅缎葮椴煅瑖腶碫锻緞毈簖鍛斷躖籪叾垖堆塠嵟痽磓頧鴭鐜队对兊兌兑対祋怼陮隊碓綐對憝濧薱镦懟瀩譈鐓譵吨惇敦蜳墩墪壿撴獤噸撉橔犜礅蹲蹾驐盹趸躉伅囤庉沌炖盾砘逇钝顿遁鈍腞頓碷遯憞潡燉踲多夛咄哆茤剟崜敠毲裰嚉仛夺铎剫掇敓敚喥敪痥鈬奪凙踱鮵鐸朵朶哚垛挅挆埵缍椯趓躱躲綞亸軃鬌嚲刴剁沲陊陏饳垜尮柮桗堕舵惰跢跥跺飿墮嶞憜墯鵽妸妿娿屙讹吪囮迗俄娥峨峩涐莪珴訛皒睋鈋锇鹅蛾磀誐鋨頟额魤額鵝鵞譌枙砈婀惡噁騀鵈厄歺屵戹岋阨呃扼苊阸呝砐轭咢咹垩姶峉匎恶砨蚅饿偔卾堊悪硆谔軛鄂阏堮崿愕湂萼豟軶遌遏廅搤搹琧腭詻僫蝁锷鹗蕚遻頞颚餓噩擜覨諤閼餩鍔鳄歞顎櫮鰐鶚讍鑩齶鱷奀恩蒽煾峎摁鞥仒乻旕儿而児侕兒陑峏洏耏荋栭胹唲袻鸸粫聏輀鲕隭髵鮞鴯轜尒尓尔耳迩洱饵栮毦珥铒爾鉺餌駬薾邇趰二弍弐佴刵咡贰貮衈貳誀樲发沷発發彂髪橃醗乏伐姂垡疺罚茷阀栰傠筏瞂罰閥罸藅佱法砝鍅灋珐琺髮帆忛犿番勫噃墦嬏幡憣旙旛翻藩轓颿籓飜鱕凡凢凣匥杋柉矾籵钒舤烦舧笲釩棥煩緐樊蕃橎燔璠膰薠繁襎繙羳蹯瀿礬蘩鐇蠜鷭反仮払辺返氾犯奿汎泛饭范贩畈訉軓梵盕笵販軬飯飰滼嬎範嬔瀪匚方邡坊芳枋牥钫淓蚄堏趽鈁錺鴋防妨房肪埅鲂魴仿访彷纺昉昘瓬眆倣旊紡舫訪髣鶭放飞妃非飛啡婓婔渄绯菲扉猆靟裶緋蜚霏鲱餥馡騑騛鯡飝肥淝暃腓蜰蟦朏胐匪诽奜悱斐棐榧翡蕜誹篚吠废杮沸狒肺昲费俷剕厞疿屝萉廃費痱镄廢蕟曊癈鼣濷櫠鐨靅分吩帉纷芬昐氛玢竕衯紛翂棻訜躮酚鈖雰朆餴饙坆坟妢岎汾枌炃肦梤羒蚠蚡棼焚蒶馚隫墳幩蕡魵鳻橨燌燓豮鼢羵鼖豶轒鐼馩黂粉瞓黺份坋弅奋忿秎偾愤粪僨憤奮膹糞鲼瀵鱝丰风仹凨凬妦沣沨凮枫封疯盽砜風峯峰偑桻烽琒崶渢溄猦葑锋楓犎蜂瘋碸僼篈鄷鋒檒豐鎽鏠酆寷灃蘴靊飌麷冯夆捀浲逢堸馮摓綘缝艂縫讽覂唪諷凤奉甮俸湗焨煈赗鳯鳳鴌賵蘕瓰覅仏佛坲梻垺紑缶否妚缹缻雬鴀夫伕邞呋妋姇枎玞肤怤柎砆胕荂衭娐尃荴旉紨趺酜麸稃跗鈇筟綒鄜孵豧敷膚鳺麩糐麬麱懯乀巿弗伏凫甶冹刜孚扶芙芣芾咈岪帗彿怫拂服泭绂绋苻茀俘垘枹柫氟洑炥玸畉畐祓罘茯郛韨鳬哹栿浮畗砩莩蚨匐桴涪烰琈符笰紱紼翇艴菔虙袱幅棴絥罦葍福粰綍艀蜉辐鉘鉜颫鳧榑稪箙複韍幞澓蝠髴鴔諨踾輻鮄癁襆鮲黻襥鵩鶝呒抚甫府弣拊斧俌郙俯釜釡捬脯辅椨焤盙腑滏蜅腐輔撫鬴簠黼阝父讣付妇负附咐坿竎阜驸复峊祔訃負赴蚥袝陚偩冨副婏婦蚹傅媍富復秿萯蛗覄詂赋椱缚腹鲋禣褔赙緮蕧蝜蝮賦駙縛輹鮒賻鍑鍢鳆覆馥鰒猤旮伽嘠钆尜釓嘎噶錷尕玍尬魀侅该郂陔垓姟峐荄晐赅畡祴絯隑該豥賅賌忋改絠鎅丐乢匃匄杚钙盖摡溉葢鈣戤概蓋槩槪漑瓂干甘忓芉迀攼杆玕肝坩泔苷柑竿疳酐粓亁凲尲尴筸漧鳱尶尷魐仠皯秆衦赶敢桿笴稈感澉趕橄擀簳鳡鱤旰汵盰矸绀倝凎淦紺詌骭幹榦檊赣贛灨冈罓冮刚阬岗纲肛岡牨疘矼缸钢剛罡堈掆釭棡犅堽綱罁鋼鎠崗港杠焵筻槓戆戇皋羔羙高皐髙臯滜睪槔睾膏槹橰篙糕餻櫜韟鷎鼛鷱夰杲菒稁搞缟槀槁獔稾稿镐縞藁檺藳鎬吿告勂诰郜峼祮祰锆筶暠禞誥鋯戈圪犵纥戓肐牫疙牱紇哥胳袼鸽割搁彁歌滒戨閤鴐鴚擱謌鴿鎶呄佮匌挌茖阁革敋格鬲愅臵葛蛒蛤裓隔嗝塥滆觡搿槅膈閣镉鞈韐骼諽輵鮯櫊鎘韚轕鞷騔鰪哿舸个各虼個硌铬箇鉻獦给給根跟哏亘艮茛揯搄更刯庚畊浭耕掶菮椩焿絚赓鹒緪縆羮賡羹鶊郠哽埂峺挭绠耿莄梗綆鲠骾鯁亙堩啹喼嗰工弓公厷功攻杛供糼肱宫宮恭蚣躬龚匑塨幊愩觥躳匔碽篢髸觵龏龔廾巩汞拱唝拲栱珙輁鞏共贡羾貢慐熕贑兝兣勾佝沟钩袧缑鈎溝鉤緱褠篝簼鞲韝岣狗苟枸玽耇耉笱耈蚼豿坸构诟购垢姤茩冓够夠訽媾彀搆詬遘雊構煹觏撀覯購估咕姑孤沽泒柧轱唂唃罛鸪笟菇菰蛄蓇觚軱軲辜酤毂鈲箍箛嫴篐橭鮕鴣轂鹘鶻古夃扢汩诂谷股峠牯骨罟羖逧钴傦啒淈脵蛊蛌尳愲焸硲詁馉鹄榾鈷鼓鼔嘏榖皷穀縎糓薣濲臌餶瀔盬瞽鵠蠱固怘故凅顾堌崓崮梏牿棝祻雇痼稒锢頋僱錮鲴鯝顧瓜刮苽胍鸹歄焻煱颪趏劀緺銽颳鴰騧冎叧呱剐剮啩寡卦坬诖挂掛罣絓罫褂詿乖拐枴柺箉夬叏怪恠关观官冠覌倌萖棺蒄窤関瘝癏観闗鳏關鰥觀鱞馆琯痯筦管輨舘錧館躀鳤卝毌丱贯泴悺惯掼涫貫悹祼慣摜潅遦樌盥罆雚鏆灌爟瓘矔礶鹳罐鑵鸛鱹光灮侊炗炚炛咣垙姯洸茪桄烡珖胱硄僙輄銧黆欟广広犷廣獷臩俇逛臦撗归圭妫龟规邽皈茥闺帰珪胿亀硅窐袿規媯椝瑰郌嫢摫閨鲑嬀嶲槻槼璝瞡膭鮭龜巂歸鬶騩瓌鬹櫷宄氿轨庋佹匦诡陒垝姽恑癸軌鬼庪祪匭晷湀蛫觤詭厬簋蟡刽刿攰昋柜炅攱贵桂椢筀貴溎蓕跪瞆劊劌撌槶瞶禬簂櫃襘鳜鞼鱖鱥丨衮惃绲袞辊滚蓘裷滾緄蔉磙緷輥鲧鮌鯀棍棞睔睴璭謴呙咼埚郭啯堝崞楇聒鈛锅墎瘑嘓彉濄蝈鍋彍蟈囯囶囻国圀國帼掴腘幗慖摑漍聝蔮膕虢馘果惈淉猓菓馃椁褁槨粿綶蜾裹輠餜鐹过過腂妎铪鉿丷哈咍嗨孩骸海胲烸塰酼醢亥骇害氦嗐餀駭駴嚡饚乤兯佄顸哻蚶酣頇嫨谽憨馠魽鼾邗含邯函咁肣凾虷唅圅娢浛崡晗梒涵焓寒嵅韩甝筨爳蜬澏鋡韓厈罕浫喊蔊豃鬫汉屽扞汗闬旱垾悍捍晘涆猂莟晥淊焊琀菡釬閈皔睅傼蛿颔馯撖漢蜭暵熯銲鋎憾撼翰螒頷顄駻譀雗瀚蘫鶾夯魧妔苀迒斻杭垳绗笐航蚢颃貥筕絎頏沆茠蒿嚆薅薧竓蚝毫椃嗥獆噑豪嘷獋儫曍嚎壕濠籇蠔譹好郝号昊昦秏哠恏悎浩耗晧淏傐皓滈聕號暤暭澔皜皞皡薃皥颢灏顥鰝灝兞诃呵抲欱喝訶嗬蠚禾合何劾咊和姀河郃峆曷柇狢盇籺阂饸哬敆核盉盍荷啝涸渮盒秴菏萂蚵龁惒粭訸颌楁毼詥貈貉鉌阖鲄熆閡鹖麧澕頜篕翮螛魺礉闔鞨齕覈鶡皬鑉龢佫垎贺袔隺寉焃湼賀嗃煂碋熇褐赫鹤翯壑癋燺爀鶴齃靍靎鸖靏黒黑嘿潶嬒拫痕鞎佷很狠詪恨亨哼悙涥脝姮恆恒桁烆珩胻鸻横橫衡鴴鵆蘅鑅啈堼囍乊乥叿灴轰哄訇烘軣揈渹焢硡谾薨輷嚝鍧轟仜弘妅红吰宏汯玒纮闳宖泓玜苰垬娂洪竑紅荭虹浤紘翃耾硔紭谹鸿渱竤粠葒葓鈜閎綋翝谼潂鉷鞃魟篊鋐彋蕻霐黉霟鴻黌晎嗊讧訌閧撔澋澒銾闀闂鬨齁侯矦喉帿猴葔瘊睺銗篌糇翭骺鍭餱鯸吼吽犼后郈厚垕後洉逅候鄇堠豞鲎鲘鮜鱟乎匢虍呼垀忽昒曶泘苸恗烀轷匫唿惚淴虖軤雽嘑寣滹雐幠歑膴謼囫抇弧狐瓳胡壶壷斛焀喖壺媩搰湖猢絗葫楜煳瑚嘝蔛鹕槲箶糊蝴衚魱縠螜醐頶觳鍸餬瀫鬍鰗鶘鶦鶮乕汻虎浒唬萀琥虝滸箎錿鯱互弖戶户戸冱冴芐帍护沍沪岵怙戽昈枑祜笏粐婟扈瓠綔鄠嫭嫮摢滬蔰槴熩鳸簄鍙嚛鹱護鳠韄頀鱯鸌花芲埖婲椛硴糀誮錵蘤华哗姡骅華铧滑猾嘩撶璍磆蕐螖鋘譁鏵驊鷨化划杹画话崋桦婳畫嬅畵觟話劃摦槬樺嫿澅諙諣黊繣舙蘳怀徊淮槐褢踝懐褱懷瀤櫰耲蘹坏咶壊壞蘾欢欥歓鴅懁鵍酄嚾懽獾歡貛讙驩还环郇峘洹狟荁桓萈萑堚寏絙雈綄羦貆锾阛寰澴缳還環豲鍰镮鹮糫繯轘闤鐶鬟瓛睆缓輐緩攌幻奂肒奐宦唤换浣涣烉患梙焕逭喚喛嵈愌換渙痪煥瑍豢漶瘓槵鲩擐澣瞣藧鯇鯶鰀巟肓荒衁朚塃慌皇偟凰隍黃黄喤堭媓崲徨惶揘湟葟遑楻煌瑝墴潢獚锽熿璜篁艎蝗癀磺穔諻簧蟥鍠餭鳇趪韹鐄騜鰉鱑鷬怳恍炾宺晃晄奛谎幌愰詤熀縨謊櫎皩兤滉榥曂皝鎤灰灳诙咴恢拻挥洃虺袆晖烣珲豗婎媈揮翚辉隓暉楎煇琿禈詼幑睳褘噅噕撝翬輝麾徽隳瀈鰴囘回囬佪廻廽恛洄茴迴烠蚘逥痐蛔蛕蜖鮰悔螝毇檓燬譭卉屷汇会讳泋哕浍绘芔荟诲恚恵桧烩烪贿彗晦秽喙惠湏絵缋翙阓匯彙彚會毀毁滙詯賄僡嘒瘣蔧誨圚寭慧憓暳槥潓蕙噦徻橞澮獩璤薈薉諱頮檅檜燴璯篲藱餯嚖懳瞺穢繢蟪櫘繪翽譓儶譮鏸闠孈鐬靧韢譿顪昏昬荤婚惛涽阍惽棔殙葷睧睯閽忶浑馄渾魂餛繉轋鼲诨俒倱圂掍混焝溷慁觨諢吙耠锪劐鍃豁攉騞佸活秮秳火伙邩钬鈥漷夥沎或货咟俰捇眓获閄剨掝祸貨惑旤湱禍嗀蒦嚄奯擭濩獲霍檴謋雘矆穫镬嚯瀖耯艧藿蠖嚿曤臛癨矐鑊靃夻丌讥击刉叽饥乩刏圾机玑肌芨矶鸡枅咭迹剞唧姬屐积笄飢基绩喞嵆嵇攲敧犄筓缉赍勣嗘畸稘跻鳮僟毄箕銈嘰撃槣樭畿稽緝觭賫躸齑墼憿機激璣禨積錤隮擊磯簊績羁賷鄿櫅耭雞譏韲鶏譤鐖饑癪躋鞿鷄齎羇虀鑇覉鑙齏羈鸄覊亼及伋吉岌彶忣汲级即极亟佶郆卽叝姞急狤皍笈級揤疾觙偮卙庴楖焏脨谻戢棘極殛湒集塉嫉愱楫蒺蝍趌辑槉耤膌銡嶯潗瘠箿蕀蕺踖鞊鹡橶檝濈螏輯襋蹐鍓艥籍轚鏶霵鶺鷑躤雦雧几己丮妀犱泲虮挤脊掎鱾幾戟嵴麂魢撠擠穖蟣彐彑旡计记伎纪坖妓忌技芰芶际剂季哜垍峜既洎济紀茍計剤紒继觊記偈寂寄徛悸旣梞済祭萕惎臮葪蔇兾痵継蓟裚跡際墍暨漃漈禝稩穊誋跽霁鲚暩稷諅鲫冀劑曁穄縘薊襀髻嚌檕濟繋罽覬鮆檵璾蹟鯽鵋齌廭懻癠穧糭繫蘎骥鯚瀱繼蘮鱀蘻霽鰶鰿鱭驥加夹夾宊抸佳拁泇迦枷毠浃珈埉家浹痂梜笳耞袈袷傢猳葭裌跏犌腵鉫嘉镓糘豭貑鎵麚圿扴岬郏荚郟唊恝莢戛脥铗戞蛱颊蛺跲餄鋏頬頰鴶鵊甲叚玾胛斚贾钾婽徦斝椵賈鉀榎槚瘕檟价驾架假嫁幏榢價稼駕嗧戋奸尖幵坚歼间冿戔玪肩艰姦姧兼监堅惤猏笺菅菺豜湔牋犍缄葌葏間靬搛椷椾煎瑊睷碊缣蒹豣監箋樫熞緘蕑蕳鲣鳽鹣熸篯縑鋻艱鞬餰馢麉瀐鞯鳒殱礛覸鵳瀸鰔櫼殲譼鰜鶼籛韀鰹囏虃鑯韉囝拣枧俭柬茧倹挸捡笕减剪帴梘检湕趼揀揃検減睑硷裥詃锏弿暕瑐筧简絸谫彅戩戬碱儉翦撿檢藆襇襉謇蹇瞼礆簡繭謭鬋鰎鹸瀽蠒鐗鐧鹻譾襺鹼见件見侟建饯剑洊牮荐贱俴健剣栫涧珔舰剱徤渐袸谏釼寋旔楗毽溅腱臶葥跈践閒賎鉴键僭榗槛漸劍劎墹澗箭糋諓賤趝踐踺劒劔橺薦諫鍵餞瞯瞷磵礀螹鍳擶檻濺繝瀳覵鏩聻艦轞鑑鑒鑬鑳江姜将茳浆畕豇葁摪翞僵漿螀壃彊缰薑橿殭螿鳉疅礓疆繮韁鱂讲奖桨傋蒋勥奨奬蔣槳獎耩膙講顜匞匠夅弜杢降洚绛將弶袶絳畺酱摾滰嵹犟糡醤糨醬櫤謽艽芁交郊姣娇峧浇茭茮骄胶椒焦焳蛟跤僬嘄虠鲛嬌嶕嶣憍澆膠蕉燋膲礁穚鮫鵁鹪簥蟭轇鐎驕鷦鷮櫵臫角佼侥挢狡绞饺捁晈烄笅皎矫脚铰搅湫筊絞剿勦敫湬煍腳賋僥摷暞踋鉸餃儌劋撟撹徼敽敿缴曒璬矯皦蟜鵤繳譑孂纐攪灚鱎叫呌峤挍訆珓窌轿较敎教窖滘較嘂嘦斠漖酵噍嶠潐噭嬓獥藠趭轎醮譥皭釂阶疖皆接掲痎秸菨階喈嗟堦媘嫅揭椄湝脻街煯稭鞂蝔擑癤鶛卩卪孑尐节讦刦刧劫岊昅刼劼杰疌衱诘拮洁结迼倢桀桝莭訐偼婕崨捷袺傑媫結蛣颉嵥楬楶滐睫節蜐詰鉣魝截榤碣竭蓵鲒潔羯誱踕頡幯擳嶻擮礍鍻鮚巀櫭蠞蠘蠽她姐毑媎解觧飷檞丯介吤岕庎忦戒芥屆届斺玠界畍疥砎衸诫借悈蚧徣堺楐琾蛶骱犗誡褯魪藉繲巾今斤钅兓金釒津矜砛荕衿觔埐珒紟惍琎堻琻筋嶜璡鹶黅襟仅卺巹紧堇菫僅厪谨锦嫤廑漌盡緊蓳馑槿瑾錦謹饉伒劤尽劲妗近进侭枃勁浕荩晉晋浸烬赆祲進煡缙寖搢溍禁靳墐慬瑨僸凚歏殣觐儘噤濅縉賮嚍壗嬧濜藎燼璶覲贐齽坕坙巠京泾经茎亰秔荆荊涇莖婛惊旌旍猄経菁晶稉腈睛粳經兢精聙橸鲸鵛鯨鶁鶄麖鼱驚麠井丼阱刭坓宑汫汬肼剄穽颈景儆幜憬璄憼暻燝燞璟璥頸蟼警妌净弪径迳俓浄胫倞凈弳徑痉竞逕婙婧桱梷淨竟竫脛敬痙竧靓傹靖境獍誩踁静頚靚曔镜靜瀞鏡競竸冂冋坰扃埛絅駉駫蘏冏囧泂迥侰炯逈浻烱煚窘颎綗僒煛熲澃燑燛褧顈蘔丩勼纠朻牞究糺鸠糾赳阄萛啾揂揪揫鳩摎樛鬏鬮九久乆乣奺汣杦灸玖舏韭紤酒镹韮匛旧臼咎畂疚柩柾倃桕厩救就廄匓舅僦廏廐慦殧舊鹫鯦麔匶齨鷲欍凥圧抅匊居拘泃狙苴驹倶挶捄疽痀眗砠罝陱娵婅婮崌掬梮涺椐琚腒趄跔锔裾雎艍蜛諊踘鋦駒鮈鴡鞠鞫鶋局泦侷狊桔毩淗焗菊郹椈毱湨犑輂僪粷蓻跼趜躹閰橘檋駶鵙蹫鵴巈蘜鶪鼰鼳驧咀弆沮举矩莒挙椇筥榉榘蒟龃聥舉踽擧櫸齟欅襷句巨讵姖岠怇拒洰苣邭具怚拠昛歫炬秬钜俱倨冣剧粔耟蚷袓埧埾惧据詎距焣犋跙鉅飓虡豦锯寠愳窭聚駏劇勮屦踞鮔壉懅據澽窶遽鋸屨颶瞿貗簴躆醵懼鐻爠姢娟捐涓脧裐鹃勬鋑鋗镌鎸鵑鐫蠲卷呟帣埍捲菤锩臇錈奆劵弮倦勌桊狷绢隽淃瓹眷鄄睊絭罥雋睠絹飬慻蔨餋獧羂噘撅撧屩屫亅孒孓决刔氒诀妜抉決芵泬玦玨挗珏砄绝虳觉倔捔欮蚗崛掘斍桷殌焆覐觖訣赽趹逫傕厥絕絶覚趉鈌劂勪瑴谲駃嶡嶥憰潏熦爴獗瘚蕝蕨鴂鴃噱憠橛橜镼爵臄镢蟨蟩爑譎蹶蹷鶌嚼矍覺鐍鐝灍爝觼彏戄攫玃鷢欔矡龣貜躩钁军君均汮姰袀軍钧莙蚐桾皲菌鈞碅筠皸皹覠銁銞鲪麇鍕鮶麏麕呁俊郡陖埈峻捃晙浚馂骏焌珺畯竣箘箟蜠儁寯懏餕燇濬駿鵔鵕鵘攈咔咖喀卡佧垰胩裃鉲开奒揩衉锎開鐦凯剀垲恺闿铠凱剴慨蒈塏愷楷輆暟锴鍇鎧闓颽忾炌炏欬烗勓嘅愾鎎乫刊栞勘龛堪嵁戡龕冚坎侃砍莰偘埳惂堿欿塪歁輡轁顑竷轗看衎崁墈阚瞰磡闞矙忼砊粇康嫝嵻慷漮槺穅糠躿鏮鱇扛摃亢伉匟邟囥抗犺闶炕钪鈧閌尻髛丂攷考拷洘栲烤铐犒銬鲓靠鮳鯌匼坷苛柯牁珂科胢轲疴趷钶嵙棵痾萪軻颏搕犐稞窠鈳榼薖颗樖瞌磕蝌頦醘顆髁礚壳咳殻揢翗嶱可岢炣渇嵑敤渴克刻剋勀勊客峇恪娔尅课堁氪骒缂嗑愙溘锞碦緙課錁礊騍肎肯肻垦恳啃豤貇墾錹懇掯裉褃劥吭坈坑挳硁牼硜铿硻誙銵鍞鏗巪乬唟厼怾空倥埪崆悾涳硿箜躻躼錓鵼孔恐控鞚廤抠芤眍剾彄摳瞘口劶叩扣怐敂冦宼寇釦窛筘滱蔲蔻瞉簆鷇扝刳矻郀枯哭桍堀崫圐跍窟骷鮬狜苦楛库俈绔庫秙焅袴喾絝裤瘔酷褲嚳夸姱晇舿誇侉咵垮銙挎胯跨骻蒯擓巜凷圦块快侩郐哙狯脍塊筷鲙儈墤鄶噲廥獪膾旝糩鱠宽寛寬髋鑧髖梡欵款歀窽窾匡劻诓邼匩哐恇洭筐筺誆軭抂狂狅诳軖軠誑鵟夼儣懭邝圹纩况旷岲況矿昿贶框眖砿眶絋絖貺軦鉱鋛鄺壙黋懬曠爌矌礦穬纊鑛亏刲岿悝盔窥聧窺虧闚顝巋蘬奎晆逵鄈頄馗喹揆葵骙戣暌楏楑魁睽蝰頯櫆藈鍨鍷騤夔蘷虁巙躨卼傀煃跬頍磈蹞尯匮欳喟媿愦愧溃蒉蒊馈匱嘳嬇憒潰篑聩聭蕢樻殨謉餽簣聵籄鐀饋鑎坤昆晜堃堒婫崐崑猑菎裈焜琨髠裩锟髡鹍尡潉蜫褌髨熴瑻醌錕鲲臗騉鯤鵾鶤悃捆阃壸梱祵硱稇裍壼稛綑閫閸困涃睏扩拡括挄栝桰筈萿葀蛞阔廓噋頢髺擴濶闊鞟韕懖霩鞹鬠穒垃拉柆啦翋菈搚邋旯砬揦磖喇藞嚹剌溂腊揧楋瘌蜡蝋辢辣蝲臈攋爉臘鬎櫴瓎镴鯻蠟鑞鞡来來俫倈崃徕涞莱郲婡崍庲徠梾淶猍萊逨棶琜筙铼箂錸騋鯠鶆麳唻赉睐睞赖賚濑賴頼顂癞鵣瀨瀬籁藾癩襰籟兰岚拦栏婪嵐葻阑蓝蓞谰厱澜褴儖斓篮懢燣藍襕镧闌璼襤譋幱攔瀾灆籃繿蘭斕欄礷襴囒灡籣欗讕躝襽鑭钄韊览浨揽缆榄漤罱醂壈懒覧擥嬾懶孄覽孏攬欖爦纜烂滥燗嚂壏濫爁爛爤瓓灠糷啷勆郎郞欴狼莨嫏廊桹琅蓈榔瑯硠稂锒筤艆蜋郒螂躴鋃鎯駺悢朗阆朖烺塱蓢樃誏閬朤埌崀浪蒗唥捞粩撈劳労牢狫窂哰唠崂浶勞痨铹僗嘮嶗憥朥癆磱簩蟧醪鐒顟髝耂老佬咾姥恅荖栳珯硓铑蛯銠潦橑鮱轑涝烙嗠耢酪嫪憦澇橯耮軂仂阞乐叻忇扐氻艻玏泐竻砳勒楽韷樂簕鳓鰳饹餎雷嫘缧蔂樏畾檑縲镭櫑瓃羸礧纍罍蘲鐳轠壨鑘靁虆鱩欙纝鼺厽耒诔垒塁絫傫誄磊蕌磥蕾儡壘癗藟櫐矋礨灅蠝蘽讄儽鑸鸓肋泪洡类涙淚累酹銇頛頪擂錑攂礌颣類纇蘱禷嘞脷塄棱楞碐稜踜薐冷倰堎愣睖唎刕厘剓梨狸离荲莉骊悡梸犁菞喱棃犂鹂剺漓睝筣缡艃蓠蜊嫠孷樆璃盠竰貍氂犛糎蔾褵鋫鲡黎篱縭罹錅蟍謧醨嚟藜邌釐離鯏斄鏫鯬鵹黧囄灕蘺蠡蠫孋廲劙鑗穲籬驪鱺鸝礼李里俚峛哩娌峲浬逦理裡锂粴裏豊鋰鲤澧禮鯉蟸醴鳢邐鱧欚力历厉屴立吏朸丽利励呖坜沥苈例岦戾枥沴疠苙隶俐俪栃栎疬砅茘荔赲轹郦娳悧栗栛栵涖猁珕砺砾秝莅唳婯悷琍笠粒粝蚸蛎傈凓厤棙痢蛠詈跞雳塛慄搮溧蒚蒞鉝鳨厯厲暦歴瑮綟蜧勵曆歷篥隷鴗巁檪濿癘磿隸鬁儮曞櫔爄犡禲蠇嚦壢攊櫟瀝瓅礪藶麗櫪爏瓑皪盭礫糲蠣儷癧礰酈鷅麜囇攦躒轢欐讈轣攭瓥靂鱱靋瓈俩倆嫾奁连帘怜涟莲連梿联裢亷嗹廉慩溓漣蓮匲奩熑覝劆匳噒憐磏聨聫褳鲢濂濓縺翴聮薕螊櫣燫聯臁蹥謰鎌镰簾蠊譧鬑鐮鰱籢籨敛琏脸裣摙槤璉蔹嬚斂歛臉鄻襝羷蘝蘞练娈炼恋浰殓堜媡湅萰链僆楝煉瑓潋稴練澰錬殮鍊鏈瀲鰊戀纞簗良俍凉梁涼椋辌粮粱墚綡踉樑輬糧両两兩唡啢掚脼裲緉蜽魉魎亮哴谅辆喨晾湸量煷輌諒輛鍄蹽辽疗聊僚寥嵺廖憀漻膋嘹嫽寮嶚嶛憭撩敹獠缭遼暸燎璙窷膫療竂镣鹩屪廫簝繚蟟豂賿蹘爎鐐髎飉鷯钌釕鄝蓼爒镽了尥尦炓料尞撂瞭咧毟挘埓列劣冽劽姴峢挒洌茢迾埒浖烈烮捩猎猟脟蛚裂煭睙聗趔巤颲儠鮤鴷擸獵犣躐鬛鬣鱲厸邻林临啉崊惏淋晽琳粦痳碄箖粼鄰隣嶙潾獜遴斴暽燐璘辚霖瞵磷臨繗翷麐轔壣瀶鏻鳞驎麟鱗菻亃稟僯凛凜撛廩廪懍懔澟檁檩癛癝顲吝恡悋赁焛賃蔺橉甐膦閵疄藺蹸躏躙躪轥拎伶刢灵囹坽夌姈岭岺彾泠狑苓昤朎柃玲瓴凌皊砱秢竛铃陵鸰婈崚掕棂淩琌笭紷绫羚翎聆舲菱蛉衑祾詅跉軨蓤裬鈴閝零龄綾蔆輘霊駖澪蕶錂霗魿鲮鴒鹷燯霛霝齢瀮酃鯪孁蘦齡櫺醽靈欞爧麢龗阾袊领領嶺令另呤炩溜熘刘沠畄浏流留旈琉畱硫裗媹嵧旒蒥蓅遛馏骝榴瑠飗劉瑬瘤磂镏駠鹠橊璢疁镠癅蟉駵嚠懰瀏藰鎏鎦餾麍鏐飀鐂騮飅鰡鶹驑柳栁桞珋桺绺锍綹熮罶鋶橮羀嬼六翏塯廇澑磟鹨蹓霤雡飂鬸鷚瓼甅囖咯龙屸咙泷茏昽栊珑胧眬砻竜笼聋隆湰嶐槞漋蕯癃窿篭龍嚨巃巄瀧蘢鏧霳曨朧櫳爖瓏矓礱礲襱龒籠聾蠪蠬龓豅躘鑨靇驡鸗陇垄垅拢儱隴壟壠攏竉哢梇硦衖徿贚娄偻婁喽溇蒌僂楼嘍廔慺蔞遱樓熡耧蝼瞜耬艛螻謱軁髅鞻髏嵝搂塿嶁摟漊甊篓簍陋屚漏瘘镂瘺瘻鏤露噜撸嚕擼卢庐芦垆枦泸炉栌胪轳舮鸬玈舻颅鈩鲈魲盧嚧壚廬攎瀘獹璷蘆櫨爐瓐臚矑籚纑罏艫蠦轤鑪顱髗鱸鸕黸卤虏挔捛掳鹵硵鲁虜塷滷蓾樐澛魯擄橹磠镥瀂櫓氌艣鏀艪鐪鑥圥甪陆侓坴彔录峍勎赂辂陸娽淕淥渌硉菉逯鹿椂琭祿禄僇剹勠滤盝睩碌稑賂路輅塶廘摝漉箓粶蔍戮樚熝膔膟觮趢踛辘醁潞穋蕗錄録錴璐簏螰鴼濾簶蹗轆騄鹭簬簵鏕鯥鵦鵱麓鏴騼籙觻虂鷺氇驴闾榈閭馿氀膢櫚藘曥鷜驢吕呂侣郘侶旅梠焒祣稆铝屡絽缕屢膂膐褛鋁履褸儢穞縷穭寽垏律哷虑率绿嵂氯葎綠緑慮箻勴繂櫖爈鑢孪峦挛栾鸾脔滦銮鵉圝奱孌孿巒攣曫欒灓羉臠圞灤虊鑾癴癵鸞卵乱釠亂掠略畧锊稤稥圙鋝鋢擽抡掄仑伦囵沦纶侖轮倫陯圇婨崘崙惀淪菕棆腀碖綸蜦踚輪磮錀鯩稐耣论埨溣論捋頱囉罗啰猡脶萝逻椤腡锣箩骡镙螺羅覶鏍儸覼騾玀蘿邏欏鸁籮鑼饠驘剆倮砢蓏裸躶瘰蠃臝攞曪癳泺峈洛络荦骆洜珞笿絡落摞漯犖雒駱鮥鵅濼纙鱳嘸呣妈媽嬤嬷麻痲嫲蔴犘蟆蟇马犸玛码蚂馬溤獁遤瑪碼螞鎷鷌鰢亇杩祃閁骂唛傌睰嘜榪禡罵駡礣鬕吗嗎嘛埋薶霾买荬買嘪蕒鷶劢迈佅売麦卖脉脈麥衇勱賣邁霡霢颟顢姏悗蛮慲摱馒槾樠瞒瞞鞔饅鳗鬗鬘鰻蠻屘満睌满滿螨襔蟎鏋矕曼僈谩鄤墁嫚幔慢漫獌缦蔄蔓熳澫澷镘縵蟃謾鏝蘰牤邙吂忙汒芒尨杗杧盲厖恾笀茫哤娏浝狵牻硭釯铓痝蛖鋩駹蘉莽莾茻壾漭蟒蠎匁猫貓毛矛毜毝枆牦茅旄渵軞酕堥蛑锚緢髦蝥髳錨蟊鶜冇卯夘戼峁泖茆昴铆笷蓩鉚冃皃芼冐茂冒眊贸耄袤覒媢帽貿鄚愗暓楙毷瑁瞀貌鄮蝐懋唜庅嚒濹嚰么癦呅沒没枚玫苺栂眉脄莓梅珻脢郿堳媒嵋湄湈猸睂葿楣楳煤瑂禖腜塺槑酶镅鹛鋂霉徾鎇矀攗蘪鶥攟黴毎每凂美挴浼媄嵄渼媺镁嬍燘躾鎂黣妹抺沬昧祙袂眛媚寐痗跊鬽煝睸韎魅篃蝞嚜椚门扪玣钔門閅捫菛璊穈鍆虋闷焖悶暪燜懑懣们們掹擝氓甿虻冡庬罞莔萌萠夢溕盟雺甍儚橗瞢蕄蝱鄳鄸幪懞濛獴曚朦檬氋矇礞鯍艨鹲矒靀饛顭鸏勐猛瓾蒙锰艋蜢錳懵蠓鯭鼆孟梦夣懜霥霿踎咪瞇冞弥祢迷袮猕谜蒾詸謎醚彌擟糜縻麊麋禰靡獼麛爢戂攠瓕蘼镾醾醿鸍釄米羋芈侎沵弭洣敉眫粎脒眯渳葞蝆蔝銤濔瀰孊灖冖糸汨沕宓泌觅峚祕宻秘密淧覓覔幂谧塓幎覛嘧榓滵漞熐蔤蜜鼏冪樒幦濗藌謐櫁簚羃宀芇眠婂绵媔棉綿緜臱蝒嬵檰櫋矈矊矏丏汅免沔黾俛勉眄娩偭冕勔喕愐湎缅葂腼緬鮸靣面糆麪麫麺麵喵苗媌描瞄鹋嫹鶓鱙杪眇秒淼渺缈篎緲藐邈妙庙玅竗庿廟乜吀咩哶孭灭覕搣滅蔑薎鴓幭懱瀎篾櫗蠛衊鑖鱴瓱民垊姄岷忞怋旻旼玟苠珉盿冧罠崏捪琘琝缗暋瑉痻碈鈱緍緡賯錉鴖鍲皿冺刡闵抿泯勄敃闽悯敏笢笽湣閔愍敯黽閩僶慜憫潣簢鳘蠠鰵名明鸣洺眀茗冥朙眳铭鄍嫇溟猽蓂暝榠銘鳴瞑螟覭佲姳凕慏酩命掵詺谬缪繆謬摸嚤尛谟嫫馍摹模膜麼麽摩魹橅磨糢謨謩擵饃嚩蘑譕髍魔劘饝抹懡麿末劰圽妺帓怽歾歿殁沫茉陌帞昩枺皌眜眿砞秣莈莫眽粖絈袹蛨貃嗼塻寞漠蓦貊銆靺墨嫼暯瘼瞐瞙镆魩黙縸默貘藦蟔鏌爅驀礳纆耱乮哞牟侔劺恈洠桙眸谋鉾謀瞴鍪鴾麰蟱某母毪獏墲氁亩牡姆拇峔牳畆畒胟娒畝畞砪畮鉧踇木仫目凩沐狇坶炑牧苜毣莯蚞钼募萺雮墓幕幙慔楘睦鉬慕暮樢艒霂穆鞪旀丆椧拏拿挐誽镎鎿乸哪雫内那吶妠纳肭娜衲钠納袦捺笝豽軜貀鈉嗱蒳靹魶腉熋摨孻乃奶艿氖疓妳廼迺倷釢嬭奈柰耐萘渿鼐褦螚錼囡男抩枏枬侽南柟娚畘莮难喃遖暔楠煵諵難赧揇湳萳腩蝻戁婻囔乪嚢囊蠰鬞馕欜饢擃曩攮灢儾齉孬檂呶怓挠峱硇铙猱蛲詉碙撓嶩獶蟯夒譊鐃巎獿垴恼悩脑匘脳堖惱嫐瑙腦碯闹婥淖閙鬧臑疒讷呐抐眲訥呢娞馁腇餒鮾鯘內氝焾嫩能莻嗯鈪銰啱妮尼坭怩泥籾倪屔秜郳铌埿婗淣猊蚭棿跜鈮蜺觬貎輗霓鲵鯢麑齯臡伱伲你拟抳狔苨柅掜旎晲孴鉨馜儗儞隬擬薿檷鑈屰氼迡昵胒逆匿痆眤堄惄嫟愵溺睨腻暱縌膩嬺拈年秊哖秥鲇鮎鲶鵇黏鯰涊捻淰辇撚撵碾輦簐攆蹨躎卄廿念姩埝艌娘嬢孃酿醸釀鸟茑茒袅鳥嫋裊蔦嬝褭嬲尿脲捏揑肀帇圼苶枿陧涅聂臬啮惗菍隉喦敜嗫嵲鉩踂噛摰槷踗踙镊镍嶭篞臲錜颞蹑嚙聶鎳闑孼孽櫱籋蘖囁齧巕糱糵蠥囓讘躡鑷顳钀脌囜您拰宁咛拧狞柠聍寍寕寜寧儜凝嚀嬣擰獰薴檸聹鑏鬡鸋橣矃佞侫泞甯寗澝濘妞牛牜汼忸扭沑狃纽杻炄钮紐莥鈕靵农侬哝浓脓秾農儂辳噥憹濃蕽禯膿穠襛醲欁繷弄挊挵癑齈羺譨啂槈耨獳檽鎒鐞譳奴伖孥驽笯駑伮努弩砮胬怒傉搙女钕籹釹衂恧朒衄疟虐瘧奻渜暖煖煗餪硸黁燶郍挪梛傩搻儺橠诺喏掿逽搦锘榒稬諾蹃糑鍩懦懧糥穤糯桛噢哦筽毮夞乯鞰讴欧殴瓯鸥塸歐毆熰甌膒鴎櫙藲謳鏂鷗齵吘呕偶腢嘔耦蕅藕怄沤慪漚妑皅趴舥啪葩杷爬耙掱琶筢潖帊帕怕袙拍俳徘排猅棑牌箄輫簰犤哌派湃蒎鎃磗眅畨潘攀爿柈盘跘媻幋蒰搫槃盤磐縏蹒瀊蟠蹣鎜鞶坢冸判沜泮炍叛牉盼畔袢詊溿頖鋬鵥襻鑻乓汸沗肨胮雱滂膖霶厐庞逄旁舽嫎篣螃鳑龎龐鰟蠭嗙耪覫髈炐胖抛拋脬刨咆垉庖狍炮炰爮袍匏蚫軳鞄褜麅跑奅泡疱皰砲萢麭礟礮呸怌肧柸胚衃醅阫陪陫培毰赔锫裴裵賠錇俖伂沛佩帔姵斾旆浿珮配笩蓜辔馷嶏霈轡喷噴濆歕瓫盆湓葐呠翉翸喯匉怦抨泙恲胓砰梈烹硑軯閛漰嘭駍磞芃朋挷竼倗莑堋弸彭棚椖傰塜塳搒漨硼稝蓬鹏槰樥熢憉澎輣篷膨錋韸髼蟚蟛鬅纄韼鵬騯鬔鑝捧淎皏剻掽椪碰踫浌巼闏乶喸丕伓伾批纰邳坯怶披抷炋狉狓砒悂秛秠紕铍旇翍耚豾釽鈚鈹鉟銔劈磇駓髬噼錃錍魾憵礔礕闢霹皮阰芘岯枇毞肶毗毘疲笓蚍郫陴啤埤崥蚽豼椑焷琵脾腗榌鲏罴膍蜱隦魮壀鮍篺螷貔簲羆鵧朇鼙蠯匹庀仳圮苉脴痞銢諀鴄擗噽癖嚭屁淠渒揊媲嫓睤睥潎僻澼嚊甓疈譬鷿鸊片囨偏媥犏篇翩鶣骈胼腁楄楩賆諚骿蹁駢騈覑谝貵諞骗魸騗騙剽彯漂缥飘磦旚縹翲螵犥飃飄魒瓢薸闝殍瞟篻醥皫顠票僄勡嘌嫖徱慓氕撇撆暼瞥丿苤鐅嫳姘拼礗穦馪驞玭贫貧琕嫔频頻嬪薲嚬矉颦顰品榀朩牝汖娉聘乒甹俜涄砯艵竮頩平评凭呯坪岼苹郱屏帡枰洴玶荓娦瓶屛帲淜萍蚲塀幈焩甁缾聠蓱蛢評軿鲆凴慿箳輧憑鮃檘簈蘋钋坡岥泼娝釙颇溌酦潑醱鏺婆嘙蔢鄱皤謈櫇叵尀钷笸鉕駊廹岶迫敀昢洦珀哱烞破砶粕奤蒪頗魄剖颒抔抙捊掊裒箁咅哣婄堷犃兺哛仆攴攵扑抪炇巬巭柨陠痡铺駇噗撲鋪擈鯆圤匍莆菩菐葡蒱蒲僕酺墣璞濮瞨穙镤贌纀鏷朴圃埔浦烳普圑溥暜谱潽樸氆諩檏镨譜蹼鐠舖舗瀑曝七迉沏妻恓柒倛凄栖桤缼郪娸悽戚捿桼淒萋朞期棲欺紪褄僛嘁慽榿槭漆緀慼磎諆踦諿霋蹊魌鏚鶈亓祁齐圻岐岓忯芪亝其奇斉歧祇祈肵疧竒剘斊旂耆脐蚑蚔蚚颀埼崎帺掑淇渏猉畦萁跂軝釮骐骑嵜棊棋琦琪祺蛴愭碁碕褀锜頎鬾鬿旗粸綥綦綨緕蜝蜞齊璂禥蕲踑螧錡鲯懠濝藄檱櫀簱臍騎騏鳍蘄鯕鵸鶀麒籏纃艩蠐鬐騹魕鰭玂麡乞邔企屺岂芑启呇杞玘盀唘豈起啓啔啟婍绮晵棨裿綮綺諬簯闙气讫気汔迄弃汽矵芞呮泣炁盵咠契砌荠栔氣訖唭欫夡愒棄湆湇葺碛摖暣甈碶噐憇器憩磜磧磩薺礘罊蟿掐葜拤跒酠鞐圶冾帢恰洽殎硈愘髂千仟阡圱圲奷扦汘芊迁佥岍杄汧茾欦竏臤钎拪牵粁悭蚈谸铅婜孯牽釺掔谦鈆雃僉愆签鉛骞鹐慳搴摼撁箞諐遷褰謙顅檶攐攑櫏簽鏲鵮攓騫鐱鬜鬝籤韆仱岒忴扲拑乹前荨钤歬虔钱钳乾偂掮揵軡媊鈐鉆鉗墘榩箝銭潜羬蕁橬錢黔鎆黚騝濳騚灊籖鰬凵浅肷淺嵰慊遣槏膁蜸潛谴缱繾譴鑓欠刋伣芡俔茜倩悓堑傔嵌棈椠嗛皘蒨塹歉綪蔳儙槧篏輤篟壍嬱縴呛羌戕戗斨枪玱羗猐琷跄嗴椌獇腔嗆溬蜣锖嶈戧槍牄瑲羫锵篬錆蹌镪蹡鎗鏘鏹強强墙嫱蔷樯漒蔃墻嬙廧薔檣牆謒艢蘠抢羟搶羥墏摤繈襁繦炝唴熗羻兛瓩悄硗郻鄗嵪跷鄡鄥劁敲踍锹墝碻頝骹墽幧橇燆缲磽鍫鍬繑繰趬蹺蹻鐰乔侨荍荞桥硚菬喬睄僑槗谯嘺嫶憔蕎鞒樵橋犞癄瞧礄藮譙趫鐈鞽顦巧釥愀髜俏诮陗峭帩窍殼翘誚髚僺撬撽鞘韒竅翹鞩躈切苆癿茄聺且厒妾怯匧窃倿悏挈洯惬淁笡愜蛪朅箧緁锲魥篋踥穕藒鍥鯜鐑竊籡亲侵钦衾骎菳媇嵚綅誛嶔親顉駸鮼寴庈芩芹埁珡矝秦耹菦蚙捦琴琹禽鈙雂勤嗪嫀溱靲噙擒斳鳹懄檎澿瘽螓懃蠄坅昑笉梫赺赾寑锓寝寢鋟螼吢吣抋沁唚菣揿欽搇撳瀙藽靑青氢轻倾卿郬圊埥氫淸清軽傾廎蜻輕鲭鯖鑋夝甠剠勍情殑硘晴棾氰葝暒擏樈擎檠黥苘顷请庼頃漀請檾謦庆凊掅殸碃箐靘慶磬儬濪罄櫦宆跫銎卭邛穷穹茕桏笻筇赹惸焪焭琼舼蛩蛬煢熍睘瞏窮儝憌橩璚藑瓊竆藭瓗丘丠邱坵恘秋秌寈蚯媝萩楸蓲鹙篍緧蝵穐趥鳅蟗鞦鞧蘒鰌鰍鶖鱃龝叴囚扏犰玌朹汓肍求虬泅虯俅觓訄訅酋唒浗紌莍逎逑釚梂殏毬球赇釻崷巯渞湭皳盚遒煪絿蛷裘巰觩賕璆蝤銶醔鮂鼽鯄鵭蠤鰽搝糗区曲伹佉匤岖诎阹驱坥屈岨岴抾浀祛胠袪區蛆躯筁粬蛐詘趋嶇駆憈敺誳駈麹髷魼趨麯軀麴黢驅鰸鱋佢劬斪朐朑胊菃衐鸲淭渠絇翑葋軥蕖璖磲螶鴝璩翵蟝鼩蘧匷忂灈戵欋氍籧臞癯蠷衢躣蠼鑺鸜取竘娶紶詓竬蝺龋齲厺去刞呿迲郥耝阒觑趣閴麮闃覰覷鼁覻峑恮悛圈圏棬駩騡鐉全权佺诠姾泉洤荃拳牷辁啳埢婘惓痊硂铨湶犈筌絟腃葲搼楾瑔觠詮跧輇蜷銓権踡縓醛闎鳈鬈孉巏鰁權齤蠸颧顴犭犬汱甽畎烇绻綣虇劝券巻牶椦勧韏勸炔缺蒛瘸却卻埆崅悫雀硞确舃阕塙搉皵碏阙鹊愨榷墧慤毃確趞燩闋礐闕鵲礭夋囷峮逡輑宭帬裙羣群裠亽罖囕呥肰衻袇蚦袡蚺然髥嘫髯燃繎冄冉姌苒染珃媣蒅橪穣儴勷瀼獽蘘禳瓤穰躟鬤壌嚷壤攘爙纕让懹譲讓荛饶桡蕘橈襓饒犪扰娆隢嬈擾绕遶繞惹热熱人亻仁壬忈朲忎秂芢鈓魜銋鵀忍荏栠栣荵秹棯稔綛躵刃刄认仞仭讱任屻扨纫妊杒牣纴肕轫韧饪姙紉衽恁紝訒軔梕袵絍腍葚靭靱韌飪認餁扔仍辸礽芿陾日驲囸釰鈤馹戎肜栄狨绒茙茸荣容峵毧烿媶嵘絨羢嫆嵤搈搑摉榵溶蓉榕榮熔瑢穁蝾褣镕氄縙融螎駥髶嬫嶸爃鎔瀜曧蠑冗宂傇軵穃厹禸柔粈媃揉渘葇瑈腬糅蝚蹂輮鍒鞣瓇騥鰇鶔楺煣韖肉宍嶿邚如侞帤茹桇袽铷渪筎蒘銣蕠儒鴑嚅嬬孺濡薷鴽曘燸襦繻蠕颥醹顬鱬汝肗乳辱鄏入扖込杁洳嗕媷溽缛蓐鳰褥縟擩堧撋壖阮朊软耎偄軟媆愞瑌腝嫰碝緛蝡輭瓀礝桵甤緌蕤蕊蕋橤繠蘂蘃汭芮枘蚋锐瑞蜹睿銳鋭叡壡闰润閏閠潤橍挼捼叒若偌弱鄀婼渃焫楉嵶蒻箬篛爇鰙鰯鶸仨桬撒洒訯靸潵灑卅钑飒脎萨鈒摋隡馺颯薩櫒栍毢愢揌塞毸腮嘥噻鳃顋鰓嗮赛僿賽簺虄三弎叁毵毶厁毿犙鬖壭伞傘散糁糂馓橵糝糣糤繖鏒饊俕閐桒桑槡嗓搡磉褬颡鎟顙丧喪掻慅搔溞骚缫繅臊鳋颾騒騷鰠鱢扫掃嫂埽瘙氉矂髞色洓栜涩啬渋铯雭歮琗嗇瑟歰銫澁懎擌濇濏瘷穑澀璱瀒穡繬穯轖鏼譅飋裇聓森槮襂篸僧鬙閪縇杀沙纱乷刹砂唦挱殺猀粆紗莎铩痧硰蔱裟榝樧魦鲨閷鎩鯊鯋繺傻儍繌倽唼啥帹萐喢歃煞翜箑翣閯霎筛篩簁簛晒曬山彡邖圸删刪杉杣芟姍姗衫钐埏挻狦珊舢烻痁脠軕笘釤閊跚剼搧嘇幓煽蔪潸澘曑檆縿膻鯅羴羶闪陕炶陝閃晱煔睒熌覢讪汕疝苫剡扇訕赸傓善椫銏骟僐鄯墠墡缮嬗擅敾樿膳磰謆赡繕蟮蟺譱贍鐥饍騸鳝灗鱓鱔伤殇商愓觞傷墒慯滳漡蔏殤熵螪觴謪鬺裳垧扄晌赏賞鑜丄上仩尙尚恦绱緔弰捎梢烧莦焼焽稍旓筲艄蛸輎蕱燒颵髾鮹勺芍苕柖玿萔韶少劭卲邵绍哨娋袑紹綤潲奢猞赊畲輋賒賖檨舌佘虵蛇蛥舍捨厍设社舎厙射涉涻渉設赦弽慑摂摄滠慴摵蔎蠂韘騇懾攝灄麝欇申屾扟伸身侁呻妽籶绅罙诜姺柛氠珅穼籸娠峷甡眒砷堔深紳兟椮葠裑訷罧蓡詵甧蔘燊薓駪鲹鯓鵢鯵鰺神榊鉮鰰邥弞抌沈审矤哂矧宷谂谉婶渖訠審諗頣魫曋瞫嬸瀋覾讅肾侺昚甚胂涁眘渗祳脤腎愼慎椹瘆蜃滲鋠瘮升生阩呏声斘昇枡泩苼殅牲珄竔胜陞曻陹笙湦焺甥鉎聲鍟鼪鵿渑绳縄憴澠繩譝鱦省眚偗渻圣晟晠剰盛剩勝琞貹嵊聖墭榺蕂橳賸尸失师呞虱虲诗邿鸤屍施浉狮師絁釶湤湿葹溮溼獅蒒蓍詩鉇瑡酾鳲箷蝨鳾褷鲺濕鍦鯴鰤鶳襹籭釃十饣什石辻佦时竍识实実旹飠姼峕拾炻祏蚀食埘時莳寔湜遈塒嵵溡蒔鉐實榯蝕鉽篒鲥鮖鼫識鼭鰣史矢乨豕使始驶兘宩屎笶榁鉂駛士氏礻世丗仕市示卋式忕亊叓戺事侍势呩柹视试饰冟室恀恃拭是昰枾柿眂贳适栻烒眎眡舐轼逝铈笹視釈崼弑徥揓谥貰释勢嗜弒煶睗筮觢試軾鈰鉃飾舓褆誓適奭銴噬嬕澨諟諡遾餝檡螫謚簭籂襫釋鰘齛兙瓧収收手扌守垨首艏寿受狩兽售授涭绶痩膄壽瘦綬夀獣獸鏉书殳抒纾叔杸枢陎姝柕倏倐書殊紓掓梳淑焂菽軗鄃疎疏舒摅毹毺綀输瑹跾踈樞蔬輸橾鮛儵攄瀭鵨尗秫婌孰赎塾熟璹贖暏暑黍署鼠属鼡蜀潻薥薯曙癙藷襡糬襩籔蠴鱪鸀鱰朮术戍束沭述侸咰怷树竖荗恕庶庻絉蒁術尌裋数竪腧鉥墅漱潄數澍豎樹濖錰鏣鶐鶑虪刷唰耍誜衰摔甩帅帥蟀卛闩拴閂栓涮腨双滝霜雙孀骦孇騻欆礵鷞鹴艭驦鸘爽塽慡樉縔鏯灀谁脽誰氵水氺閖帨涗涚祱稅税裞睡吮楯顺舜順蕣橓瞚瞤瞬鬊说哾說説妁烁朔铄欶硕矟嗍搠蒴嗽槊碩獡箾鎙爍鑠厶纟丝司糹私咝泀俬思恖虒鸶媤斯絲缌蛳楒禗鉰飔凘厮榹禠罳蜤銯锶嘶噝廝撕澌磃緦蕬鋖燍螄鍶蟖蟴颸騦鐁鷥鼶死巳亖四罒寺汜伺似佀兕姒泤祀価孠泗饲驷俟娰枱柶牭梩洍涘肂飤笥耜釲竢覗嗣肆貄鈻飼禩駟蕼儩騃瀃螦乺忪松枀枩娀柗倯凇梥崧庺淞菘嵩硹蜙憽檧濍鬆怂悚捒耸竦傱愯嵷慫聳駷讼宋诵送颂訟頌誦餸鎹凁捜鄋嗖廀廋搜溲獀蒐蓃馊飕摗锼艘螋醙鎪餿颼騪叜叟傁嗾瞍擞薮擻藪櫢瘶苏甦酥稣窣穌鯂蘇蘓櫯囌俗玊夙诉泝肃洬涑珟素速宿梀殐粛骕傃粟訴谡嗉塐塑嫊愫溯溸肅遡鹔僳愬榡膆蔌觫趚遬憟樎樕潥碿鋉餗潚縤橚璛簌藗謖蹜驌鱐鷫狻痠酸匴祘笇筭蒜算夊芕虽倠哸浽荽荾眭葰滖睢熣濉鞖雖绥隋随遀綏隨瓍膸瀡髄髓亗岁砕祟粋谇埣嵗脺遂歲歳煫睟碎隧嬘澻穂誶賥檖燧璲禭穗穟繀襚邃旞繐繸鐆譢鐩孙狲荪孫飧搎猻蓀飱槂蕵薞畃损笋隼筍損榫箰簨鎨鶽巺潠唆娑莏傞挲桫梭睃嗦羧蓑摍缩趖簑簔縮髿鮻所唢索琐琑惢锁嗩暛溑瑣鎍鎖鎻鎼鏁逤溹蜶他它牠祂咜趿铊塌榙溻鉈褟蹹侤塔墖獭鮙鳎獺鰨挞狧闼崉涾搨遝遢阘榻毾禢撻澾誻踏嚃錔嚺濌蹋鞜闒鞳闥譶躢襨囼孡骀珆胎駘台旲邰坮抬苔炱炲菭跆鲐箈臺颱儓鮐嬯擡薹檯籉太冭夳忲汰态肽钛泰粏舦酞鈦溙態燤坍贪怹啴痑舑貪摊滩嘽潬瘫擹攤灘癱坛昙倓谈郯婒惔弾覃榃痰锬谭墰墵憛潭談醈壇曇橝錟檀顃罈藫壜譚貚醰譠罎鷤忐坦袒钽菼毯鉭嗿憳憻暺醓璮襢叹炭埮探傝湠赕僋嘆碳舕撢歎賧汤铴湯嘡劏羰蝪薚镗蹚鏜鐋鞺鼞饧坣唐堂傏啺棠鄌塘嵣搪溏蓎隚榶漟煻瑭禟膅樘磄糃膛橖篖糖螗踼糛螳赯醣餳鎕餹闛饄鶶帑倘偒淌傥耥躺镋鎲儻戃曭爣矘钂烫摥趟燙仐夲弢涛绦掏絛詜嫍幍慆搯滔槄瑫韬飸縚縧濤謟鞱韜饕匋迯咷洮逃桃陶啕梼淘绹萄祹裪綯蜪鞀醄鞉鋾錭駣檮饀騊鼗讨套討畓忑忒特貣脦犆铽慝鋱蟘膯鼟疼痋幐腾誊漛滕邆縢螣駦謄儯藤騰籐鰧籘虅驣霯唞朰剔梯锑踢銻鷈鷉厗绨偍珶啼媞崹惿提渧稊缇罤遆鹈嗁瑅綈碮徲漽緹蕛蝭题趧蹄醍謕蹏鍗鳀鴺題鮷鵜騠鯷鶗鶙体挮躰骵軆體戻屉剃洟倜悌涕逖屜悐惕掦逷惖揥替楴裼褅歒殢髰薙嚏鬀嚔瓋鬄籊鐟趯天兲婖添酟靔黇靝田屇沺恬畋畑盷胋畠甛甜菾湉塡填搷阗碵緂磌窴鴫璳闐鷆鷏忝殄倎唺悿捵淟晪琠腆觍痶睓舔餂覥賟錪靦掭瑱睼舚旫佻庣恌挑祧聎芀条岧岹迢祒條笤蓚蓨龆樤蜩鋚鞗髫鲦螩鯈鎥齠鰷宨晀朓脁窕誂窱嬥眺粜铫絩覜趒跳頫糶怗贴萜聑貼跕铁蛈鉄僣銕鴩鐡鐢鐵驖呫帖飻餮厅庁汀艼听町耓厛烃桯烴綎鞓聴聼廰聽廳邒廷亭庭莛停婷嵉渟筳葶蜓楟榳閮霆聤蝏諪鼮圢侹娗挺涏梃烶珽脡铤艇颋艈誔鋌頲濎乭囲炵通痌嗵蓪樋熥仝同佟彤峂庝哃狪茼晍桐浵烔砼蚒眮秱铜童粡絧衕赨酮鉖僮勭鉵銅餇鲖潼獞曈朣橦氃犝膧瞳穜鮦统捅桶筒統筩綂恸痛慟憅偷偸婾媮鍮亠头投骰緰頭妵紏敨殕斢黈蘣透凸禿秃怢突唋涋捸堗湥痜葖嶀鋵鵚鼵図图凃峹庩徒悇捈涂荼途屠梌揬稌塗嵞瘏筡腯蒤鈯圖圗廜潳跿酴馟鍎駼鵌鶟鷋鷵土圡吐汢钍釷兎迌兔莵堍菟鵵湍猯煓貒团団抟剬剸團塼慱摶槫漙篿檲鏄糰鷒鷻圕疃彖湪褖推蓷藬颓隤尵頹頺頽魋穨蘈蹪俀脮腿僓蹆骽退娧煺蛻蜕褪駾吞呑旽涒啍朜焞暾黗屯忳芚饨豘豚軘飩鲀魨霕臀臋氽畽坉乇讬托扡汑饦杔侂咃拕拖沰侻挩捝莌袥託涶脫脱飥馲魠驝驮佗陀陁坨岮沱狏迱驼柁砣砤袉鸵紽堶詑跎酡碢馱槖駄踻駝駞橐鮀鴕鼧騨鼍驒鼉彵妥毤庹媠椭楕嫷撱橢鵎鰖拓柝唾萚跅毻箨蘀籜屲劸哇娃徍挖洼娲畖窊啘媧嗗蛙搲溛漥窪鼃攨瓦佤邷咓瓲砙袜聉嗢腽膃襪韈韤歪喎竵崴外顡乛弯剜婠帵塆湾睕蜿潫豌彎壪灣丸刓汍纨芄完岏忨抏玩笂紈捖顽烷琓貦頑邜宛倇唍挽晚盌莞埦婉惋晩梚涴绾脘菀晼椀琬皖畹碗綩綰輓踠鋔鍐万卍卐妧杤捥腕萬翫鋄薍錽贃鎫贎尣尩尪尫汪亡亾兦王仼彺莣蚟网忹往徃枉罔惘菵暀棢焹蛧辋網蝄誷輞瀇魍妄忘迋旺盳望朢危威烓偎逶隇隈喴媁媙愄揋揻渨煀葨葳微椳楲溦煨詴縅蝛覣嶶薇燰鳂癐巍鰃鰄囗为韦圩围帏沩违闱峗峞洈為韋桅涠唯帷惟维喡圍嵬幃湋溈爲琟違潍維蓶鄬潙潿醀濰鍏闈鮠癓覹犩霺霻厃伟伪尾纬芛苇委炜玮洧娓捤浘荱诿偉偽崣梶痏硊萎隗骩嵔廆徫愇猥葦蒍骪骫暐椲煒瑋痿腲艉韪僞碨蜲蜼鲔寪緯蔿諉踓韑頠薳儰濻鍡鮪壝韙颹瀢韡亹斖卫未位味苿畏胃叞軎尉硙菋谓喂媦渭猬煟墛蔚慰熭犚磑緭蝟衛懀濊璏罻衞謂錗餧鮇螱褽餵魏藯轊鏏霨鳚蘶饖讆躗讏躛昷塭温榅殟溫瑥辒榲瘟豱輼轀鳁鎾饂鰛鰮文彣纹芠炆砇闻紋蚉蚊珳阌鈫雯瘒聞馼魰鳼鴍螡閺閿蟁闅鼤闦闧刎吻呚忟抆呡肳紊桽脗稳穏穩问妏汶莬問渂脕揾搵絻顐璺翁嗡鹟螉鎓鶲勜奣塕嵡滃蓊暡瞈聬瓮蕹甕罋齆挝倭涡莴唩涹渦猧萵喔窝窩蜗撾蝸踒我婐婑捰仴沃肟卧臥偓捾媉幄握渥焥硪楃腛斡瞃濣瓁臒龌齷乌圬弙汙汚污邬呜杇巫屋洿诬钨烏趶剭窏釫鄔嗚誈歍誣箼螐鴮鎢鰞无毋吳吴吾呉芜郚唔娪梧洖浯茣莁珸祦鹀無禑蜈蕪璑鵐鯃鼯鷡乄五午仵伍坞妩庑忤怃迕旿武玝侮俉倵捂啎娬牾珷塢摀熓碔鹉瑦舞嫵廡憮潕錻儛橆甒鵡躌兀勿务戊阢伆屼扤岉杌芴忢物矹敄误務悞悟悮粅逜晤焐焑婺嵍痦隖靰骛奦嵨溩雾寤熃誤鹜鋈窹霚鼿霧齀蘁騖鶩夕兮忚汐西覀吸希扸卥昔析矽穸肸肹俙徆怸诶郗饻唏奚娭屖屗息悕晞氥浠牺狶莃唽悉惜桸欷淅渓烯焁焈琋硒菥赥釸傒惁晰晳焟焬犀睎稀粞翕翖舾鄎厀嵠徯溪煕皙蒠锡僖榽熄熈熙緆蜥誒豨餏嘻噏嬆嬉瘜膝餙凞樨橀歙歚熹熺熻窸羲螅螇錫燨犠瞦礂蟋谿豀豯貕繥雟鯑鵗觹譆醯鏭隵巇曦爔犧酅觽鼷蠵鸂觿鑴习郋席習袭觋媳椺蒵蓆嶍漝覡趘槢蝷薂隰檄謵鎴霫鳛飁騱騽襲鰼驨杫枲洗玺徙铣喜徚葈葸鈢屣漇蓰銑憘憙暿橲歖禧諰壐縰謑蟢蹝璽鱚矖纚躧匸卌戏屃系饩呬忥怬细郄係咥恄盻郤欯绤細釳阋塈椞舄趇隙慀滊禊綌赩隟熂犔稧戯潝潟澙蕮覤戱黖戲磶虩餼鬩嚱闟霼衋呷疨虾谺傄閕敮煆颬瞎蝦鰕匣侠狎俠峡柙炠狭陜峽烚狹珨祫硖笚翈舺陿溊硤遐搳暇瑕筪碬舝辖磍縀蕸縖赮魻轄鍜霞鎋黠騢鶷閜丅下吓圷疜夏梺厦廈睱諕嚇懗罅夓鏬仙仚屳先奾纤佡忺氙杴祆秈苮枮籼珗莶掀铦跹酰锨僊僲嘕銛鲜暹韯嬐憸薟鍁鍂繊褼韱鮮馦蹮孅廯攕譣纎鶱襳躚纖鱻伭咞闲妶弦贤咸唌挦涎胘娴娹婱絃舷蚿衔啣湺痫蛝閑鹇嫌衘甉銜嫺嫻憪撏澖誸賢諴輱醎癇癎藖鹹礥贒鑦鷳鷴鷼冼狝显险崄毨烍猃蚬険赻筅尟尠搟禒蜆跣箲藔險嶮獫獮藓鍌燹顕幰攇櫶蘚玁韅顯灦县岘苋现线臽限姭宪県陥哯垷娊娨峴晛涀莧陷現硍馅睍絤缐羡献粯羨腺僩僴綫誢撊線鋧憲橌縣錎餡豏麲瀗臔獻糮鏾霰鼸乡芗相香郷厢啌鄉鄊廂湘缃葙鄕楿薌箱緗膷襄忀骧麘欀瓖镶鱜鑲驤瓨佭详庠栙祥絴翔詳跭享亯响蚃饷晑飨想銄餉鲞嚮蠁鮝鯗響饗饟鱶向姠巷项珦象缿萫項像勨嶑曏橡襐蟓鐌鱌灱灲呺枭侾削哓枵骁宯宵庨恷消绡虓逍鸮啋婋梟焇猇萧痚痟硝硣窙翛萷销揱綃嘐歊潇箫踃嘵憢撨獢銷霄彇膮蕭魈鴞穘簘藃蟂蟏謞鴵嚣瀟簫蟰髇嚻囂櫹髐鷍蠨驍毊虈洨郩崤淆訤誵小晓暁筱筿皛曉篠謏皢孝肖効咲恔俲哮效校涍笑啸傚敩滧詨嘋嘨誟嘯歗熽斅斆些楔歇蝎蠍劦协旪邪協胁垥奊峫恊拹挟挾脅脇脋衺偕斜谐猲絜翓嗋愶携瑎綊熁膎勰撷擕緳缬蝢鞋諧燲擷鞵襭鐷攜纈讗龤写冩寫藛伳灺泄泻祄绁缷卸洩炧炨卨娎屑屓偰徢械焎禼紲亵媟屟揳渫絏絬谢僁塮榍榭褉噧屧暬緤韰嶰廨懈澥獬糏薢薤邂燮褻謝夑瀉鞢瀣爕蟹蠏齘齥齂躠屭躞忄心邤妡忻芯辛昕杺欣盺俽莘惞訢鈊锌新歆廞鋅噷噺嬜薪馨鑫馫枔鬵鐔伈潃阠伩囟孞炘信軐脪衅訫焮馸舋顖釁兴狌星垶骍惺猩煋瑆腥蛵觪箵篂興謃鮏曐觲騂皨鯹刑行邢形陉侀郉哘型洐钘陘娙硎裄铏鈃鉶銒鋞睲醒擤杏姓幸性荇倖莕婞悻涬塂緈嬹臖凶兄兇匈芎讻忷汹哅恟洶胷胸訩詾雄熊诇詗夐敻休俢修咻庥烋烌羞脩脙鸺臹貅馐樇銝髤髹鎀鮴鵂饈鏅飍苬朽綇滫糔秀岫珛绣袖琇锈溴綉璓裦褎褏銹螑繍繡鏥鏽齅戌旴疞盱欨砉胥须訏顼虗虚谞媭幁揟欻虛須楈窢頊嘘稰需魆噓墟嬃歔縃蕦蝑歘諝譃魖驉鑐鬚俆徐蒣许呴姁诩冔栩珝偦許湑暊詡鄦糈醑盨旭伵序汿侐卹沀叙恤昫洫垿欰殈烅珬畜勖勗敍敘烼绪续酗喣壻婿朂溆絮訹嗅慉煦続蓄賉槒漵潊盢瞁緒聟銊獝稸緖藇瞲藚續鱮蓿吅轩昍咺宣晅軒梋谖喧塇媗愃愋揎萱萲暄煊瑄蓒睻儇禤箮翧蝖嬛蕿諠諼鍹駽矎翾藼蘐蠉譞鰚讂玄玹痃悬旋琁蜁嫙漩暶璇檈璿懸选烜暅選癣癬怰泫昡炫绚眩袨铉琄眴衒渲絢楥楦鉉碹蔙镟鞙颴縼繏鏇贙疶蒆靴薛辥鞾穴斈乴坹学岤峃茓泶袕鸴踅學嶨澩燢觷雤鷽雪樰膤艝轌鳕鱈血吷怴泧狘疦桖烕谑趐謔瀥坃勋埙焄勛塤熏窨蔒勲勳薫駨嚑壎獯薰曛燻臐矄蘍壦爋纁醺廵寻巡旬驯杊询峋恂洵浔紃荀栒桪毥珣偱尋循揗詢馴鄩鲟噚潯攳樳燂燅燖璕襑蟳鱏鱘灥卂训讯伨汛迅侚徇狥迿逊殉訊訓訙奞巽殾遜愻賐噀蕈顨鑂丫压呀庘押鸦桠鸭孲铔椏鴉錏鴨壓鵶鐚牙伢岈芽厓枒琊笌蚜堐崕崖涯猚瑘睚衙漄齖疋厊庌哑唖啞痖雅瘂蕥劜圠亚穵襾讶亜犽迓亞玡垭娅挜砑俹氩埡婭掗訝揠氬猰聐圔稏窫齾咽恹剦烟珚胭偣崦淹焉菸阉湮腌傿煙鄢嫣漹蔫嶖樮醃閹嬮篶懕臙黫讠円延闫严妍芫言訁岩昖沿炎郔姸娫狿研莚娮盐琂硏訮閆阎嵒嵓筵綖蜒塩揅楌詽碞蔅颜虤閻厳檐顏顔嚴壛巌簷櫩麙壧孍巖巗巚欕礹鹽麣夵抁沇乵兖奄俨兗匽弇衍偃厣掩眼萒郾酓嵃愝扊揜棪渰渷琰遃隒椼硽罨裺演褗戭蝘魇噞躽縯檿黡厴甗鰋鶠黤齞龑儼黬黭顩鼴巘曮魘鼹齴黶厌妟觃牪姲彥彦砚唁宴晏艳覎验偐掞焔谚隁喭堰敥焰焱猒硯葕雁椻滟鳫厭墕暥熖酽嬊谳餍鴈燄燕諺赝鬳曕鴳酀騐験嚥嬿艶贋軅爓醶騴鷃灔贗贘觾讌醼饜驗鷰艷灎釅驠灧讞豓豔灩央咉姎抰泱殃胦眏秧鸯鉠雵鞅鍈鴦扬羊阦阳旸杨炀佯劷氜疡钖飏垟徉昜洋羏烊珜眻陽崵崸揚蛘敭暘楊煬禓瘍諹輰鍚鴹颺鐊鰑霷鸉卬仰佒坱奍岟养炴氧痒紻傟楧軮慃氱羪養駚懩攁瀁癢礢怏柍恙样羕詇様漾樣幺夭吆妖枖祅訞喓葽楆腰鴁邀爻尧尭肴垚姚峣轺倄烑珧窑傜堯揺殽谣軺嗂媱徭愮搖摇猺遙遥摿暚榣瑤瑶銚飖餆嶢嶤徺磘窯窰餚繇謠謡鎐鳐颻蘨顤鰩仸宎岆抭杳殀狕苭咬柼眑窅窈舀偠婹崾溔蓔榚鴢闄騕齩鷕穾药要袎窔筄葯詏熎覞靿獟鹞薬鼼曜燿艞藥矅曣耀纅鷂讑鑰倻椰暍噎潱蠮爷耶捓揶铘爺釾鋣鎁擨也吔亪冶埜野嘢漜壄业叶曳页邺夜抴亱枼洂頁捙晔枽烨偞掖液谒堨殗腋葉鄓墷楪業馌僷曄曅歋燁擖擛皣瞱鄴靥嶪嶫澲謁餣嚈擫曗瞸鍱擪爗礏鎑饁鵺靨驜鸈膶岃一弌辷衤伊衣医吚壱依祎咿洢猗畩郼铱壹揖欹蛜禕嫛漪稦銥嬄噫夁瑿鹥繄檹毉醫黟譩鷖黳乁仪匜圯夷冝宐杝沂诒侇宜怡沶狋衪迤饴咦姨峓弬恞柂瓵荑贻迻宧巸扅栘桋眙胰袘酏痍移萓媐椬羠蛦詒貽遗暆椸誃跠頉颐飴疑儀熪遺嶬彛彜螔頤頥寲嶷簃顊鮧彝彞謻鏔籎觺讉鸃乙已以迆钇佁攺矣苡苢庡舣蚁釔倚扆笖逘偯崺旑椅鈘鉯鳦旖輢敼螘檥礒艤蟻顗轙齮乂义亿弋刈忆艺仡匇肊议阣亦伇屹异忔芅伿佚劮呓坄役抑曵杙耴苅译邑佾呭呹妷峄怈怿易枍泆炈秇绎诣驿俋奕帟帠弈枻浂玴疫羿衵轶唈垼悒挹栧栺欭浥浳益袣谊貤陭勚埶埸悘悥殹異羛翊翌萟訲訳豙豛逸釴隿幆敡晹棭殔湙焲蛡詍跇軼鈠骮亄兿意溢獈痬竩缢義肄裔裛詣勩嫕廙榏潩瘗膉蓺蜴靾駅億撎槸毅熠熤熼瘞誼镒鹝鹢黓劓圛墿嬑嬟嶧憶懌曀殪澺燚瘱瞖穓縊艗薏螠褹寱斁曎檍歝燡燱翳翼臆貖鮨癔藙藝贀鎰镱繶繹豷霬鯣鶂鶃鶍瀷蘙譯議醳醷饐囈鐿鷁鷊懿襼驛鷧虉鷾讛齸乚囙因阥阴侌垔姻洇茵荫音骃栶殷氤陰凐秵裀铟陻隂喑堙婣愔筃絪歅溵禋蒑蔭慇瘖銦磤緸鞇諲霒駰噾濦闉霠韾冘乑吟犾苂斦垠泿圁峾烎狺珢粌荶訔唫婬寅崟崯淫訡银鈝龂滛碒鄞夤蔩訚誾銀龈噖殥璌嚚檭蟫霪齗齦鷣廴尹引吲饮蚓隐淾釿鈏飲隠靷飮朄趛檃瘾隱嶾濥螾蘟櫽癮讔印茚洕胤垽湚猌廕酳慭癊憖憗鮣懚檼应応英偀桜珱莺啨婴媖愥渶绬朠煐瑛嫈碤锳嘤撄滎甇緓缨罂蝧賏樱璎噟罃褮霙鴬鹦嬰應膺韺甖鎣鹰鶧嚶孆孾攖瀴罌蘡櫻瓔礯譻鶯鑍纓蠳鷪軈鷹鸎鸚盁迎茔盈荥荧莹萤营萦蛍営溁溋萾僌塋楹滢蓥潆熒蝇瑩蝿嬴營縈螢濙濚濴藀覮謍赢巆攍攚瀛瀠瀯蠅櫿灐籝灜贏籯矨郢浧梬颍颕颖摬影潁瘿穎頴巊廮鐛癭映暎硬媵膡鞕瀅譍哟唷喲佣拥痈邕庸傭嗈鄘雍墉嫞慵滽槦牅銿噰壅擁澭郺镛臃癕雝鏞鳙廱灉饔鱅鷛癰喁颙顒鰫永甬咏怺泳俑勇勈栐埇悀柡涌恿傛惥愑湧硧詠塎嵱彮愹蛹慂踊禜鲬踴鯒用苚砽醟优忧攸呦怮泑幽悠麀滺憂優鄾嚘懮瀀櫌纋耰尢尤由沋犹邮怞油肬怣斿柚疣峳浟秞莜莤莸逌郵铀偤蚰訧逰游猶遊鱿楢猷鈾鲉輏駀蕕蝣魷輶鮋櫾邎友有丣卣苃酉羑庮羐莠梄聈脜铕湵蒏禉蜏銪槱牖牗黝又右幼佑侑孧狖糿哊囿姷宥峟牰祐诱迶唀梎蚴亴貁釉酭誘鼬扜纡迂迃穻陓紆虶唹淤盓渝瘀箊于亐予邘伃余妤扵杅欤玗玙於盂臾衧鱼俞兪禺竽舁茰荢娛娯娱狳谀酑馀渔萸釪隃隅雩魚堣堬崳嵎嵛愉揄楰湡畬畭硢腴逾骬愚楡榆歈牏瑜艅虞觎漁睮窬舆褕歶羭蕍蝓諛雓餘魣嬩懙澞覦踰歟璵螸輿鍝礖謣髃鮽旟籅騟鯲鰅鷠鸆与伛宇屿羽雨俁俣挧禹语圄峿祤偊匬圉庾敔鄅萭萮铻傴寙斞楀瑀瘐與語窳鋙龉噳嶼貐斔麌蘌齬玉驭吁圫聿芋芌妪忬饫育郁彧昱狱秗茟俼峪栯浴砡钰预喐域堉悆惐欲淢淯袬谕逳阈喅喩喻媀寓庽御棛棜棫焴琙矞裕遇飫馭鹆愈滪煜稢罭蒮蓣誉鈺預嫗嶎戫毓獄瘉緎蜟蜮輍銉隩噊慾稶蓹薁豫遹鋊鳿澦燏燠蕷諭錥閾鴥鴧鴪儥礇禦魊鹬癒礜穥篽繘醧鵒櫲饇蘛譽轝鐭霱欎驈鬻籞鱊鷸鸒欝軉鬰鬱灪籲爩囦鸢剈冤弲悁眢鸳寃渁渆渊渕惌淵葾棩蒬蜎鹓箢鳶蜵駌鋺鴛嬽鵷灁鼘鼝元贠邧员园沅杬垣爰貟原員圆笎蚖袁厡酛圎援湲猨缘鈨鼋園圓塬媴嫄源溒猿獂蒝榞榬辕緣縁蝝蝯魭圜橼羱薗螈謜轅黿鎱櫞邍騵鶢鶰厵远盶逺遠夗肙妴苑怨院垸衏傆媛掾瑗禐愿裫褑褤噮願曰曱约約箹矱彟彠月戉刖汋岄抈礿岳枂玥恱钥悅悦蚎蚏軏钺阅捳跀跃粤越鈅粵鉞閱閲嬳樾篗嶽龠籆瀹蘥黦爚禴躍籥鸑籰龥鸙蒀煴蒕熅奫蝹赟頵馧贇云勻匀伝呍囩妘抣沄纭芸昀畇眃秐郧涢紜耘耺鄖雲愪氲溳筼蒷氳熉澐蕓鋆橒篔縜繧允阭夽抎狁玧陨荺殒喗鈗隕殞褞馻磒霣齫齳孕运枟郓恽晕鄆酝傊惲愠缊運慍暈腪韫韵熨緼蕰蕴縕薀賱醖醞餫藴韗韞蘊韻帀匝沞咂拶沯桚紥紮鉔魳臜臢杂砸韴雑磼襍雜囐雥災灾甾哉栽烖菑渽溨睵賳宰载崽載再在扗洅傤酨儎縡兂糌簪簮鐕咱偺喒昝寁撍儧攒儹攢趱趲暂暫賛赞錾鄼濽蹔酂瓉贊鏨瓒酇囋灒讃瓚禶襸讚饡牂羘赃賍臧賘贓髒贜驵駔奘弉脏塟葬銺臓臟傮遭糟蹧醩凿鑿早枣栆蚤棗璅澡璪薻藻灶皁皂唕唣造梍喿慥煰艁噪簉燥竃譟趮躁竈啫伬则択沢择泎泽责迮則唶啧帻笮舴責溭矠嘖嫧幘箦蔶樍歵諎赜擇澤皟瞔簀耫礋襗謮賾蠌齚齰鸅仄夨庂汄昃昗捑崱稄贼賊鲗蠈鰂鱡怎谮譖譛囎曽曾増鄫增憎缯橧熷璔矰磳罾繒譄鱛锃鋥甑赠贈吒迊咋抯挓柤哳偧喳揸渣溠楂劄皶箚樝觰皻皼譇齄齇扎札甴轧軋闸蚻铡煠牐閘霅鍘譗厏苲眨砟搩鲊鲝踷鮓鮺乍灹诈咤奓柵栅炸宱痄蚱詐搾摣榨膪醡夈粂捚斋斎斏摘榸齋宅翟窄鉙债砦債寨瘵沾毡旃栴粘蛅飦惉詀趈詹閚谵噡嶦澶薝邅霑氈氊瞻鹯旜譫饘鳣驙魙鱣鸇讝拃斩飐展盏崭斬琖搌盞嶃嶄榐辗颭嫸醆橏蹍輾皽黵占佔战栈桟站偡绽菚棧湛戦綻嶘輚骣戰虥虦覱轏蘸驏张弡張章傽鄣嫜彰慞漳獐粻蔁遧暲樟璋餦蟑鏱騿鱆麞仉涨涱掌漲幥礃鞝鐣丈仗扙帐杖胀账粀帳脹痮障墇嶂幛賬瘬瘴瞕佋钊妱巶招昭炤盄釗啁鉊駋窼鍣爫找沼瑵召兆诏枛垗狣赵笊肁旐棹罀詔照罩箌肇肈趙曌燳鮡櫂瞾羄蜇嫬遮厇折歽矺砓籷虴哲埑粍袩啠悊晢晣辄喆棏蛰詟谪摺輒樀磔輙銸辙蟄嚞謫謺鮿轍讁襵讋者锗赭褶鍺这柘浙這淛嗻蔗樜鹧蟅鷓贞针侦浈珍珎貞帪栕桢眞真砧祯針偵敒桭酙寊湞葴遉搸斟楨獉甄禎蒖蓁鉁靕榛槇殝瑧碪禛潧箴樼澵臻薽錱轃鍖鍼籈鱵屒诊抮枕姫弫昣胗轸畛疹眕袗紾聄萙裖覙診軫嫃缜稹駗縝縥辴鬒黰圳阵纼侲挋陣鸩振朕栚紖眹赈塦揕絼蜄敶誫賑鋴镇震鴆鎭鎮黮凧争佂姃征怔爭峥挣炡狰烝眐钲埩崝崢掙猙睁聇铮媜揁筝徰睜蒸鉦徴箏徵踭篜錚鬇癥氶抍糽拯掟塣晸愸撜整正㊣证诤郑帧政症幀証鄭諍鴊證之支卮汁芝吱巵汥枝知织肢徔栀祗秓秖胑胝衹衼倁疷祬秪脂隻梔戠椥臸搘禔綕榰蜘馶鳷謢鴲織蘵鼅禵执侄坧直姪値值聀聁釞埴執职植殖禃絷跖瓡墌摭馽嬂慹漐踯樴膱縶職蟙蹠蹢軄躑夂止只凪劧旨阯址坁帋扺汦沚纸芷抧祉茋咫恉指枳洔砋轵淽疻紙訨趾軹黹酯藢襧阤至芖志忮扻豸制厔垁帙帜治炙质郅俧峙庢庤挃柣栉洷祑陟娡徏挚晊桎狾秩致袟贽轾乿偫徝掷梽猘畤痔秲秷窒紩翐袠觗貭铚鸷傂崻彘智滞痣蛭骘寘廌搱滍稙稚筫置跱輊锧雉墆槜滯潌疐瘈製覟誌銍幟憄摯潪熫稺膣觯質踬鋕旘瀄緻隲駤鴙儨劕懥擲擿櫛穉螲懫贄櫍瓆觶騭鯯礩豑騺驇躓鷙鑕豒中伀汷刣妐彸迚忠泈炂终柊盅衳钟舯衷終鈡幒蔠锺螤鴤螽鍾鼨蹱鐘籦肿种冢喠尰塚歱煄腫瘇種踵仲众妕狆祌祍茽衶重蚛偅眾堹媑筗衆諥州舟诌侜周洀洲炿诪烐珘辀郮婤徟淍矪週鸼喌粥赒輈銂賙輖霌駲嚋盩謅鵃騆譸妯轴軸碡肘帚疛菷晭睭箒鯞纣伷呪咒宙绉冑咮昼紂胄荮晝皱酎粙葤詋甃僽皺駎噣縐骤籀籕籒驟朱劯侏诛邾洙茱株㈱珠诸猪硃袾铢絑蛛誅跦槠潴蝫銖橥諸豬駯鮢鴸瀦藸櫧櫫鼄鯺蠩竹泏竺炢笁茿烛窋逐笜舳瘃蓫燭蠋躅鱁劚孎灟斸曯欘爥蠾钃丶主宔拄砫罜陼渚煑煮詝嘱濐麈瞩屬囑矚伫佇住助纻芧苎坾杼注苧贮迬驻壴柱柷殶炷祝疰眝祩竚莇秼紵紸羜著蛀嵀筑註貯跓軴铸筯鉒飳馵墸箸翥樦鋳駐築篫霔麆鑄抓檛膼簻髽爪拽跩专叀専砖專鄟嫥瑼甎膞颛磚諯蟤顓鱄转孨転竱轉灷啭堟蒃瑑僎赚撰篆馔縳襈賺譔饌囀籑妆庄妝庒荘娤桩莊湷粧装裝樁糚丬壮壯状狀壵梉焋幢撞戅隹追骓椎锥錐騅鵻沝坠笍娷缀惴甀缒畷硾膇墜綴赘縋諈醊錣餟礈贅轛鑆宒迍肫窀谆諄衠准埻凖準綧訰稕卓拙炪倬捉桌棁涿棳琸窧槕穛穱蠿圴彴犳灼叕妰茁斫浊丵浞烵诼酌啄啅娺梲着斮晫椓琢斱硺窡罬撯擆斲禚劅諁諑鋜濁篧擢斀斵濯櫡謶镯鐯鵫灂蠗鐲籗鷟籱仔孖孜茊兹咨姕姿茲栥玆紎赀资崰淄秶缁谘赼嗞孳嵫椔湽滋粢葘辎鄑孶禌觜貲資趑锱稵緇鈭镃龇輜鼒澬諮趦輺錙髭鲻鍿鎡頾頿鯔鶅齍鰦齜籽子吇姉姊杍矷秄胏呰秭耔虸笫梓釨啙紫滓訾訿榟橴字自芓茡倳剚恣牸渍眥眦胔胾漬唨宗倧综骔堫嵏嵕惾棕猣腙葼朡椶嵸稯綜緃熧緵翪艐蝬踨踪磫豵蹤騌鬃騣鬉鬷鯮鯼鑁总偬捴惣愡揔搃傯蓗摠総縂燪總鍯鏓纵昮疭倊猔碂粽糉瘲縦錝縱邹驺诹郰陬掫菆棷棸鄒箃緅諏鄹鲰鯫黀騶齺赱走鯐奏揍媰租菹葅蒩卆足卒哫崒崪族傶稡箤踤踿镞鏃诅阻组俎爼珇祖組詛靻鎺謯劗躜鑚躦鑽繤缵纂纉籫纘钻揝攥厜朘嗺樶蟕纗嶊嘴噿濢璻枠栬絊酔晬最祽罪辠酻蕞醉嶵檇鋷錊檌穝欈尊嶟遵樽繜罇鶎鐏鳟鱒鷷僔噂撙譐捘銌昨秨莋捽椊葃稓筰鈼左佐繓作坐阼岝岞怍侳柞祚胙唑座袏做葄蓙飵糳咗</pc>
+
+ </rules>
+ </collation>
+
+
</charset>
<charset name="latin1">
@@ -148,4 +303,791 @@
<collation name="latin1_test" id="99" order="test"/>
</charset>
+ <charset name="utf8">
+ <collation name="utf8_bengali_standard_ci" id="336">
+ <rules>
+ <reset>\u9FA</reset>
+ <p>\u9F8</p>
+ <p>\u9F9</p>
+ <p>\u9F2</p>
+ <p>\u9F3</p>
+ <p>\u985</p>
+ <p>\u986</p>
+ <p>\u987</p>
+ <p>\u988</p>
+ <p>\u989</p>
+ <p>\u98A</p>
+ <p>\u98B</p>
+ <p>\u9E0</p>
+ <p>\u98C</p>
+ <p>\u9E1</p>
+ <p>\u98F</p>
+ <p>\u990</p>
+ <p>\u993</p>
+ <p>\u994</p>
+ <p>\u9BC</p>
+ <p>\u982</p>
+ <p>\u983</p>
+ <p>\u981</p>
+ <p>\u995</p>
+ <p>\u996</p>
+ <p>\u997</p>
+ <p>\u998</p>
+ <p>\u999</p>
+ <p>\u99A</p>
+ <p>\u99B</p>
+ <p>\u99C</p>
+ <p>\u99D</p>
+ <p>\u99E</p>
+ <p>\u99F</p>
+ <p>\u9A0</p>
+ <p>\u9A1</p>
+ <p>\u9DC</p>
+ <i>\u9A1\u9BC</i>
+ <p>\u9A2</p>
+ <p>\u9DD</p>
+ <i>\u9A2\u9BC</i>
+ <p>\u9A3</p>
+ <p>\u9CE</p>
+ <p>\u9A4</p>
+ <p>\u9A5</p>
+ <p>\u9A6</p>
+ <p>\u9A7</p>
+ <p>\u9A8</p>
+ <p>\u9AA</p>
+ <p>\u9AB</p>
+ <p>\u9AC</p>
+ <p>\u9AD</p>
+ <p>\u9AE</p>
+ <p>\u9AF</p>
+ <p>\u9DF</p>
+ <i>\u9AF\u9BC</i>
+ <p>\u9B0</p>
+ <p>\u9F0</p>
+ <p>\u9B2</p>
+ <p>\u9F1</p>
+ <p>\u9B6</p>
+ <p>\u9B7</p>
+ <p>\u9B8</p>
+ <p>\u9B9</p>
+ <p>\u9BD</p>
+ <p>\u9BE</p>
+ <p>\u9BF</p>
+ <p>\u9C0</p>
+ <p>\u9C1</p>
+ <p>\u9C2</p>
+ <p>\u9C3</p>
+ <p>\u9C4</p>
+ <p>\u9E2</p>
+ <p>\u9E3</p>
+ <p>\u9C7</p>
+ <p>\u9C8</p>
+ <p>\u9CB</p>
+ <i>\u9C7\u9BE</i>
+ <p>\u9CC</p>
+ <i>\u9C7\u9D7</i>
+ <p>\u9CD</p>
+ <p>\u9D7</p>
+ </rules>
+ </collation>
+
+ <collation name="utf8_bengali_traditional_ci" id="337">
+ <rules>
+ <reset>\u994</reset>
+ <p>\u982</p>
+ <p>\u983</p>
+ <p>\u981</p>
+ <p>\u995\u9CD</p>
+ <p>\u996\u9CD</p>
+ <p>\u997\u9CD</p>
+ <p>\u998\u9CD</p>
+ <p>\u999\u9CD</p>
+ <p>\u99A\u9CD</p>
+ <p>\u99B\u9CD</p>
+ <p>\u99C\u9CD</p>
+ <p>\u99D\u9CD</p>
+ <p>\u99E\u9CD</p>
+ <p>\u99F\u9CD</p>
+ <p>\u9A0\u9CD</p>
+ <p>\u9A1\u9CD</p>
+ <p>\u9A2\u9CD</p>
+ <p>\u9A3\u9CD</p>
+ <p>\u9CE</p><i>\u9A4\u9CD\u200D</i><s>\u9A4\u9CD</s>
+ <p>\u9A5\u9CD</p>
+ <p>\u9A6\u9CD</p>
+ <p>\u9A7\u9CD</p>
+ <p>\u9A8\u9CD</p>
+ <p>\u9AA\u9CD</p>
+ <p>\u9AB\u9CD</p>
+ <p>\u9AC\u9CD</p>
+ <p>\u9AD\u9CD</p>
+ <p>\u9AE\u9CD</p>
+ <p>\u9AF\u9CD</p>
+ <p>\u9B0\u9CD</p>
+ <p>\u9F0\u9CD</p>
+ <p>\u9B2\u9CD</p>
+ <p>\u9F1\u9CD</p>
+ <p>\u9B6\u9CD</p>
+ <p>\u9B7\u9CD</p>
+ <p>\u9B8\u9CD</p>
+ <p>\u9B9\u9CD</p>
+
+ <reset>\u995\u9CD\u985</reset><i>\u995</i>
+ <reset>\u995\u9CD\u986</reset><i>\u995\u9BE</i>
+ <reset>\u995\u9CD\u987</reset><i>\u995\u9BF</i>
+ <reset>\u995\u9CD\u988</reset><i>\u995\u9C0</i>
+ <reset>\u995\u9CD\u989</reset><i>\u995\u9C1</i>
+ <reset>\u995\u9CD\u98A</reset><i>\u995\u9C2</i>
+ <reset>\u995\u9CD\u98B</reset><i>\u995\u9C3</i>
+ <reset>\u995\u9CD\u9E0</reset><i>\u995\u9C4</i>
+ <reset>\u995\u9CD\u98C</reset><i>\u995\u9E2</i>
+ <reset>\u995\u9CD\u9E1</reset><i>\u995\u9E3</i>
+ <reset>\u995\u9CD\u98F</reset><i>\u995\u9C7</i>
+ <reset>\u995\u9CD\u990</reset><i>\u995\u9C8</i>
+ <reset>\u995\u9CD\u993</reset><i>\u995\u9CB</i>
+ <reset>\u995\u9CD\u994</reset><i>\u995\u9CC</i>
+
+ <reset>\u996\u9CD\u985</reset><i>\u996</i>
+ <reset>\u996\u9CD\u986</reset><i>\u996\u9BE</i>
+ <reset>\u996\u9CD\u987</reset><i>\u996\u9BF</i>
+ <reset>\u996\u9CD\u988</reset><i>\u996\u9C0</i>
+ <reset>\u996\u9CD\u989</reset><i>\u996\u9C1</i>
+ <reset>\u996\u9CD\u98A</reset><i>\u996\u9C2</i>
+ <reset>\u996\u9CD\u98B</reset><i>\u996\u9C3</i>
+ <reset>\u996\u9CD\u9E0</reset><i>\u996\u9C4</i>
+ <reset>\u996\u9CD\u98C</reset><i>\u996\u9E2</i>
+ <reset>\u996\u9CD\u9E1</reset><i>\u996\u9E3</i>
+ <reset>\u996\u9CD\u98F</reset><i>\u996\u9C7</i>
+ <reset>\u996\u9CD\u990</reset><i>\u996\u9C8</i>
+ <reset>\u996\u9CD\u993</reset><i>\u996\u9CB</i>
+ <reset>\u996\u9CD\u994</reset><i>\u996\u9CC</i>
+
+ <reset>\u997\u9CD\u985</reset><i>\u997</i>
+ <reset>\u997\u9CD\u986</reset><i>\u997\u9BE</i>
+ <reset>\u997\u9CD\u987</reset><i>\u997\u9BF</i>
+ <reset>\u997\u9CD\u988</reset><i>\u997\u9C0</i>
+ <reset>\u997\u9CD\u989</reset><i>\u997\u9C1</i>
+ <reset>\u997\u9CD\u98A</reset><i>\u997\u9C2</i>
+ <reset>\u997\u9CD\u98B</reset><i>\u997\u9C3</i>
+ <reset>\u997\u9CD\u9E0</reset><i>\u997\u9C4</i>
+ <reset>\u997\u9CD\u98C</reset><i>\u997\u9E2</i>
+ <reset>\u997\u9CD\u9E1</reset><i>\u997\u9E3</i>
+ <reset>\u997\u9CD\u98F</reset><i>\u997\u9C7</i>
+ <reset>\u997\u9CD\u990</reset><i>\u997\u9C8</i>
+ <reset>\u997\u9CD\u993</reset><i>\u997\u9CB</i>
+ <reset>\u997\u9CD\u994</reset><i>\u997\u9CC</i>
+
+ <reset>\u998\u9CD\u985</reset><i>\u998</i>
+ <reset>\u998\u9CD\u986</reset><i>\u998\u9BE</i>
+ <reset>\u998\u9CD\u987</reset><i>\u998\u9BF</i>
+ <reset>\u998\u9CD\u988</reset><i>\u998\u9C0</i>
+ <reset>\u998\u9CD\u989</reset><i>\u998\u9C1</i>
+ <reset>\u998\u9CD\u98A</reset><i>\u998\u9C2</i>
+ <reset>\u998\u9CD\u98B</reset><i>\u998\u9C3</i>
+ <reset>\u998\u9CD\u9E0</reset><i>\u998\u9C4</i>
+ <reset>\u998\u9CD\u98C</reset><i>\u998\u9E2</i>
+ <reset>\u998\u9CD\u9E1</reset><i>\u998\u9E3</i>
+ <reset>\u998\u9CD\u98F</reset><i>\u998\u9C7</i>
+ <reset>\u998\u9CD\u990</reset><i>\u998\u9C8</i>
+ <reset>\u998\u9CD\u993</reset><i>\u998\u9CB</i>
+ <reset>\u998\u9CD\u994</reset><i>\u998\u9CC</i>
+
+ <reset>\u999\u9CD\u985</reset><i>\u999</i>
+ <reset>\u999\u9CD\u986</reset><i>\u999\u9BE</i>
+ <reset>\u999\u9CD\u987</reset><i>\u999\u9BF</i>
+ <reset>\u999\u9CD\u988</reset><i>\u999\u9C0</i>
+ <reset>\u999\u9CD\u989</reset><i>\u999\u9C1</i>
+ <reset>\u999\u9CD\u98A</reset><i>\u999\u9C2</i>
+ <reset>\u999\u9CD\u98B</reset><i>\u999\u9C3</i>
+ <reset>\u999\u9CD\u9E0</reset><i>\u999\u9C4</i>
+ <reset>\u999\u9CD\u98C</reset><i>\u999\u9E2</i>
+ <reset>\u999\u9CD\u9E1</reset><i>\u999\u9E3</i>
+ <reset>\u999\u9CD\u98F</reset><i>\u999\u9C7</i>
+ <reset>\u999\u9CD\u990</reset><i>\u999\u9C8</i>
+ <reset>\u999\u9CD\u993</reset><i>\u999\u9CB</i>
+ <reset>\u999\u9CD\u994</reset><i>\u999\u9CC</i>
+
+ <reset>\u99A\u9CD\u985</reset><i>\u99A</i>
+ <reset>\u99A\u9CD\u986</reset><i>\u99A\u9BE</i>
+ <reset>\u99A\u9CD\u987</reset><i>\u99A\u9BF</i>
+ <reset>\u99A\u9CD\u988</reset><i>\u99A\u9C0</i>
+ <reset>\u99A\u9CD\u989</reset><i>\u99A\u9C1</i>
+ <reset>\u99A\u9CD\u98A</reset><i>\u99A\u9C2</i>
+ <reset>\u99A\u9CD\u98B</reset><i>\u99A\u9C3</i>
+ <reset>\u99A\u9CD\u9E0</reset><i>\u99A\u9C4</i>
+ <reset>\u99A\u9CD\u98C</reset><i>\u99A\u9E2</i>
+ <reset>\u99A\u9CD\u9E1</reset><i>\u99A\u9E3</i>
+ <reset>\u99A\u9CD\u98F</reset><i>\u99A\u9C7</i>
+ <reset>\u99A\u9CD\u990</reset><i>\u99A\u9C8</i>
+ <reset>\u99A\u9CD\u993</reset><i>\u99A\u9CB</i>
+ <reset>\u99A\u9CD\u994</reset><i>\u99A\u9CC</i>
+
+ <reset>\u99B\u9CD\u985</reset><i>\u99B</i>
+ <reset>\u99B\u9CD\u986</reset><i>\u99B\u9BE</i>
+ <reset>\u99B\u9CD\u987</reset><i>\u99B\u9BF</i>
+ <reset>\u99B\u9CD\u988</reset><i>\u99B\u9C0</i>
+ <reset>\u99B\u9CD\u989</reset><i>\u99B\u9C1</i>
+ <reset>\u99B\u9CD\u98A</reset><i>\u99B\u9C2</i>
+ <reset>\u99B\u9CD\u98B</reset><i>\u99B\u9C3</i>
+ <reset>\u99B\u9CD\u9E0</reset><i>\u99B\u9C4</i>
+ <reset>\u99B\u9CD\u98C</reset><i>\u99B\u9E2</i>
+ <reset>\u99B\u9CD\u9E1</reset><i>\u99B\u9E3</i>
+ <reset>\u99B\u9CD\u98F</reset><i>\u99B\u9C7</i>
+ <reset>\u99B\u9CD\u990</reset><i>\u99B\u9C8</i>
+ <reset>\u99B\u9CD\u993</reset><i>\u99B\u9CB</i>
+ <reset>\u99B\u9CD\u994</reset><i>\u99B\u9CC</i>
+
+ <reset>\u99C\u9CD\u985</reset><i>\u99C</i>
+ <reset>\u99C\u9CD\u986</reset><i>\u99C\u9BE</i>
+ <reset>\u99C\u9CD\u987</reset><i>\u99C\u9BF</i>
+ <reset>\u99C\u9CD\u988</reset><i>\u99C\u9C0</i>
+ <reset>\u99C\u9CD\u989</reset><i>\u99C\u9C1</i>
+ <reset>\u99C\u9CD\u98A</reset><i>\u99C\u9C2</i>
+ <reset>\u99C\u9CD\u98B</reset><i>\u99C\u9C3</i>
+ <reset>\u99C\u9CD\u9E0</reset><i>\u99C\u9C4</i>
+ <reset>\u99C\u9CD\u98C</reset><i>\u99C\u9E2</i>
+ <reset>\u99C\u9CD\u9E1</reset><i>\u99C\u9E3</i>
+ <reset>\u99C\u9CD\u98F</reset><i>\u99C\u9C7</i>
+ <reset>\u99C\u9CD\u990</reset><i>\u99C\u9C8</i>
+ <reset>\u99C\u9CD\u993</reset><i>\u99C\u9CB</i>
+ <reset>\u99C\u9CD\u994</reset><i>\u99C\u9CC</i>
+
+ <reset>\u99D\u9CD\u985</reset><i>\u99D</i>
+ <reset>\u99D\u9CD\u986</reset><i>\u99D\u9BE</i>
+ <reset>\u99D\u9CD\u987</reset><i>\u99D\u9BF</i>
+ <reset>\u99D\u9CD\u988</reset><i>\u99D\u9C0</i>
+ <reset>\u99D\u9CD\u989</reset><i>\u99D\u9C1</i>
+ <reset>\u99D\u9CD\u98A</reset><i>\u99D\u9C2</i>
+ <reset>\u99D\u9CD\u98B</reset><i>\u99D\u9C3</i>
+ <reset>\u99D\u9CD\u9E0</reset><i>\u99D\u9C4</i>
+ <reset>\u99D\u9CD\u98C</reset><i>\u99D\u9E2</i>
+ <reset>\u99D\u9CD\u9E1</reset><i>\u99D\u9E3</i>
+ <reset>\u99D\u9CD\u98F</reset><i>\u99D\u9C7</i>
+ <reset>\u99D\u9CD\u990</reset><i>\u99D\u9C8</i>
+ <reset>\u99D\u9CD\u993</reset><i>\u99D\u9CB</i>
+ <reset>\u99D\u9CD\u994</reset><i>\u99D\u9CC</i>
+
+ <reset>\u99E\u9CD\u985</reset><i>\u99E</i>
+ <reset>\u99E\u9CD\u986</reset><i>\u99E\u9BE</i>
+ <reset>\u99E\u9CD\u987</reset><i>\u99E\u9BF</i>
+ <reset>\u99E\u9CD\u988</reset><i>\u99E\u9C0</i>
+ <reset>\u99E\u9CD\u989</reset><i>\u99E\u9C1</i>
+ <reset>\u99E\u9CD\u98A</reset><i>\u99E\u9C2</i>
+ <reset>\u99E\u9CD\u98B</reset><i>\u99E\u9C3</i>
+ <reset>\u99E\u9CD\u9E0</reset><i>\u99E\u9C4</i>
+ <reset>\u99E\u9CD\u98C</reset><i>\u99E\u9E2</i>
+ <reset>\u99E\u9CD\u9E1</reset><i>\u99E\u9E3</i>
+ <reset>\u99E\u9CD\u98F</reset><i>\u99E\u9C7</i>
+ <reset>\u99E\u9CD\u990</reset><i>\u99E\u9C8</i>
+ <reset>\u99E\u9CD\u993</reset><i>\u99E\u9CB</i>
+ <reset>\u99E\u9CD\u994</reset><i>\u99E\u9CC</i>
+
+ <reset>\u99F\u9CD\u985</reset><i>\u99F</i>
+ <reset>\u99F\u9CD\u986</reset><i>\u99F\u9BE</i>
+ <reset>\u99F\u9CD\u987</reset><i>\u99F\u9BF</i>
+ <reset>\u99F\u9CD\u988</reset><i>\u99F\u9C0</i>
+ <reset>\u99F\u9CD\u989</reset><i>\u99F\u9C1</i>
+ <reset>\u99F\u9CD\u98A</reset><i>\u99F\u9C2</i>
+ <reset>\u99F\u9CD\u98B</reset><i>\u99F\u9C3</i>
+ <reset>\u99F\u9CD\u9E0</reset><i>\u99F\u9C4</i>
+ <reset>\u99F\u9CD\u98C</reset><i>\u99F\u9E2</i>
+ <reset>\u99F\u9CD\u9E1</reset><i>\u99F\u9E3</i>
+ <reset>\u99F\u9CD\u98F</reset><i>\u99F\u9C7</i>
+ <reset>\u99F\u9CD\u990</reset><i>\u99F\u9C8</i>
+ <reset>\u99F\u9CD\u993</reset><i>\u99F\u9CB</i>
+ <reset>\u99F\u9CD\u994</reset><i>\u99F\u9CC</i>
+
+ <reset>\u9A0\u9CD\u985</reset><i>\u9A0</i>
+ <reset>\u9A0\u9CD\u986</reset><i>\u9A0\u9BE</i>
+ <reset>\u9A0\u9CD\u987</reset><i>\u9A0\u9BF</i>
+ <reset>\u9A0\u9CD\u988</reset><i>\u9A0\u9C0</i>
+ <reset>\u9A0\u9CD\u989</reset><i>\u9A0\u9C1</i>
+ <reset>\u9A0\u9CD\u98A</reset><i>\u9A0\u9C2</i>
+ <reset>\u9A0\u9CD\u98B</reset><i>\u9A0\u9C3</i>
+ <reset>\u9A0\u9CD\u9E0</reset><i>\u9A0\u9C4</i>
+ <reset>\u9A0\u9CD\u98C</reset><i>\u9A0\u9E2</i>
+ <reset>\u9A0\u9CD\u9E1</reset><i>\u9A0\u9E3</i>
+ <reset>\u9A0\u9CD\u98F</reset><i>\u9A0\u9C7</i>
+ <reset>\u9A0\u9CD\u990</reset><i>\u9A0\u9C8</i>
+ <reset>\u9A0\u9CD\u993</reset><i>\u9A0\u9CB</i>
+ <reset>\u9A0\u9CD\u994</reset><i>\u9A0\u9CC</i>
+
+ <reset>\u9A1\u9CD\u985</reset><i>\u9A1</i>
+ <reset>\u9A1\u9CD\u986</reset><i>\u9A1\u9BE</i>
+ <reset>\u9A1\u9CD\u987</reset><i>\u9A1\u9BF</i>
+ <reset>\u9A1\u9CD\u988</reset><i>\u9A1\u9C0</i>
+ <reset>\u9A1\u9CD\u989</reset><i>\u9A1\u9C1</i>
+ <reset>\u9A1\u9CD\u98A</reset><i>\u9A1\u9C2</i>
+ <reset>\u9A1\u9CD\u98B</reset><i>\u9A1\u9C3</i>
+ <reset>\u9A1\u9CD\u9E0</reset><i>\u9A1\u9C4</i>
+ <reset>\u9A1\u9CD\u98C</reset><i>\u9A1\u9E2</i>
+ <reset>\u9A1\u9CD\u9E1</reset><i>\u9A1\u9E3</i>
+ <reset>\u9A1\u9CD\u98F</reset><i>\u9A1\u9C7</i>
+ <reset>\u9A1\u9CD\u990</reset><i>\u9A1\u9C8</i>
+ <reset>\u9A1\u9CD\u993</reset><i>\u9A1\u9CB</i>
+ <reset>\u9A1\u9CD\u994</reset><i>\u9A1\u9CC</i>
+
+ <reset>\u9A2\u9CD\u985</reset><i>\u9A2</i>
+ <reset>\u9A2\u9CD\u986</reset><i>\u9A2\u9BE</i>
+ <reset>\u9A2\u9CD\u987</reset><i>\u9A2\u9BF</i>
+ <reset>\u9A2\u9CD\u988</reset><i>\u9A2\u9C0</i>
+ <reset>\u9A2\u9CD\u989</reset><i>\u9A2\u9C1</i>
+ <reset>\u9A2\u9CD\u98A</reset><i>\u9A2\u9C2</i>
+ <reset>\u9A2\u9CD\u98B</reset><i>\u9A2\u9C3</i>
+ <reset>\u9A2\u9CD\u9E0</reset><i>\u9A2\u9C4</i>
+ <reset>\u9A2\u9CD\u98C</reset><i>\u9A2\u9E2</i>
+ <reset>\u9A2\u9CD\u9E1</reset><i>\u9A2\u9E3</i>
+ <reset>\u9A2\u9CD\u98F</reset><i>\u9A2\u9C7</i>
+ <reset>\u9A2\u9CD\u990</reset><i>\u9A2\u9C8</i>
+ <reset>\u9A2\u9CD\u993</reset><i>\u9A2\u9CB</i>
+ <reset>\u9A2\u9CD\u994</reset><i>\u9A2\u9CC</i>
+
+ <reset>\u9A3\u9CD\u985</reset><i>\u9A3</i>
+ <reset>\u9A3\u9CD\u986</reset><i>\u9A3\u9BE</i>
+ <reset>\u9A3\u9CD\u987</reset><i>\u9A3\u9BF</i>
+ <reset>\u9A3\u9CD\u988</reset><i>\u9A3\u9C0</i>
+ <reset>\u9A3\u9CD\u989</reset><i>\u9A3\u9C1</i>
+ <reset>\u9A3\u9CD\u98A</reset><i>\u9A3\u9C2</i>
+ <reset>\u9A3\u9CD\u98B</reset><i>\u9A3\u9C3</i>
+ <reset>\u9A3\u9CD\u9E0</reset><i>\u9A3\u9C4</i>
+ <reset>\u9A3\u9CD\u98C</reset><i>\u9A3\u9E2</i>
+ <reset>\u9A3\u9CD\u9E1</reset><i>\u9A3\u9E3</i>
+ <reset>\u9A3\u9CD\u98F</reset><i>\u9A3\u9C7</i>
+ <reset>\u9A3\u9CD\u990</reset><i>\u9A3\u9C8</i>
+ <reset>\u9A3\u9CD\u993</reset><i>\u9A3\u9CB</i>
+ <reset>\u9A3\u9CD\u994</reset><i>\u9A3\u9CC</i>
+
+ <reset>\u9A4\u9CD\u985</reset><i>\u9A4</i>
+ <reset>\u9A4\u9CD\u986</reset><i>\u9A4\u9BE</i>
+ <reset>\u9A4\u9CD\u987</reset><i>\u9A4\u9BF</i>
+ <reset>\u9A4\u9CD\u988</reset><i>\u9A4\u9C0</i>
+ <reset>\u9A4\u9CD\u989</reset><i>\u9A4\u9C1</i>
+ <reset>\u9A4\u9CD\u98A</reset><i>\u9A4\u9C2</i>
+ <reset>\u9A4\u9CD\u98B</reset><i>\u9A4\u9C3</i>
+ <reset>\u9A4\u9CD\u9E0</reset><i>\u9A4\u9C4</i>
+ <reset>\u9A4\u9CD\u98C</reset><i>\u9A4\u9E2</i>
+ <reset>\u9A4\u9CD\u9E1</reset><i>\u9A4\u9E3</i>
+ <reset>\u9A4\u9CD\u98F</reset><i>\u9A4\u9C7</i>
+ <reset>\u9A4\u9CD\u990</reset><i>\u9A4\u9C8</i>
+ <reset>\u9A4\u9CD\u993</reset><i>\u9A4\u9CB</i>
+ <reset>\u9A4\u9CD\u994</reset><i>\u9A4\u9CC</i>
+
+ <reset>\u9A5\u9CD\u985</reset><i>\u9A5</i>
+ <reset>\u9A5\u9CD\u986</reset><i>\u9A5\u9BE</i>
+ <reset>\u9A5\u9CD\u987</reset><i>\u9A5\u9BF</i>
+ <reset>\u9A5\u9CD\u988</reset><i>\u9A5\u9C0</i>
+ <reset>\u9A5\u9CD\u989</reset><i>\u9A5\u9C1</i>
+ <reset>\u9A5\u9CD\u98A</reset><i>\u9A5\u9C2</i>
+ <reset>\u9A5\u9CD\u98B</reset><i>\u9A5\u9C3</i>
+ <reset>\u9A5\u9CD\u9E0</reset><i>\u9A5\u9C4</i>
+ <reset>\u9A5\u9CD\u98C</reset><i>\u9A5\u9E2</i>
+ <reset>\u9A5\u9CD\u9E1</reset><i>\u9A5\u9E3</i>
+ <reset>\u9A5\u9CD\u98F</reset><i>\u9A5\u9C7</i>
+ <reset>\u9A5\u9CD\u990</reset><i>\u9A5\u9C8</i>
+ <reset>\u9A5\u9CD\u993</reset><i>\u9A5\u9CB</i>
+ <reset>\u9A5\u9CD\u994</reset><i>\u9A5\u9CC</i>
+
+ <reset>\u9A6\u9CD\u985</reset><i>\u9A6</i>
+ <reset>\u9A6\u9CD\u986</reset><i>\u9A6\u9BE</i>
+ <reset>\u9A6\u9CD\u987</reset><i>\u9A6\u9BF</i>
+ <reset>\u9A6\u9CD\u988</reset><i>\u9A6\u9C0</i>
+ <reset>\u9A6\u9CD\u989</reset><i>\u9A6\u9C1</i>
+ <reset>\u9A6\u9CD\u98A</reset><i>\u9A6\u9C2</i>
+ <reset>\u9A6\u9CD\u98B</reset><i>\u9A6\u9C3</i>
+ <reset>\u9A6\u9CD\u9E0</reset><i>\u9A6\u9C4</i>
+ <reset>\u9A6\u9CD\u98C</reset><i>\u9A6\u9E2</i>
+ <reset>\u9A6\u9CD\u9E1</reset><i>\u9A6\u9E3</i>
+ <reset>\u9A6\u9CD\u98F</reset><i>\u9A6\u9C7</i>
+ <reset>\u9A6\u9CD\u990</reset><i>\u9A6\u9C8</i>
+ <reset>\u9A6\u9CD\u993</reset><i>\u9A6\u9CB</i>
+ <reset>\u9A6\u9CD\u994</reset><i>\u9A6\u9CC</i>
+
+ <reset>\u9A7\u9CD\u985</reset><i>\u9A7</i>
+ <reset>\u9A7\u9CD\u986</reset><i>\u9A7\u9BE</i>
+ <reset>\u9A7\u9CD\u987</reset><i>\u9A7\u9BF</i>
+ <reset>\u9A7\u9CD\u988</reset><i>\u9A7\u9C0</i>
+ <reset>\u9A7\u9CD\u989</reset><i>\u9A7\u9C1</i>
+ <reset>\u9A7\u9CD\u98A</reset><i>\u9A7\u9C2</i>
+ <reset>\u9A7\u9CD\u98B</reset><i>\u9A7\u9C3</i>
+ <reset>\u9A7\u9CD\u9E0</reset><i>\u9A7\u9C4</i>
+ <reset>\u9A7\u9CD\u98C</reset><i>\u9A7\u9E2</i>
+ <reset>\u9A7\u9CD\u9E1</reset><i>\u9A7\u9E3</i>
+ <reset>\u9A7\u9CD\u98F</reset><i>\u9A7\u9C7</i>
+ <reset>\u9A7\u9CD\u990</reset><i>\u9A7\u9C8</i>
+ <reset>\u9A7\u9CD\u993</reset><i>\u9A7\u9CB</i>
+ <reset>\u9A7\u9CD\u994</reset><i>\u9A7\u9CC</i>
+
+ <reset>\u9A8\u9CD\u985</reset><i>\u9A8</i>
+ <reset>\u9A8\u9CD\u986</reset><i>\u9A8\u9BE</i>
+ <reset>\u9A8\u9CD\u987</reset><i>\u9A8\u9BF</i>
+ <reset>\u9A8\u9CD\u988</reset><i>\u9A8\u9C0</i>
+ <reset>\u9A8\u9CD\u989</reset><i>\u9A8\u9C1</i>
+ <reset>\u9A8\u9CD\u98A</reset><i>\u9A8\u9C2</i>
+ <reset>\u9A8\u9CD\u98B</reset><i>\u9A8\u9C3</i>
+ <reset>\u9A8\u9CD\u9E0</reset><i>\u9A8\u9C4</i>
+ <reset>\u9A8\u9CD\u98C</reset><i>\u9A8\u9E2</i>
+ <reset>\u9A8\u9CD\u9E1</reset><i>\u9A8\u9E3</i>
+ <reset>\u9A8\u9CD\u98F</reset><i>\u9A8\u9C7</i>
+ <reset>\u9A8\u9CD\u990</reset><i>\u9A8\u9C8</i>
+ <reset>\u9A8\u9CD\u993</reset><i>\u9A8\u9CB</i>
+ <reset>\u9A8\u9CD\u994</reset><i>\u9A8\u9CC</i>
+
+ <reset>\u9AA\u9CD\u985</reset><i>\u9AA</i>
+ <reset>\u9AA\u9CD\u986</reset><i>\u9AA\u9BE</i>
+ <reset>\u9AA\u9CD\u987</reset><i>\u9AA\u9BF</i>
+ <reset>\u9AA\u9CD\u988</reset><i>\u9AA\u9C0</i>
+ <reset>\u9AA\u9CD\u989</reset><i>\u9AA\u9C1</i>
+ <reset>\u9AA\u9CD\u98A</reset><i>\u9AA\u9C2</i>
+ <reset>\u9AA\u9CD\u98B</reset><i>\u9AA\u9C3</i>
+ <reset>\u9AA\u9CD\u9E0</reset><i>\u9AA\u9C4</i>
+ <reset>\u9AA\u9CD\u98C</reset><i>\u9AA\u9E2</i>
+ <reset>\u9AA\u9CD\u9E1</reset><i>\u9AA\u9E3</i>
+ <reset>\u9AA\u9CD\u98F</reset><i>\u9AA\u9C7</i>
+ <reset>\u9AA\u9CD\u990</reset><i>\u9AA\u9C8</i>
+ <reset>\u9AA\u9CD\u993</reset><i>\u9AA\u9CB</i>
+ <reset>\u9AA\u9CD\u994</reset><i>\u9AA\u9CC</i>
+
+ <reset>\u9AB\u9CD\u985</reset><i>\u9AB</i>
+ <reset>\u9AB\u9CD\u986</reset><i>\u9AB\u9BE</i>
+ <reset>\u9AB\u9CD\u987</reset><i>\u9AB\u9BF</i>
+ <reset>\u9AB\u9CD\u988</reset><i>\u9AB\u9C0</i>
+ <reset>\u9AB\u9CD\u989</reset><i>\u9AB\u9C1</i>
+ <reset>\u9AB\u9CD\u98A</reset><i>\u9AB\u9C2</i>
+ <reset>\u9AB\u9CD\u98B</reset><i>\u9AB\u9C3</i>
+ <reset>\u9AB\u9CD\u9E0</reset><i>\u9AB\u9C4</i>
+ <reset>\u9AB\u9CD\u98C</reset><i>\u9AB\u9E2</i>
+ <reset>\u9AB\u9CD\u9E1</reset><i>\u9AB\u9E3</i>
+ <reset>\u9AB\u9CD\u98F</reset><i>\u9AB\u9C7</i>
+ <reset>\u9AB\u9CD\u990</reset><i>\u9AB\u9C8</i>
+ <reset>\u9AB\u9CD\u993</reset><i>\u9AB\u9CB</i>
+ <reset>\u9AB\u9CD\u994</reset><i>\u9AB\u9CC</i>
+
+ <reset>\u9AC\u9CD\u985</reset><i>\u9AC</i>
+ <reset>\u9AC\u9CD\u986</reset><i>\u9AC\u9BE</i>
+ <reset>\u9AC\u9CD\u987</reset><i>\u9AC\u9BF</i>
+ <reset>\u9AC\u9CD\u988</reset><i>\u9AC\u9C0</i>
+ <reset>\u9AC\u9CD\u989</reset><i>\u9AC\u9C1</i>
+ <reset>\u9AC\u9CD\u98A</reset><i>\u9AC\u9C2</i>
+ <reset>\u9AC\u9CD\u98B</reset><i>\u9AC\u9C3</i>
+ <reset>\u9AC\u9CD\u9E0</reset><i>\u9AC\u9C4</i>
+ <reset>\u9AC\u9CD\u98C</reset><i>\u9AC\u9E2</i>
+ <reset>\u9AC\u9CD\u9E1</reset><i>\u9AC\u9E3</i>
+ <reset>\u9AC\u9CD\u98F</reset><i>\u9AC\u9C7</i>
+ <reset>\u9AC\u9CD\u990</reset><i>\u9AC\u9C8</i>
+ <reset>\u9AC\u9CD\u993</reset><i>\u9AC\u9CB</i>
+ <reset>\u9AC\u9CD\u994</reset><i>\u9AC\u9CC</i>
+
+ <reset>\u9AD\u9CD\u985</reset><i>\u9AD</i>
+ <reset>\u9AD\u9CD\u986</reset><i>\u9AD\u9BE</i>
+ <reset>\u9AD\u9CD\u987</reset><i>\u9AD\u9BF</i>
+ <reset>\u9AD\u9CD\u988</reset><i>\u9AD\u9C0</i>
+ <reset>\u9AD\u9CD\u989</reset><i>\u9AD\u9C1</i>
+ <reset>\u9AD\u9CD\u98A</reset><i>\u9AD\u9C2</i>
+ <reset>\u9AD\u9CD\u98B</reset><i>\u9AD\u9C3</i>
+ <reset>\u9AD\u9CD\u9E0</reset><i>\u9AD\u9C4</i>
+ <reset>\u9AD\u9CD\u98C</reset><i>\u9AD\u9E2</i>
+ <reset>\u9AD\u9CD\u9E1</reset><i>\u9AD\u9E3</i>
+ <reset>\u9AD\u9CD\u98F</reset><i>\u9AD\u9C7</i>
+ <reset>\u9AD\u9CD\u990</reset><i>\u9AD\u9C8</i>
+ <reset>\u9AD\u9CD\u993</reset><i>\u9AD\u9CB</i>
+ <reset>\u9AD\u9CD\u994</reset><i>\u9AD\u9CC</i>
+
+ <reset>\u9AE\u9CD\u985</reset><i>\u9AE</i>
+ <reset>\u9AE\u9CD\u986</reset><i>\u9AE\u9BE</i>
+ <reset>\u9AE\u9CD\u987</reset><i>\u9AE\u9BF</i>
+ <reset>\u9AE\u9CD\u988</reset><i>\u9AE\u9C0</i>
+ <reset>\u9AE\u9CD\u989</reset><i>\u9AE\u9C1</i>
+ <reset>\u9AE\u9CD\u98A</reset><i>\u9AE\u9C2</i>
+ <reset>\u9AE\u9CD\u98B</reset><i>\u9AE\u9C3</i>
+ <reset>\u9AE\u9CD\u9E0</reset><i>\u9AE\u9C4</i>
+ <reset>\u9AE\u9CD\u98C</reset><i>\u9AE\u9E2</i>
+ <reset>\u9AE\u9CD\u9E1</reset><i>\u9AE\u9E3</i>
+ <reset>\u9AE\u9CD\u98F</reset><i>\u9AE\u9C7</i>
+ <reset>\u9AE\u9CD\u990</reset><i>\u9AE\u9C8</i>
+ <reset>\u9AE\u9CD\u993</reset><i>\u9AE\u9CB</i>
+ <reset>\u9AE\u9CD\u994</reset><i>\u9AE\u9CC</i>
+
+ <reset>\u9AF\u9CD\u985</reset><i>\u9AF</i>
+ <reset>\u9AF\u9CD\u986</reset><i>\u9AF\u9BE</i>
+ <reset>\u9AF\u9CD\u987</reset><i>\u9AF\u9BF</i>
+ <reset>\u9AF\u9CD\u988</reset><i>\u9AF\u9C0</i>
+ <reset>\u9AF\u9CD\u989</reset><i>\u9AF\u9C1</i>
+ <reset>\u9AF\u9CD\u98A</reset><i>\u9AF\u9C2</i>
+ <reset>\u9AF\u9CD\u98B</reset><i>\u9AF\u9C3</i>
+ <reset>\u9AF\u9CD\u9E0</reset><i>\u9AF\u9C4</i>
+ <reset>\u9AF\u9CD\u98C</reset><i>\u9AF\u9E2</i>
+ <reset>\u9AF\u9CD\u9E1</reset><i>\u9AF\u9E3</i>
+ <reset>\u9AF\u9CD\u98F</reset><i>\u9AF\u9C7</i>
+ <reset>\u9AF\u9CD\u990</reset><i>\u9AF\u9C8</i>
+ <reset>\u9AF\u9CD\u993</reset><i>\u9AF\u9CB</i>
+ <reset>\u9AF\u9CD\u994</reset><i>\u9AF\u9CC</i>
+
+ <reset>\u9B0\u9CD\u985</reset><i>\u9B0</i>
+ <reset>\u9B0\u9CD\u986</reset><i>\u9B0\u9BE</i>
+ <reset>\u9B0\u9CD\u987</reset><i>\u9B0\u9BF</i>
+ <reset>\u9B0\u9CD\u988</reset><i>\u9B0\u9C0</i>
+ <reset>\u9B0\u9CD\u989</reset><i>\u9B0\u9C1</i>
+ <reset>\u9B0\u9CD\u98A</reset><i>\u9B0\u9C2</i>
+ <reset>\u9B0\u9CD\u98B</reset><i>\u9B0\u9C3</i>
+ <reset>\u9B0\u9CD\u9E0</reset><i>\u9B0\u9C4</i>
+ <reset>\u9B0\u9CD\u98C</reset><i>\u9B0\u9E2</i>
+ <reset>\u9B0\u9CD\u9E1</reset><i>\u9B0\u9E3</i>
+ <reset>\u9B0\u9CD\u98F</reset><i>\u9B0\u9C7</i>
+ <reset>\u9B0\u9CD\u990</reset><i>\u9B0\u9C8</i>
+ <reset>\u9B0\u9CD\u993</reset><i>\u9B0\u9CB</i>
+ <reset>\u9B0\u9CD\u994</reset><i>\u9B0\u9CC</i>
+
+ <reset>\u9F0\u9CD\u985</reset><i>\u9F0</i>
+ <reset>\u9F0\u9CD\u986</reset><i>\u9F0\u9BE</i>
+ <reset>\u9F0\u9CD\u987</reset><i>\u9F0\u9BF</i>
+ <reset>\u9F0\u9CD\u988</reset><i>\u9F0\u9C0</i>
+ <reset>\u9F0\u9CD\u989</reset><i>\u9F0\u9C1</i>
+ <reset>\u9F0\u9CD\u98A</reset><i>\u9F0\u9C2</i>
+ <reset>\u9F0\u9CD\u98B</reset><i>\u9F0\u9C3</i>
+ <reset>\u9F0\u9CD\u9E0</reset><i>\u9F0\u9C4</i>
+ <reset>\u9F0\u9CD\u98C</reset><i>\u9F0\u9E2</i>
+ <reset>\u9F0\u9CD\u9E1</reset><i>\u9F0\u9E3</i>
+ <reset>\u9F0\u9CD\u98F</reset><i>\u9F0\u9C7</i>
+ <reset>\u9F0\u9CD\u990</reset><i>\u9F0\u9C8</i>
+ <reset>\u9F0\u9CD\u993</reset><i>\u9F0\u9CB</i>
+ <reset>\u9F0\u9CD\u994</reset><i>\u9F0\u9CC</i>
+
+ <reset>\u9B2\u9CD\u985</reset><i>\u9B2</i>
+ <reset>\u9B2\u9CD\u986</reset><i>\u9B2\u9BE</i>
+ <reset>\u9B2\u9CD\u987</reset><i>\u9B2\u9BF</i>
+ <reset>\u9B2\u9CD\u988</reset><i>\u9B2\u9C0</i>
+ <reset>\u9B2\u9CD\u989</reset><i>\u9B2\u9C1</i>
+ <reset>\u9B2\u9CD\u98A</reset><i>\u9B2\u9C2</i>
+ <reset>\u9B2\u9CD\u98B</reset><i>\u9B2\u9C3</i>
+ <reset>\u9B2\u9CD\u9E0</reset><i>\u9B2\u9C4</i>
+ <reset>\u9B2\u9CD\u98C</reset><i>\u9B2\u9E2</i>
+ <reset>\u9B2\u9CD\u9E1</reset><i>\u9B2\u9E3</i>
+ <reset>\u9B2\u9CD\u98F</reset><i>\u9B2\u9C7</i>
+ <reset>\u9B2\u9CD\u990</reset><i>\u9B2\u9C8</i>
+ <reset>\u9B2\u9CD\u993</reset><i>\u9B2\u9CB</i>
+ <reset>\u9B2\u9CD\u994</reset><i>\u9B2\u9CC</i>
+
+ <reset>\u9F1\u9CD\u985</reset><i>\u9F1</i>
+ <reset>\u9F1\u9CD\u986</reset><i>\u9F1\u9BE</i>
+ <reset>\u9F1\u9CD\u987</reset><i>\u9F1\u9BF</i>
+ <reset>\u9F1\u9CD\u988</reset><i>\u9F1\u9C0</i>
+ <reset>\u9F1\u9CD\u989</reset><i>\u9F1\u9C1</i>
+ <reset>\u9F1\u9CD\u98A</reset><i>\u9F1\u9C2</i>
+ <reset>\u9F1\u9CD\u98B</reset><i>\u9F1\u9C3</i>
+ <reset>\u9F1\u9CD\u9E0</reset><i>\u9F1\u9C4</i>
+ <reset>\u9F1\u9CD\u98C</reset><i>\u9F1\u9E2</i>
+ <reset>\u9F1\u9CD\u9E1</reset><i>\u9F1\u9E3</i>
+ <reset>\u9F1\u9CD\u98F</reset><i>\u9F1\u9C7</i>
+ <reset>\u9F1\u9CD\u990</reset><i>\u9F1\u9C8</i>
+ <reset>\u9F1\u9CD\u993</reset><i>\u9F1\u9CB</i>
+ <reset>\u9F1\u9CD\u994</reset><i>\u9F1\u9CC</i>
+
+ <reset>\u9B6\u9CD\u985</reset><i>\u9B6</i>
+ <reset>\u9B6\u9CD\u986</reset><i>\u9B6\u9BE</i>
+ <reset>\u9B6\u9CD\u987</reset><i>\u9B6\u9BF</i>
+ <reset>\u9B6\u9CD\u988</reset><i>\u9B6\u9C0</i>
+ <reset>\u9B6\u9CD\u989</reset><i>\u9B6\u9C1</i>
+ <reset>\u9B6\u9CD\u98A</reset><i>\u9B6\u9C2</i>
+ <reset>\u9B6\u9CD\u98B</reset><i>\u9B6\u9C3</i>
+ <reset>\u9B6\u9CD\u9E0</reset><i>\u9B6\u9C4</i>
+ <reset>\u9B6\u9CD\u98C</reset><i>\u9B6\u9E2</i>
+ <reset>\u9B6\u9CD\u9E1</reset><i>\u9B6\u9E3</i>
+ <reset>\u9B6\u9CD\u98F</reset><i>\u9B6\u9C7</i>
+ <reset>\u9B6\u9CD\u990</reset><i>\u9B6\u9C8</i>
+ <reset>\u9B6\u9CD\u993</reset><i>\u9B6\u9CB</i>
+ <reset>\u9B6\u9CD\u994</reset><i>\u9B6\u9CC</i>
+
+ <reset>\u9B7\u9CD\u985</reset><i>\u9B7</i>
+ <reset>\u9B7\u9CD\u986</reset><i>\u9B7\u9BE</i>
+ <reset>\u9B7\u9CD\u987</reset><i>\u9B7\u9BF</i>
+ <reset>\u9B7\u9CD\u988</reset><i>\u9B7\u9C0</i>
+ <reset>\u9B7\u9CD\u989</reset><i>\u9B7\u9C1</i>
+ <reset>\u9B7\u9CD\u98A</reset><i>\u9B7\u9C2</i>
+ <reset>\u9B7\u9CD\u98B</reset><i>\u9B7\u9C3</i>
+ <reset>\u9B7\u9CD\u9E0</reset><i>\u9B7\u9C4</i>
+ <reset>\u9B7\u9CD\u98C</reset><i>\u9B7\u9E2</i>
+ <reset>\u9B7\u9CD\u9E1</reset><i>\u9B7\u9E3</i>
+ <reset>\u9B7\u9CD\u98F</reset><i>\u9B7\u9C7</i>
+ <reset>\u9B7\u9CD\u990</reset><i>\u9B7\u9C8</i>
+ <reset>\u9B7\u9CD\u993</reset><i>\u9B7\u9CB</i>
+ <reset>\u9B7\u9CD\u994</reset><i>\u9B7\u9CC</i>
+
+ <reset>\u9B8\u9CD\u985</reset><i>\u9B8</i>
+ <reset>\u9B8\u9CD\u986</reset><i>\u9B8\u9BE</i>
+ <reset>\u9B8\u9CD\u987</reset><i>\u9B8\u9BF</i>
+ <reset>\u9B8\u9CD\u988</reset><i>\u9B8\u9C0</i>
+ <reset>\u9B8\u9CD\u989</reset><i>\u9B8\u9C1</i>
+ <reset>\u9B8\u9CD\u98A</reset><i>\u9B8\u9C2</i>
+ <reset>\u9B8\u9CD\u98B</reset><i>\u9B8\u9C3</i>
+ <reset>\u9B8\u9CD\u9E0</reset><i>\u9B8\u9C4</i>
+ <reset>\u9B8\u9CD\u98C</reset><i>\u9B8\u9E2</i>
+ <reset>\u9B8\u9CD\u9E1</reset><i>\u9B8\u9E3</i>
+ <reset>\u9B8\u9CD\u98F</reset><i>\u9B8\u9C7</i>
+ <reset>\u9B8\u9CD\u990</reset><i>\u9B8\u9C8</i>
+ <reset>\u9B8\u9CD\u993</reset><i>\u9B8\u9CB</i>
+ <reset>\u9B8\u9CD\u994</reset><i>\u9B8\u9CC</i>
+
+ <reset>\u9B9\u9CD\u985</reset><i>\u9B9</i>
+ <reset>\u9B9\u9CD\u986</reset><i>\u9B9\u9BE</i>
+ <reset>\u9B9\u9CD\u987</reset><i>\u9B9\u9BF</i>
+ <reset>\u9B9\u9CD\u988</reset><i>\u9B9\u9C0</i>
+ <reset>\u9B9\u9CD\u989</reset><i>\u9B9\u9C1</i>
+ <reset>\u9B9\u9CD\u98A</reset><i>\u9B9\u9C2</i>
+ <reset>\u9B9\u9CD\u98B</reset><i>\u9B9\u9C3</i>
+ <reset>\u9B9\u9CD\u9E0</reset><i>\u9B9\u9C4</i>
+ <reset>\u9B9\u9CD\u98C</reset><i>\u9B9\u9E2</i>
+ <reset>\u9B9\u9CD\u9E1</reset><i>\u9B9\u9E3</i>
+ <reset>\u9B9\u9CD\u98F</reset><i>\u9B9\u9C7</i>
+ <reset>\u9B9\u9CD\u990</reset><i>\u9B9\u9C8</i>
+ <reset>\u9B9\u9CD\u993</reset><i>\u9B9\u9CB</i>
+ <reset>\u9B9\u9CD\u994</reset><i>\u9B9\u9CC</i>
+
+ <reset>\u995</reset><t>\u995\u9BC</t>
+ <reset>\u995\u9BE</reset><t>\u995\u9BC\u9BE</t>
+ <reset>\u995\u9BF</reset><t>\u995\u9BC\u9BF</t>
+ <reset>\u995\u9C0</reset><t>\u995\u9BC\u9C0</t>
+ <reset>\u995\u9C1</reset><t>\u995\u9BC\u9C1</t>
+ <reset>\u995\u9C2</reset><t>\u995\u9BC\u9C2</t>
+ <reset>\u995\u9C3</reset><t>\u995\u9BC\u9C3</t>
+ <reset>\u995\u9C4</reset><t>\u995\u9BC\u9C4</t>
+ <reset>\u995\u9E2</reset><t>\u995\u9BC\u9E2</t>
+ <reset>\u995\u9E3</reset><t>\u995\u9BC\u9E3</t>
+ <reset>\u995\u9C7</reset><t>\u995\u9BC\u9C7</t>
+ <reset>\u995\u9C8</reset><t>\u995\u9BC\u9C8</t>
+ <reset>\u995\u9CB</reset><t>\u995\u9BC\u9CB</t>
+ <reset>\u995\u9CC</reset><t>\u995\u9BC\u9CC</t>
+ <reset>\u995\u9CD</reset><t>\u995\u9BC\u9CD</t>
+
+ <reset>\u996</reset><t>\u996\u9BC</t>
+ <reset>\u996\u9BE</reset><t>\u996\u9BC\u9BE</t>
+ <reset>\u996\u9BF</reset><t>\u996\u9BC\u9BF</t>
+ <reset>\u996\u9C0</reset><t>\u996\u9BC\u9C0</t>
+ <reset>\u996\u9C1</reset><t>\u996\u9BC\u9C1</t>
+ <reset>\u996\u9C2</reset><t>\u996\u9BC\u9C2</t>
+ <reset>\u996\u9C3</reset><t>\u996\u9BC\u9C3</t>
+ <reset>\u996\u9C4</reset><t>\u996\u9BC\u9C4</t>
+ <reset>\u996\u9E2</reset><t>\u996\u9BC\u9E2</t>
+ <reset>\u996\u9E3</reset><t>\u996\u9BC\u9E3</t>
+ <reset>\u996\u9C7</reset><t>\u996\u9BC\u9C7</t>
+ <reset>\u996\u9C8</reset><t>\u996\u9BC\u9C8</t>
+ <reset>\u996\u9CB</reset><t>\u996\u9BC\u9CB</t>
+ <reset>\u996\u9CC</reset><t>\u996\u9BC\u9CC</t>
+ <reset>\u996\u9CD</reset><t>\u996\u9BC\u9CD</t>
+
+ <reset>\u997</reset><t>\u997\u9BC</t>
+ <reset>\u997\u9BE</reset><t>\u997\u9BC\u9BE</t>
+ <reset>\u997\u9BF</reset><t>\u997\u9BC\u9BF</t>
+ <reset>\u997\u9C0</reset><t>\u997\u9BC\u9C0</t>
+ <reset>\u997\u9C1</reset><t>\u997\u9BC\u9C1</t>
+ <reset>\u997\u9C2</reset><t>\u997\u9BC\u9C2</t>
+ <reset>\u997\u9C3</reset><t>\u997\u9BC\u9C3</t>
+ <reset>\u997\u9C4</reset><t>\u997\u9BC\u9C4</t>
+ <reset>\u997\u9E2</reset><t>\u997\u9BC\u9E2</t>
+ <reset>\u997\u9E3</reset><t>\u997\u9BC\u9E3</t>
+ <reset>\u997\u9C7</reset><t>\u997\u9BC\u9C7</t>
+ <reset>\u997\u9C8</reset><t>\u997\u9BC\u9C8</t>
+ <reset>\u997\u9CB</reset><t>\u997\u9BC\u9CB</t>
+ <reset>\u997\u9CC</reset><t>\u997\u9BC\u9CC</t>
+ <reset>\u997\u9CD</reset><t>\u997\u9BC\u9CD</t>
+
+ <reset>\u99C</reset><t>\u99C\u9BC</t>
+ <reset>\u99C\u9BE</reset><t>\u99C\u9BC\u9BE</t>
+ <reset>\u99C\u9BF</reset><t>\u99C\u9BC\u9BF</t>
+ <reset>\u99C\u9C0</reset><t>\u99C\u9BC\u9C0</t>
+ <reset>\u99C\u9C1</reset><t>\u99C\u9BC\u9C1</t>
+ <reset>\u99C\u9C2</reset><t>\u99C\u9BC\u9C2</t>
+ <reset>\u99C\u9C3</reset><t>\u99C\u9BC\u9C3</t>
+ <reset>\u99C\u9C4</reset><t>\u99C\u9BC\u9C4</t>
+ <reset>\u99C\u9E2</reset><t>\u99C\u9BC\u9E2</t>
+ <reset>\u99C\u9E3</reset><t>\u99C\u9BC\u9E3</t>
+ <reset>\u99C\u9C7</reset><t>\u99C\u9BC\u9C7</t>
+ <reset>\u99C\u9C8</reset><t>\u99C\u9BC\u9C8</t>
+ <reset>\u99C\u9CB</reset><t>\u99C\u9BC\u9CB</t>
+ <reset>\u99C\u9CC</reset><t>\u99C\u9BC\u9CC</t>
+ <reset>\u99C\u9CD</reset><t>\u99C\u9BC\u9CD</t>
+
+ <reset>\u9A1</reset><t>\u9A1\u9BC</t>
+ <reset>\u9A1\u9BE</reset><t>\u9A1\u9BC\u9BE</t>
+ <reset>\u9A1\u9BF</reset><t>\u9A1\u9BC\u9BF</t>
+ <reset>\u9A1\u9C0</reset><t>\u9A1\u9BC\u9C0</t>
+ <reset>\u9A1\u9C1</reset><t>\u9A1\u9BC\u9C1</t>
+ <reset>\u9A1\u9C2</reset><t>\u9A1\u9BC\u9C2</t>
+ <reset>\u9A1\u9C3</reset><t>\u9A1\u9BC\u9C3</t>
+ <reset>\u9A1\u9C4</reset><t>\u9A1\u9BC\u9C4</t>
+ <reset>\u9A1\u9E2</reset><t>\u9A1\u9BC\u9E2</t>
+ <reset>\u9A1\u9E3</reset><t>\u9A1\u9BC\u9E3</t>
+ <reset>\u9A1\u9C7</reset><t>\u9A1\u9BC\u9C7</t>
+ <reset>\u9A1\u9C8</reset><t>\u9A1\u9BC\u9C8</t>
+ <reset>\u9A1\u9CB</reset><t>\u9A1\u9BC\u9CB</t>
+ <reset>\u9A1\u9CC</reset><t>\u9A1\u9BC\u9CC</t>
+ <reset>\u9A1\u9CD</reset><t>\u9A1\u9BC\u9CD</t>
+
+ <reset>\u9A2</reset><t>\u9A2\u9BC</t>
+ <reset>\u9A2\u9BE</reset><t>\u9A2\u9BC\u9BE</t>
+ <reset>\u9A2\u9BF</reset><t>\u9A2\u9BC\u9BF</t>
+ <reset>\u9A2\u9C0</reset><t>\u9A2\u9BC\u9C0</t>
+ <reset>\u9A2\u9C1</reset><t>\u9A2\u9BC\u9C1</t>
+ <reset>\u9A2\u9C2</reset><t>\u9A2\u9BC\u9C2</t>
+ <reset>\u9A2\u9C3</reset><t>\u9A2\u9BC\u9C3</t>
+ <reset>\u9A2\u9C4</reset><t>\u9A2\u9BC\u9C4</t>
+ <reset>\u9A2\u9E2</reset><t>\u9A2\u9BC\u9E2</t>
+ <reset>\u9A2\u9E3</reset><t>\u9A2\u9BC\u9E3</t>
+ <reset>\u9A2\u9C7</reset><t>\u9A2\u9BC\u9C7</t>
+ <reset>\u9A2\u9C8</reset><t>\u9A2\u9BC\u9C8</t>
+ <reset>\u9A2\u9CB</reset><t>\u9A2\u9BC\u9CB</t>
+ <reset>\u9A2\u9CC</reset><t>\u9A2\u9BC\u9CC</t>
+ <reset>\u9A2\u9CD</reset><t>\u9A2\u9BC\u9CD</t>
+
+ <reset>\u9AB</reset><t>\u9AB\u9BC</t>
+ <reset>\u9AB\u9BE</reset><t>\u9AB\u9BC\u9BE</t>
+ <reset>\u9AB\u9BF</reset><t>\u9AB\u9BC\u9BF</t>
+ <reset>\u9AB\u9C0</reset><t>\u9AB\u9BC\u9C0</t>
+ <reset>\u9AB\u9C1</reset><t>\u9AB\u9BC\u9C1</t>
+ <reset>\u9AB\u9C2</reset><t>\u9AB\u9BC\u9C2</t>
+ <reset>\u9AB\u9C3</reset><t>\u9AB\u9BC\u9C3</t>
+ <reset>\u9AB\u9C4</reset><t>\u9AB\u9BC\u9C4</t>
+ <reset>\u9AB\u9E2</reset><t>\u9AB\u9BC\u9E2</t>
+ <reset>\u9AB\u9E3</reset><t>\u9AB\u9BC\u9E3</t>
+ <reset>\u9AB\u9C7</reset><t>\u9AB\u9BC\u9C7</t>
+ <reset>\u9AB\u9C8</reset><t>\u9AB\u9BC\u9C8</t>
+ <reset>\u9AB\u9CB</reset><t>\u9AB\u9BC\u9CB</t>
+ <reset>\u9AB\u9CC</reset><t>\u9AB\u9BC\u9CC</t>
+ <reset>\u9AB\u9CD</reset><t>\u9AB\u9BC\u9CD</t>
+
+ <reset>\u9AC</reset><t>\u9AC\u9BC</t>
+ <reset>\u9AC\u9BE</reset><t>\u9AC\u9BC\u9BE</t>
+ <reset>\u9AC\u9BF</reset><t>\u9AC\u9BC\u9BF</t>
+ <reset>\u9AC\u9C0</reset><t>\u9AC\u9BC\u9C0</t>
+ <reset>\u9AC\u9C1</reset><t>\u9AC\u9BC\u9C1</t>
+ <reset>\u9AC\u9C2</reset><t>\u9AC\u9BC\u9C2</t>
+ <reset>\u9AC\u9C3</reset><t>\u9AC\u9BC\u9C3</t>
+ <reset>\u9AC\u9C4</reset><t>\u9AC\u9BC\u9C4</t>
+ <reset>\u9AC\u9E2</reset><t>\u9AC\u9BC\u9E2</t>
+ <reset>\u9AC\u9E3</reset><t>\u9AC\u9BC\u9E3</t>
+ <reset>\u9AC\u9C7</reset><t>\u9AC\u9BC\u9C7</t>
+ <reset>\u9AC\u9C8</reset><t>\u9AC\u9BC\u9C8</t>
+ <reset>\u9AC\u9CB</reset><t>\u9AC\u9BC\u9CB</t>
+ <reset>\u9AC\u9CC</reset><t>\u9AC\u9BC\u9CC</t>
+ <reset>\u9AC\u9CD</reset><t>\u9AC\u9BC\u9CD</t>
+
+ <reset>\u9AF</reset><t>\u9AF\u9BC</t>
+ <reset>\u9AF\u9BE</reset><t>\u9AF\u9BC\u9BE</t>
+ <reset>\u9AF\u9BF</reset><t>\u9AF\u9BC\u9BF</t>
+ <reset>\u9AF\u9C0</reset><t>\u9AF\u9BC\u9C0</t>
+ <reset>\u9AF\u9C1</reset><t>\u9AF\u9BC\u9C1</t>
+ <reset>\u9AF\u9C2</reset><t>\u9AF\u9BC\u9C2</t>
+ <reset>\u9AF\u9C3</reset><t>\u9AF\u9BC\u9C3</t>
+ <reset>\u9AF\u9C4</reset><t>\u9AF\u9BC\u9C4</t>
+ <reset>\u9AF\u9E2</reset><t>\u9AF\u9BC\u9E2</t>
+ <reset>\u9AF\u9E3</reset><t>\u9AF\u9BC\u9E3</t>
+ <reset>\u9AF\u9C7</reset><t>\u9AF\u9BC\u9C7</t>
+ <reset>\u9AF\u9C8</reset><t>\u9AF\u9BC\u9C8</t>
+ <reset>\u9AF\u9CB</reset><t>\u9AF\u9BC\u9CB</t>
+ <reset>\u9AF\u9CC</reset><t>\u9AF\u9BC\u9CC</t>
+ <reset>\u9AF\u9CD</reset><t>\u9AF\u9BC\u9CD</t>
+ </rules>
+ </collation>
+
+ </charset>
+
</charsets>
=== modified file 'mysql-test/t/ctype_ldml.test'
--- a/mysql-test/t/ctype_ldml.test 2010-06-25 12:00:49 +0000
+++ b/mysql-test/t/ctype_ldml.test 2010-12-20 08:30:44 +0000
@@ -210,3 +210,142 @@ SELECT hex(@a:=convert(_utf32 0x10400 us
SELECT hex(@a:=convert(_utf32 0x10428 using utf8mb4) collate utf8mb4_test_400_ci), hex(upper(@a));
SELECT hex(@a:=convert(_utf32 0x2C00 using utf8mb4) collate utf8mb4_test_400_ci), hex(lower(@a));
SELECT hex(@a:=convert(_utf32 0x2C30 using utf8mb4) collate utf8mb4_test_400_ci), hex(upper(@a));
+
+--echo #
+--echo # WL#5624 Collation customization improvements
+--echo #
+SET NAMES utf8 COLLATE utf8_5624_1;
+CREATE TABLE t1 AS SELECT REPEAT(' ', 16) AS a LIMIT 0;
+# Part 1,2,3: long contractions and expansions
+# Part 7: Quarternary difference
+INSERT INTO t1 VALUES ('012345'),('001234'),('000123'),('000012'),('000001');
+INSERT INTO t1 VALUES ('12345'),('01234'),('00123'),('00012'),('00001');
+INSERT INTO t1 VALUES ('1234'),('0123'),('0012'),('0001');
+INSERT INTO t1 VALUES ('123'),('012'),('001');
+INSERT INTO t1 VALUES ('12'),('01');
+INSERT INTO t1 VALUES ('1'),('9');
+INSERT INTO t1 VALUES ('ГАИ'),('ГИБДД');
+# Part 4: reset before
+# Part 6: characters rather than escape sequences
+INSERT INTO t1 VALUES ('a'),('b'),('c'),('d'),('e');
+INSERT INTO t1 VALUES ('cz'),('Ċ'),('ċ');
+INSERT INTO t1 VALUES ('f'),('fz'),('g'),('Ġ'),('ġ');
+INSERT INTO t1 VALUES ('h'),('hz'),('GĦ'),('Għ'),('gĦ'),('għ');
+INSERT INTO t1 VALUES ('i'),('iz'),('Ħ'),('ħ');
+INSERT INTO t1 VALUES ('y'),('yz'),('z'),('Ż'),('ż');
+INSERT INTO t1 VALUES ('ā'),('Ā'),('á'),('Á'),('à'),('À');
+INSERT INTO t1 VALUES ('ē'),('é'),('ě'),('ê'),('Ē'),('É'),('Ě'),('Ê');
+# Part 8: Abbreviated shift syntax
+INSERT INTO t1 VALUES ('a'),('~'),('!'),('@'),('#'),('$'),('%'),('^');
+INSERT INTO t1 VALUES ('('),(')'),('-'),('+'),('|'),('='),(':'),(';');
+INSERT INTO t1 VALUES ('"'),('\''),('?');
+# Part 9: Normal expansion syntax
+INSERT INTO t1 VALUES ('ch'),('k'),('cs'),('ccs'),('cscs');
+# Part 10: Previous context
+INSERT INTO t1 VALUES ('aa-'),('ab-'),('ac-'),('ad-'),('ae-'),('af-'),('az-');
+# Part 12: Logical reset positions
+INSERT INTO t1 VALUES ('lp-fni'),('lp-lni');
+INSERT INTO t1 VALUES ('lp-fpi'),('lp-lpi');
+INSERT INTO t1 VALUES ('lp-fsi'),('lp-lsi');
+INSERT INTO t1 VALUES ('lp-fti'),('lp-lti');
+INSERT INTO t1 VALUES ('lp-ft'),('lp-lt');
+INSERT INTO t1 VALUES ('lp-fv'),('lp-lv');
+# Logical positions with reset before
+INSERT INTO t1 VALUES ('lb-fni'),('lb-lni');
+INSERT INTO t1 VALUES ('lb-fv'),('lb-lv');
+# Part 5: Long tailoring
+INSERT INTO t1 VALUES (_ucs2 0x3106),(_ucs2 0x3110), (_ucs2 0x3111), (_ucs2 0x3112);
+INSERT INTO t1 VALUES (_ucs2 0x32A3), (_ucs2 0x3231);
+INSERT INTO t1 VALUES (_ucs2 0x84D9), (_ucs2 0x98F5), (_ucs2 0x7CF3), (_ucs2 0x5497);
+SELECT a, HEX(WEIGHT_STRING(a)) FROM t1 ORDER BY a, LENGTH(a), BINARY a;
+--echo #
+--echo # WL#5624, the same test with UCS2
+--echo #
+ALTER TABLE t1 CONVERT TO CHARACTER SET ucs2 COLLATE ucs2_5624_1;
+SELECT a, HEX(WEIGHT_STRING(a)) FROM t1 ORDER BY a, LENGTH(a), BINARY(a);
+DROP TABLE t1;
+
+--echo #
+--echo # WL#5624, unsupported features
+--echo #
+# Part 13: More verbosity
+--error ER_UNKNOWN_COLLATION
+SET NAMES utf8 COLLATE utf8_5624_2;
+SHOW WARNINGS;
+
+--echo #
+--echo # WL#5624, reset before primary ignorable
+--echo #
+--error ER_UNKNOWN_COLLATION
+SET NAMES utf8 COLLATE utf8_5624_3;
+SHOW WARNINGS;
+
+--echo #
+--echo # WL#5624, \u without hex digits is equal to {'\\', 'u'}
+--echo #
+SET NAMES utf8 COLLATE utf8_5624_4;
+CREATE TABLE t1 AS SELECT REPEAT(' ', 10) AS a LIMIT 0;
+INSERT INTO t1 VALUES ('\\'),('u'),('x'),('X');
+SELECT a, HEX(WEIGHT_STRING(a)) FROM t1 ORDER BY a, LENGTH(a), BINARY(a);
+DROP TABLE t1;
+
+--echo #
+--echo # WL#5624, testing Bengali collations
+--echo #
+SET NAMES utf8, collation_connection=utf8_bengali_standard_ci;
+CREATE TABLE t1 AS SELECT REPEAT (' ', 10) AS a LIMIT 0;
+INSERT INTO t1 VALUES (_ucs2 0x09FA), (_ucs2 0x09F8), (_ucs2 0x09F9), (_ucs2 0x09F2);
+INSERT INTO t1 VALUES (_ucs2 0x09DC), (_ucs2 0x09A109BC);
+INSERT INTO t1 VALUES (_ucs2 0x09A2), (_ucs2 0x09DD), (_ucs2 0x09A209BC);
+INSERT INTO t1 VALUES (_ucs2 0x09A3);
+SELECT HEX(WEIGHT_STRING(a)), HEX(CONVERT(a USING ucs2)), HEX(a)
+FROM t1 ORDER BY a, BINARY a;
+DROP TABLE t1;
+
+SET NAMES utf8, collation_connection=utf8_bengali_traditional_ci;
+CREATE TABLE t1 AS SELECT REPEAT (' ', 10) AS a LIMIT 0;
+INSERT INTO t1 VALUES
+(_ucs2 0x0985),(_ucs2 0x0986),(_ucs2 0x0987),(_ucs2 0x0988),
+(_ucs2 0x0989),(_ucs2 0x098A),(_ucs2 0x098B),(_ucs2 0x09E0),
+(_ucs2 0x098C),(_ucs2 0x09E1),(_ucs2 0x098F),(_ucs2 0x0990),
+(_ucs2 0x0993);
+
+INSERT INTO t1 VALUES
+(_ucs2 0x0994),(_ucs2 0x0982),(_ucs2 0x0983),(_ucs2 0x0981),
+(_ucs2 0x099509CD), (_ucs2 0x099609CD), (_ucs2 0x099709CD), (_ucs2 0x099809CD),
+(_ucs2 0x099909CD), (_ucs2 0x099A09CD), (_ucs2 0x099B09CD), (_ucs2 0x099C09CD),
+(_ucs2 0x099D09CD), (_ucs2 0x099E09CD), (_ucs2 0x099F09CD), (_ucs2 0x09A009CD),
+(_ucs2 0x09A109CD), (_ucs2 0x09A209CD), (_ucs2 0x09A309CD),
+(_ucs2 0x09CE), (_ucs2 0x09A409CD200D), (_ucs2 0x09A409CD),
+(_ucs2 0x09A509CD),(_ucs2 0x09A609CD),
+(_ucs2 0x09A709CD), (_ucs2 0x09A809CD), (_ucs2 0x09AA09CD), (_ucs2 0x09AB09CD),
+(_ucs2 0x09AC09CD), (_ucs2 0x09AD09CD), (_ucs2 0x09AE09CD), (_ucs2 0x09AF09CD),
+(_ucs2 0x09B009CD), (_ucs2 0x09F009CD), (_ucs2 0x09B209CD), (_ucs2 0x09F109CD),
+(_ucs2 0x09B609CD), (_ucs2 0x09B709CD), (_ucs2 0x09B809CD), (_ucs2 0x09B909CD);
+
+INSERT INTO t1 VALUES
+ (_ucs2 0x099509CD0985),(_ucs2 0x0995),
+ (_ucs2 0x099509CD0986),(_ucs2 0x099509BE),
+ (_ucs2 0x099509CD0987),(_ucs2 0x099509BF),
+ (_ucs2 0x099509CD0988),(_ucs2 0x099509C0),
+ (_ucs2 0x099509CD0989),(_ucs2 0x099509C1),
+ (_ucs2 0x099509CD098A),(_ucs2 0x099509C2),
+ (_ucs2 0x099509CD098B),(_ucs2 0x099509C3),
+ (_ucs2 0x099509CD09E0),(_ucs2 0x099509C4),
+ (_ucs2 0x099509CD098C),(_ucs2 0x099509E2),
+ (_ucs2 0x099509CD09E1),(_ucs2 0x099509E3),
+ (_ucs2 0x099509CD098F),(_ucs2 0x099509C7),
+ (_ucs2 0x099509CD0990),(_ucs2 0x099509C8),
+ (_ucs2 0x099509CD0993),(_ucs2 0x099509CB),
+ (_ucs2 0x099509CD0994),(_ucs2 0x099509CC);
+
+SELECT HEX(WEIGHT_STRING(a)), HEX(CONVERT(a USING ucs2)), HEX(a)
+FROM t1 ORDER BY a, BINARY(a);
+SELECT HEX(WEIGHT_STRING(a)) as wa,
+GROUP_CONCAT(HEX(CONVERT(a USING ucs2)) ORDER BY LENGTH(a), BINARY a)
+FROM t1 GROUP BY a ORDER BY a;
+DROP TABLE t1;
+
+--echo #
+--echo # End of WL#5624
+--echo #
=== modified file 'mysys/charset.c'
--- a/mysys/charset.c 2010-07-23 12:50:04 +0000
+++ b/mysys/charset.c 2010-12-20 08:30:44 +0000
@@ -352,19 +352,70 @@ static int add_collation(CHARSET_INFO *c
}
+/**
+ Report character set initialization errors and warnings.
+ Be silent by default: no warnings on the client side.
+*/
+static void
+default_reporter(enum loglevel level __attribute__ ((unused)),
+ const char *format __attribute__ ((unused)),
+ ...)
+{
+}
+my_error_reporter my_charset_error_reporter= default_reporter;
+
+
+/**
+ Wrappers for memory functions my_malloc (and friends)
+ with C-compatbile API without extra "myf" argument.
+*/
+static void *
+my_once_alloc_c(size_t size)
+{ return my_once_alloc(size, MYF(MY_WME)); }
+
+
+static void *
+my_malloc_c(size_t size)
+{ return my_malloc(size, MYF(MY_WME)); }
+
+
+static void *
+my_realloc_c(void *old, size_t size)
+{ return my_realloc(old, size, MYF(MY_WME)); }
+
+
+/**
+ Initialize character set loader to use mysys memory management functions.
+ @param loader Loader to initialize
+*/
+void
+my_charset_loader_init_mysys(MY_CHARSET_LOADER *loader)
+{
+ loader->error[0]= '\0';
+ loader->once_alloc= my_once_alloc_c;
+ loader->malloc= my_malloc_c;
+ loader->realloc= my_realloc_c;
+ loader->free= my_free;
+ loader->reporter= my_charset_error_reporter;
+ loader->add_collation= add_collation;
+}
+
+
#define MY_MAX_ALLOWED_BUF 1024*1024
#define MY_CHARSET_INDEX "Index.xml"
const char *charsets_dir= NULL;
-static my_bool my_read_charset_file(const char *filename, myf myflags)
+static my_bool
+my_read_charset_file(MY_CHARSET_LOADER *loader,
+ const char *filename,
+ myf myflags)
{
uchar *buf;
int fd;
size_t len, tmp_len;
MY_STAT stat_info;
- char error[128];
if (!my_stat(filename, &stat_info, MYF(myflags)) ||
((len= (uint)stat_info.st_size) > MY_MAX_ALLOWED_BUF) ||
@@ -378,11 +429,10 @@ static my_bool my_read_charset_file(cons
if (tmp_len != len)
goto error;
- if (my_parse_charset_xml((char *) buf,len,add_collation,
- error, sizeof(error)))
+ if (my_parse_charset_xml(loader, (char *) buf, len))
{
my_printf_error(EE_UNKNOWN_CHARSET, "Error while parsing '%s': %s\n",
- MYF(0), filename, error);
+ MYF(0), filename, loader->error);
goto error;
}
@@ -426,11 +476,6 @@ void add_compiled_collation(CHARSET_INFO
cs->state|= MY_CS_AVAILABLE;
}
-static void *cs_alloc(size_t size)
-{
- return my_once_alloc(size, MYF(MY_WME));
-}
-
static my_pthread_once_t charsets_initialized= MY_PTHREAD_ONCE_INIT;
static my_pthread_once_t charsets_template= MY_PTHREAD_ONCE_INIT;
@@ -439,6 +484,7 @@ static void init_available_charsets(void
{
char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
CHARSET_INFO **cs;
+ MY_CHARSET_LOADER loader;
bzero(&all_charsets,sizeof(all_charsets));
init_compiled_charsets(MYF(0));
@@ -456,8 +502,9 @@ static void init_available_charsets(void
}
}
+ my_charset_loader_init_mysys(&loader);
strmov(get_charsets_dir(fname), MY_CHARSET_INDEX);
- my_read_charset_file(fname, MYF(0));
+ my_read_charset_file(&loader, fname, MYF(0));
}
@@ -543,7 +590,8 @@ const char *get_charset_name(uint charse
}
-static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
+static CHARSET_INFO *
+get_internal_charset(MY_CHARSET_LOADER *loader, uint cs_number, myf flags)
{
char buf[FN_REFLEN];
CHARSET_INFO *cs;
@@ -561,21 +609,19 @@ static CHARSET_INFO *get_internal_charse
if (!(cs->state & (MY_CS_COMPILED|MY_CS_LOADED))) /* if CS is not in memory */
{
+ MY_CHARSET_LOADER loader;
strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS);
- my_read_charset_file(buf,flags);
+ my_charset_loader_init_mysys(&loader);
+ my_read_charset_file(&loader, buf, flags);
}
if (cs->state & MY_CS_AVAILABLE)
{
if (!(cs->state & MY_CS_READY))
{
- char err[128];
- if ((cs->cset->init && cs->cset->init(cs, cs_alloc, err, sizeof(err))) ||
- (cs->coll->init && cs->coll->init(cs, cs_alloc, err, sizeof(err))))
+ if ((cs->cset->init && cs->cset->init(cs, loader)) ||
+ (cs->coll->init && cs->coll->init(cs, loader)))
{
- my_printf_error(EE_UNKNOWN_CHARSET,
- "Error while initializing '%s': %s", MYF(0),
- cs->name, err);
cs= NULL;
}
else
@@ -594,6 +640,8 @@ static CHARSET_INFO *get_internal_charse
CHARSET_INFO *get_charset(uint cs_number, myf flags)
{
CHARSET_INFO *cs;
+ MY_CHARSET_LOADER loader;
+
if (cs_number == default_charset_info->number)
return default_charset_info;
@@ -601,8 +649,9 @@ CHARSET_INFO *get_charset(uint cs_number
if (!cs_number || cs_number > array_elements(all_charsets))
return NULL;
-
- cs=get_internal_charset(cs_number, flags);
+
+ my_charset_loader_init_mysys(&loader);
+ cs= get_internal_charset(&loader, cs_number, flags);
if (!cs && (flags & MY_WME))
{
@@ -615,29 +664,58 @@ CHARSET_INFO *get_charset(uint cs_number
return cs;
}
-CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags)
+
+/**
+ Find collation by name: extended version of get_charset_by_name()
+ to return error messages to the caller.
+ @param loader Character set loader
+ @param name Collation name
+ @param flags Flags
+ @return NULL on error, pointer to collation on success
+*/
+
+CHARSET_INFO *
+my_collation_get_by_name(MY_CHARSET_LOADER *loader,
+ const char *name, myf flags)
{
uint cs_number;
CHARSET_INFO *cs;
my_pthread_once(&charsets_initialized, init_available_charsets);
- cs_number=get_collation_number(cs_name);
- cs= cs_number ? get_internal_charset(cs_number,flags) : NULL;
+ cs_number= get_collation_number(name);
+ my_charset_loader_init_mysys(loader);
+ cs= cs_number ? get_internal_charset(loader, cs_number, flags) : NULL;
if (!cs && (flags & MY_WME))
{
char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX);
- my_error(EE_UNKNOWN_COLLATION, MYF(ME_BELL), cs_name, index_file);
+ my_error(EE_UNKNOWN_COLLATION, MYF(ME_BELL), name, index_file);
}
-
return cs;
}
-CHARSET_INFO *get_charset_by_csname(const char *cs_name,
- uint cs_flags,
- myf flags)
+CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags)
+{
+ MY_CHARSET_LOADER loader;
+ my_charset_loader_init_mysys(&loader);
+ return my_collation_get_by_name(&loader, cs_name, flags);
+}
+
+
+/**
+ Find character set by name: extended version of get_charset_by_csname()
+ to return error messages to the caller.
+ @param loader Character set loader
+ @param name Collation name
+ @param cs_flags Character set flags (e.g. default or binary collation)
+ @param flags Flags
+ @return NULL on error, pointer to collation on success
+*/
+CHARSET_INFO *
+my_charset_get_by_name(MY_CHARSET_LOADER *loader,
+ const char *cs_name, uint cs_flags, myf flags)
{
uint cs_number;
CHARSET_INFO *cs;
@@ -647,7 +725,7 @@ CHARSET_INFO *get_charset_by_csname(cons
my_pthread_once(&charsets_initialized, init_available_charsets);
cs_number= get_charset_number(cs_name, cs_flags);
- cs= cs_number ? get_internal_charset(cs_number, flags) : NULL;
+ cs= cs_number ? get_internal_charset(loader, cs_number, flags) : NULL;
if (!cs && (flags & MY_WME))
{
@@ -660,6 +738,15 @@ CHARSET_INFO *get_charset_by_csname(cons
}
+CHARSET_INFO *
+get_charset_by_csname(const char *cs_name, uint cs_flags, myf flags)
+{
+ MY_CHARSET_LOADER loader;
+ my_charset_loader_init_mysys(&loader);
+ return my_charset_get_by_name(&loader, cs_name, cs_flags, flags);
+}
+
+
/**
Resolve character set by the character set name (utf8, latin1, ...).
=== modified file 'sql/item_strfunc.cc'
--- a/sql/item_strfunc.cc 2010-12-17 11:28:59 +0000
+++ b/sql/item_strfunc.cc 2010-12-20 08:30:44 +0000
@@ -3109,11 +3109,8 @@ void Item_func_set_collation::fix_length
MY_CS_BINSORT,MYF(0));
else
{
- if (!(set_collation= get_charset_by_name(colname,MYF(0))))
- {
- my_error(ER_UNKNOWN_COLLATION, MYF(0), colname);
+ if (!(set_collation= mysqld_collation_get_by_name(colname)))
return;
- }
}
if (!set_collation ||
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-12-17 11:28:59 +0000
+++ b/sql/mysqld.cc 2010-12-20 08:30:44 +0000
@@ -3409,6 +3409,8 @@ static int init_common_variables()
default_collation= get_charset_by_name(default_collation_name, MYF(0));
if (!default_collation)
{
+ buffered_logs.print();
+ buffered_logs.cleanup();
sql_print_error(ER_DEFAULT(ER_UNKNOWN_COLLATION), default_collation_name);
return 1;
}
@@ -4474,6 +4476,7 @@ int mysqld_main(int argc, char **argv)
*/
buffered_logs.init();
my_getopt_error_reporter= buffered_option_error_reporter;
+ my_charset_error_reporter= buffered_option_error_reporter;
ho_error= handle_options(&remaining_argc, &remaining_argv,
(my_option*)(all_early_options.buffer), NULL);
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-12-15 23:10:37 +0000
+++ b/sql/sql_class.h 2010-12-20 08:30:44 +0000
@@ -610,6 +610,35 @@ typedef struct system_status_var
void mark_transaction_to_rollback(THD *thd, bool all);
+
+/**
+ Get collation by name, send error to client on failure.
+ @param name Collation name
+ @param name_cs Character set of the name string
+ @return
+ @retval NULL on error
+ @retval Pointter to CHARSET_INFO with the given name on success
+*/
+inline CHARSET_INFO *
+mysqld_collation_get_by_name(const char *name,
+ CHARSET_INFO *name_cs= system_charset_info)
+{
+ CHARSET_INFO *cs;
+ MY_CHARSET_LOADER loader;
+ my_charset_loader_init_mysys(&loader);
+ if (!(cs= my_collation_get_by_name(&loader, name, MYF(0))))
+ {
+ ErrConvString err(name, name_cs);
+ my_error(ER_UNKNOWN_COLLATION, MYF(0), err.ptr());
+ if (loader.error[0])
+ push_warning_printf(current_thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_UNKNOWN_COLLATION, "%s", loader.error);
+ }
+ return cs;
+}
+
+
#ifdef MYSQL_SERVER
void free_tmp_table(THD *thd, TABLE *entry);
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2010-12-05 22:23:53 +0000
+++ b/sql/sql_yacc.yy 2010-12-20 08:30:44 +0000
@@ -5823,11 +5823,8 @@ old_or_new_charset_name_or_default:
collation_name:
ident_or_text
{
- if (!($$=get_charset_by_name($1.str,MYF(0))))
- {
- my_error(ER_UNKNOWN_COLLATION, MYF(0), $1.str);
+ if (!($$= mysqld_collation_get_by_name($1.str)))
MYSQL_YYABORT;
- }
}
;
@@ -5871,19 +5868,13 @@ unicode:
}
| UNICODE_SYM BINARY
{
- if (!(Lex->charset=get_charset_by_name("ucs2_bin", MYF(0))))
- {
- my_error(ER_UNKNOWN_COLLATION, MYF(0), "ucs2_bin");
+ if (!(Lex->charset= mysqld_collation_get_by_name("ucs2_bin")))
MYSQL_YYABORT;
- }
}
| BINARY UNICODE_SYM
{
- if (!(Lex->charset=get_charset_by_name("ucs2_bin", MYF(0))))
- {
+ if (!(Lex->charset= mysqld_collation_get_by_name("ucs2_bin")))
my_error(ER_UNKNOWN_COLLATION, MYF(0), "ucs2_bin");
- MYSQL_YYABORT;
- }
}
;
=== modified file 'strings/CMakeLists.txt'
--- a/strings/CMakeLists.txt 2010-08-12 15:19:57 +0000
+++ b/strings/CMakeLists.txt 2010-12-20 08:30:44 +0000
@@ -31,3 +31,6 @@ ENDIF()
# Avoid dependencies on perschema data defined in mysys
ADD_DEFINITIONS(-DDISABLE_MYSQL_THREAD_H)
ADD_CONVENIENCE_LIBRARY(strings ${STRINGS_SOURCES})
+
+ADD_EXECUTABLE(conf_to_src EXCLUDE_FROM_ALL conf_to_src.c)
+TARGET_LINK_LIBRARIES(conf_to_src strings)
=== modified file 'strings/conf_to_src.c'
--- a/strings/conf_to_src.c 2010-06-25 12:00:49 +0000
+++ b/strings/conf_to_src.c 2010-12-20 08:30:44 +0000
@@ -144,12 +144,35 @@ static int add_collation(CHARSET_INFO *c
}
+static void
+default_reporter(enum loglevel level __attribute__ ((unused)),
+ const char *format __attribute__ ((unused)),
+ ...)
+{
+}
+
+
+static void
+my_charset_loader_init(MY_CHARSET_LOADER *loader)
+{
+ loader->error[0]= '\0';
+ loader->once_alloc= malloc;
+ loader->malloc= malloc;
+ loader->realloc= realloc;
+ loader->free= free;
+ loader->reporter= default_reporter;
+ loader->add_collation= add_collation;
+}
+
+
static int my_read_charset_file(const char *filename)
{
- char buf[MAX_BUF], error[128];
+ char buf[MAX_BUF];
int fd;
uint len;
+ MY_CHARSET_LOADER loader;
+ my_charset_loader_init(&loader);
if ((fd=open(filename,O_RDONLY)) < 0)
{
fprintf(stderr,"Can't open '%s'\n",filename);
@@ -160,9 +183,9 @@ static int my_read_charset_file(const ch
DBUG_ASSERT(len < MAX_BUF);
close(fd);
- if (my_parse_charset_xml(buf, len, add_collation, error, sizeof(error)))
+ if (my_parse_charset_xml(&loader, buf, len))
{
- fprintf(stderr, "Error while parsing '%s': %s\n", filename, error);
+ fprintf(stderr, "Error while parsing '%s': %s\n", filename, loader.error);
exit(1);
}
=== modified file 'strings/ctype-bin.c'
--- a/strings/ctype-bin.c 2010-06-25 12:00:49 +0000
+++ b/strings/ctype-bin.c 2010-12-20 08:30:44 +0000
@@ -69,9 +69,7 @@ static uchar bin_char_array[] =
static my_bool
my_coll_init_8bit_bin(CHARSET_INFO *cs,
- void *(*alloc)(size_t) __attribute__((unused)),
- char *error __attribute__((unused)),
- size_t errsize __attribute__((unused)))
+ MY_CHARSET_LOADER *loader __attribute__((unused)))
{
cs->max_sort_char=255;
return FALSE;
=== modified file 'strings/ctype-simple.c'
--- a/strings/ctype-simple.c 2010-07-23 20:59:42 +0000
+++ b/strings/ctype-simple.c 2010-12-20 08:30:44 +0000
@@ -1145,7 +1145,9 @@ static int pcmp(const void * f, const vo
return res;
}
-static my_bool create_fromuni(CHARSET_INFO *cs, void *(*alloc)(size_t))
+static my_bool
+create_fromuni(CHARSET_INFO *cs,
+ MY_CHARSET_LOADER *loader)
{
uni_idx idx[PLANE_NUM];
int i,n;
@@ -1195,7 +1197,9 @@ static my_bool create_fromuni(CHARSET_IN
break;
numchars=idx[i].uidx.to-idx[i].uidx.from+1;
- if (!(idx[i].uidx.tab=(uchar*) alloc(numchars * sizeof(*idx[i].uidx.tab))))
+ if (!(idx[i].uidx.tab= (uchar *)
+ (loader->once_alloc) (numchars *
+ sizeof(*idx[i].uidx.tab))))
return TRUE;
bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab));
@@ -1213,7 +1217,8 @@ static my_bool create_fromuni(CHARSET_IN
/* Allocate and fill reverse table for each plane */
n=i;
- if (!(cs->tab_from_uni= (MY_UNI_IDX*) alloc(sizeof(MY_UNI_IDX)*(n+1))))
+ if (!(cs->tab_from_uni= (MY_UNI_IDX *)
+ (loader->once_alloc)(sizeof(MY_UNI_IDX) * (n + 1))))
return TRUE;
for (i=0; i< n; i++)
@@ -1224,14 +1229,13 @@ static my_bool create_fromuni(CHARSET_IN
return FALSE;
}
-static my_bool my_cset_init_8bit(CHARSET_INFO *cs, void *(*alloc)(size_t),
- char *error __attribute__((unused)),
- size_t errsize __attribute__((unused)))
+static my_bool
+my_cset_init_8bit(CHARSET_INFO *cs, MY_CHARSET_LOADER *loader)
{
cs->caseup_multiply= 1;
cs->casedn_multiply= 1;
cs->pad_char= ' ';
- return create_fromuni(cs, alloc);
+ return create_fromuni(cs, loader);
}
static void set_max_sort_char(CHARSET_INFO *cs)
@@ -1253,10 +1257,9 @@ static void set_max_sort_char(CHARSET_IN
}
}
-static my_bool my_coll_init_simple(CHARSET_INFO *cs,
- void *(*alloc)(size_t) __attribute__((unused)),
- char *error __attribute__((unused)),
- size_t errsize __attribute__((unused)))
+static my_bool
+my_coll_init_simple(CHARSET_INFO *cs,
+ MY_CHARSET_LOADER *loader __attribute__((unused)))
{
set_max_sort_char(cs);
return FALSE;
=== modified file 'strings/ctype-uca.c'
--- a/strings/ctype-uca.c 2010-11-26 11:36:39 +0000
+++ b/strings/ctype-uca.c 2010-12-20 08:30:44 +0000
@@ -6531,7 +6531,26 @@ MY_UCA_INFO my_uca_v400=
0, /* nitems */
NULL, /* item */
NULL /* flags */
- }
+ },
+
+ /* Logical positions */
+ 0x0009, /* first_non_ignorable p != ignore */
+ 0xA48C, /* last_non_ignorable Not a CJK and not UNASSIGNED */
+
+ 0x0332, /* first_primary_ignorable p == 0 */
+ 0x20EA, /* last_primary_ignorable */
+
+ 0x0000, /* first_secondary_ignorable p,s == 0 */
+ 0xFE73, /* last_secondary_ignorable p,s == 0 */
+
+ 0x0000, /* first_tertiary_ignorable p,s,t == 0 */
+ 0xFE73, /* last_tertiary_ignorable p,s,t == 0 */
+
+ 0x0000, /* first_trailing */
+ 0x0000, /* last_trailing */
+
+ 0x0009, /* first_variable */
+ 0x2183, /* last_variable */
};
/******************************************************/
@@ -19084,7 +19103,25 @@ MY_UCA_INFO my_uca_v520=
0, /* nitems */
NULL, /* item */
NULL /* flags */
- }
+ },
+
+ 0x0009, /* first_non_ignorable p != ignore */
+ 0x1342E, /* last_non_ignorable Not a CJK and not UASSIGNED */
+
+ 0x0332, /* first_primary_ignorable p == ignore */
+ 0x101FD, /* last_primary_ignorable */
+
+ 0x0000, /* first_secondary_ignorable p,s= ignore */
+ 0xFE73, /* last_secondary_ignorable */
+
+ 0x0000, /* first_tertiary_ignorable p,s,t == ignore */
+ 0xFE73, /* last_tertiary_ignorable */
+
+ 0x0000, /* first_trailing */
+ 0x0000, /* last_trailing */
+
+ 0x0009, /* first_variable if alt=non-ignorable: p != ignore */
+ 0x1D371, /* last_variable if alt=shifter: p,s,t == ignore */
};
@@ -19259,7 +19296,13 @@ static const char persian[]=
"& \\u0642 < \\u06A9 < \\u0643"
"& \\u0648 < \\u0647 < \\u0629 < \\u06C0 < \\u06CC < \\u0649 < \\u064A"
"& \\uFE80 < \\uFE81 < \\uFE82 < \\uFE8D < \\uFE8E < \\uFB50 < \\uFB51"
- " < \\uFE80 < \\uFE83 < \\uFE84 < \\uFE87 < \\uFE88 < \\uFE85"
+ " < \\uFE80 "
+ /*
+ FE80 appears both in reset and shift.
+ We need to break the rule here and reset to *new* FE80 again,
+ so weight for FE83 is calculated as P[FE80]+1, not as P[FE80]+8.
+ */
+ " & \\uFE80 < \\uFE83 < \\uFE84 < \\uFE87 < \\uFE88 < \\uFE85"
" < \\uFE86 < \\u0689 < \\u068A"
"& \\uFEAE < \\uFDFC"
"& \\uFED8 < \\uFB8E < \\uFB8F < \\uFB90 < \\uFB91 < \\uFED9 < \\uFEDA"
@@ -19435,11 +19478,15 @@ static uint16 nochar[]= {0,0};
#define MY_UCA_CNT_FLAG_SIZE 4096
#define MY_UCA_CNT_FLAG_MASK 4095
-#define MY_UCA_CNT_HEAD 1
-#define MY_UCA_CNT_TAIL 2
-
-
+#define MY_UCA_CNT_HEAD 1
+#define MY_UCA_CNT_TAIL 2
+#define MY_UCA_CNT_MID1 4
+#define MY_UCA_CNT_MID2 8
+#define MY_UCA_CNT_MID3 16
+#define MY_UCA_CNT_MID4 32
+#define MY_UCA_PREVIOUS_CONTEXT_HEAD 64
+#define MY_UCA_PREVIOUS_CONTEXT_TAIL 128
/********** Helper functions to handle contraction ************/
@@ -19471,14 +19518,30 @@ my_uca_add_contraction_flag(MY_UCA_INFO
*/
static MY_CONTRACTION *
-my_uca_add_contraction(MY_UCA_INFO *uca,
- my_wc_t *wc, int len __attribute__((unused)))
+my_uca_add_contraction(MY_UCA_INFO *uca, my_wc_t *wc, size_t len,
+ my_bool with_context)
{
MY_CONTRACTIONS *list= &uca->contractions;
MY_CONTRACTION *next= &list->item[list->nitems];
- DBUG_ASSERT(len == 2); /* We currently support only contraction2 */
- next->ch[0]= wc[0];
- next->ch[1]= wc[1];
+ size_t i;
+ /*
+ Contraction is always at least 2 characters.
+ Contraction is never longer than MY_UCA_MAX_CONTRACTION,
+ which is guaranteed by using my_coll_rule_expand() with proper limit.
+ */
+ DBUG_ASSERT(len > 1 && len <= MY_UCA_MAX_CONTRACTION);
+ for (i= 0; i < len; i++)
+ {
+ /*
+ We don't support contractions with U+0000.
+ my_coll_rule_expand() guarantees there're no U+0000 in a contraction.
+ */
+ DBUG_ASSERT(wc[i] != 0);
+ next->ch[i]= wc[i];
+ }
+ if (i < MY_UCA_MAX_CONTRACTION)
+ next->ch[i]= 0; /* Add end-of-line marker */
+ next->with_context= with_context;
list->nitems++;
return next;
}
@@ -19497,11 +19560,12 @@ my_uca_add_contraction(MY_UCA_INFO *uca,
*/
static my_bool
-my_uca_alloc_contractions(MY_UCA_INFO *uca, void *(*alloc)(size_t), size_t n)
+my_uca_alloc_contractions(MY_UCA_INFO *uca,
+ MY_CHARSET_LOADER *loader, size_t n)
{
uint size= n * sizeof(MY_CONTRACTION);
- if (!(uca->contractions.item= (*alloc)(size)) ||
- !(uca->contractions.flags= (char *) (*alloc)(MY_UCA_CNT_FLAG_SIZE)))
+ if (!(uca->contractions.item= (loader->once_alloc)(size)) ||
+ !(uca->contractions.flags= (char *) (loader->once_alloc)(MY_UCA_CNT_FLAG_SIZE)))
return 1;
bzero((void *) uca->contractions.item, size);
bzero((void *) uca->contractions.flags, MY_UCA_CNT_FLAG_SIZE);
@@ -19578,12 +19642,29 @@ my_uca_can_be_contraction_tail(MY_UCA_IN
/**
+ Check if a character can be contraction part
+
+ @param uca Pointer to UCA data
+ @param wc Code point
+
+ @retval 0 - cannot be contraction part
+ @retval 1 - can be contraction part
+*/
+
+my_bool
+my_uca_can_be_contraction_part(MY_UCA_INFO *uca, my_wc_t wc, int flag)
+{
+ return uca->contractions.flags[wc & MY_UCA_CNT_FLAG_MASK] & flag;
+}
+
+
+/**
Find a contraction and return its weight array
-
+
@param uca Pointer to UCA data
@param wc1 First character
@param wc2 Second character
-
+
@return Weight array
@retval NULL - no contraction found
@retval ptr - contraction weight array
@@ -19594,9 +19675,9 @@ my_uca_contraction2_weight(MY_UCA_INFO *
{
MY_CONTRACTIONS *list= &uca->contractions;
MY_CONTRACTION *c, *last;
- for (c= list->item, last= &list->item[list->nitems]; c < last; c++)
+ for (c= list->item, last= c + list->nitems; c < last; c++)
{
- if (c->ch[0] == wc1 && c->ch[1] == wc2)
+ if (c->ch[0] == wc1 && c->ch[1] == wc2 && c->ch[2] == 0)
{
return c->weight;
}
@@ -19605,197 +19686,214 @@ my_uca_contraction2_weight(MY_UCA_INFO *
}
-/****************************************************************/
+/**
+ Check if a character can be previous context head
+
+ @param uca Pointer to UCA data
+ @param wc Code point
+
+ @return
+ @retval FALSE - cannot be previous context head
+ @retval TRUE - can be previous context head
+*/
+
+my_bool
+my_uca_can_be_previous_context_head(MY_UCA_INFO *uca, my_wc_t wc)
+{
+ return uca->contractions.flags[wc & MY_UCA_CNT_FLAG_MASK] &
+ MY_UCA_PREVIOUS_CONTEXT_HEAD;
+}
/**
- Return implicit UCA weight
- Used for characters that do not have assigned UCA weights.
-
- @param scanner UCA weight scanner
-
- @return The leading implicit weight.
+ Check if a character can be previois context tail
+
+ @param uca Pointer to UCA data
+ @param wc Code point
+
+ @return
+ @retval FALSE - cannot be contraction tail
+ @retval TRUE - can be contraction tail
*/
-static inline int
-my_uca_scanner_next_implicit(my_uca_scanner *scanner)
+my_bool
+my_uca_can_be_previous_context_tail(MY_UCA_INFO *uca, my_wc_t wc)
{
- scanner->code= (scanner->page << 8) + scanner->code;
- scanner->implicit[0]= (scanner->code & 0x7FFF) | 0x8000;
- scanner->implicit[1]= 0;
- scanner->wbeg= scanner->implicit;
-
- scanner->page= scanner->page >> 7;
-
- if (scanner->code >= 0x3400 && scanner->code <= 0x4DB5)
- scanner->page+= 0xFB80;
- else if (scanner->code >= 0x4E00 && scanner->code <= 0x9FA5)
- scanner->page+= 0xFB40;
- else
- scanner->page+= 0xFBC0;
-
- return scanner->page;
+ return uca->contractions.flags[wc & MY_UCA_CNT_FLAG_MASK] &
+ MY_UCA_PREVIOUS_CONTEXT_TAIL;
}
-#ifdef HAVE_CHARSET_ucs2
-/*
- Initialize collation weight scanner
+/**
+ Compare two wide character strings, wide analog to strncmp().
- SYNOPSIS:
- my_uca_scanner_init()
- scanner Pointer to an initialized scanner structure
- cs Character set + collation information
- str Beginning of the string
- length Length of the string.
-
- NOTES:
- Optimized for UCS2
+ @param a Pointer to the first string
+ @param b Pointer to the second string
+ @param len Length of the strings
+
+ @return
+ @retval 0 - strings are equal
+ @retval non-zero - strings are different
+*/
- RETURN
- N/A
+static int
+my_wmemcmp(my_wc_t *a, my_wc_t *b, size_t len)
+{
+ return memcmp(a, b, len * sizeof(my_wc_t));
+}
+
+
+/**
+ Check if a string is a contraction,
+ and return its weight array on success.
+
+ @param uca Pointer to UCA data
+ @param wc Pointer to wide string
+ @param len String length
+
+ @return Weight array
+ @retval NULL - Input string is not a known contraction
+ @retval ptr - contraction weight array
*/
-static void my_uca_scanner_init_ucs2(my_uca_scanner *scanner,
- CHARSET_INFO *cs,
- const uchar *str, size_t length)
+uint16 *
+my_uca_contraction_weight(MY_UCA_INFO *uca, my_wc_t *wc, size_t len)
{
- scanner->wbeg= nochar;
- if (length)
+ MY_CONTRACTIONS *list= &uca->contractions;
+ MY_CONTRACTION *c, *last;
+ for (c= list->item, last= c + list->nitems; c < last; c++)
{
- scanner->sbeg= str;
- scanner->send= str + length - 2;
- scanner->uca= cs->uca;
- return;
+ if ((len == MY_UCA_MAX_CONTRACTION || c->ch[len] == 0) &&
+ !c->with_context &&
+ !my_wmemcmp(c->ch, wc, len))
+ return c->weight;
}
-
- /*
- Sometimes this function is called with
- str=NULL and length=0, which should be
- considered as an empty string.
-
- The above initialization is unsafe for such cases,
- because scanner->send is initialized to (NULL-2), which is 0xFFFFFFFE.
- Then we fall into an endless loop in my_uca_scanner_next_ucs2().
-
- Do special initialization for the case when length=0.
- Initialize scanner->sbeg to an address greater than scanner->send.
- Next call of my_uca_scanner_next_ucs2() will correctly return with -1.
- */
- scanner->sbeg= (uchar*) &nochar[1];
- scanner->send= (uchar*) &nochar[0];
+ return NULL;
}
-/*
- Read next collation element (weight), i.e. converts
- a stream of characters into a stream of their weights.
-
- SYNOPSIS:
- my_uca_scanner_next()
- scanner Address of a previously initialized scanner strucuture
-
- NOTES:
- Optimized for UCS2
-
- Checks if the current character's weight string has been fully scanned,
- if no, then returns the next weight for this character,
- else scans the next character and returns its first weight.
+/**
+ Find a contraction in the input stream and return its weight array
- Each character can have number weights from 0 to 8.
-
- Some characters do not have weights at all, 0 weights.
- It means they are ignored during comparison.
-
- Examples:
- 1. 0x0001 START OF HEADING, has no weights, ignored, does
- not produce any weights.
- 2. 0x0061 LATIN SMALL LETTER A, has one weight.
- 0x0E33 will be returned
- 3. 0x00DF LATIN SMALL LETTER SHARP S, aka SZ ligature,
- has two weights. It will return 0x0FEA twice for two
- consequent calls.
- 4. 0x247D PATENTHESIZED NUMBER TEN, has four weights,
- this function will return these numbers in four
- consequent calls: 0x0288, 0x0E2A, 0x0E29, 0x0289
- 5. A string consisting of the above characters:
- 0x0001 0x0061 0x00DF 0x247D
- will return the following weights, one weight per call:
- 0x0E33 0x0FEA 0x0FEA 0x0288, 0x0E2A, 0x0E29, 0x0289
-
- RETURN
- Next weight, a number between 0x0000 and 0xFFFF
- Or -1 on error (END-OF-STRING or ILLEGAL MULTIBYTE SEQUENCE)
+ Scan input characters while their flags tell that they can be
+ a contraction part. Then try to find real contraction among the
+ candidates, starting from the longest.
+
+ @param scanner Pointer to UCA scanner
+ @param[OUT] *wc Where to store the scanned string
+
+ @return Weight array
+ @retval NULL - no contraction found
+ @retval ptr - contraction weight array
*/
-static int my_uca_scanner_next_ucs2(my_uca_scanner *scanner)
+static uint16 *
+my_uca_scanner_contraction_find(my_uca_scanner *scanner, my_wc_t *wc)
{
-
- /*
- Check if the weights for the previous character have been
- already fully scanned. If yes, then get the next character and
- initialize wbeg and wlength to its weight string.
- */
-
- if (scanner->wbeg[0])
- return *scanner->wbeg++;
-
- do
+ size_t clen= 1;
+ int flag;
+ const uchar *s, *beg[MY_UCA_MAX_CONTRACTION];
+
+ /* Scan all contraction candidates */
+ for (s= scanner->sbeg, flag= MY_UCA_CNT_MID1;
+ clen < MY_UCA_MAX_CONTRACTION;
+ flag<<= 1)
{
- uint16 *wpage;
-
- if (scanner->sbeg > scanner->send)
- return -1;
-
- scanner->page= (uchar)scanner->sbeg[0];
- scanner->code= (uchar)scanner->sbeg[1];
- scanner->sbeg+= 2;
-
- if (my_uca_have_contractions_quick(scanner->uca) &&
- (scanner->sbeg <= scanner->send))
+ int mblen;
+ if ((mblen= scanner->cs->cset->mb_wc(scanner->cs, &wc[clen],
+ s, scanner->send)) <= 0)
+ break;
+ beg[clen]= s= s + mblen;
+ if (!my_uca_can_be_contraction_part(scanner->uca, wc[clen++], flag))
+ break;
+ }
+
+ /* Find among candidates the longest real contraction */
+ for ( ; clen > 1; clen--)
+ {
+ uint16 *cweight;
+ if (my_uca_can_be_contraction_tail(scanner->uca, wc[clen - 1]) &&
+ (cweight= my_uca_contraction_weight(scanner->uca, wc, clen)))
{
- my_wc_t wc1= ((scanner->page << 8) | scanner->code);
-
- if (my_uca_can_be_contraction_head(scanner->uca, wc1))
- {
- uint16 *cweight;
- my_wc_t wc2= (((my_wc_t) scanner->sbeg[0]) << 8) | scanner->sbeg[1];
- if (my_uca_can_be_contraction_tail(scanner->uca, wc2) &&
- (cweight= my_uca_contraction2_weight(scanner->uca, wc1, wc2)))
- {
- scanner->implicit[0]= 0;
- scanner->wbeg= scanner->implicit;
- scanner->sbeg+=2;
- return *cweight;
- }
- }
+ scanner->wbeg= cweight + 1;
+ scanner->sbeg= beg[clen - 1];
+ return cweight;
}
-
- if (!(wpage= scanner->uca->weights[scanner->page]))
- return my_uca_scanner_next_implicit(scanner);
- scanner->wbeg= wpage +
- scanner->code * scanner->uca->lengths[scanner->page];
- } while (!scanner->wbeg[0]);
-
- return *scanner->wbeg++;
+ }
+
+ return NULL; /* No contractions were found */
}
-static my_uca_scanner_handler my_ucs2_uca_scanner_handler=
+/**
+ Find weight for contraction with previous context
+ and return its weight array.
+
+ @param scanner Pointer to UCA scanner
+ @param wc0 Previous character
+ @param wc1 Current character
+
+ @return Weight array
+ @retval NULL - no contraction with context found
+ @retval ptr - contraction weight array
+*/
+
+uint16 *
+my_uca_previous_context_find(my_uca_scanner *scanner,
+ my_wc_t wc0, my_wc_t wc1)
{
- my_uca_scanner_init_ucs2,
- my_uca_scanner_next_ucs2
-};
+ MY_CONTRACTIONS *list= &scanner->uca->contractions;
+ MY_CONTRACTION *c, *last;
+ for (c= list->item, last= c + list->nitems; c < last; c++)
+ {
+ if (c->with_context && wc0 == c->ch[0] && wc1 == c->ch[1])
+ {
+ scanner->wbeg= c->weight + 1;
+ return c->weight;
+ }
+ }
+ return NULL;
+}
-#endif
+/****************************************************************/
+
+
+/**
+ Return implicit UCA weight
+ Used for characters that do not have assigned UCA weights.
+
+ @param scanner UCA weight scanner
+
+ @return The leading implicit weight.
+*/
+
+static inline int
+my_uca_scanner_next_implicit(my_uca_scanner *scanner)
+{
+ scanner->code= (scanner->page << 8) + scanner->code;
+ scanner->implicit[0]= (scanner->code & 0x7FFF) | 0x8000;
+ scanner->implicit[1]= 0;
+ scanner->wbeg= scanner->implicit;
+
+ scanner->page= scanner->page >> 7;
+
+ if (scanner->code >= 0x3400 && scanner->code <= 0x4DB5)
+ scanner->page+= 0xFB80;
+ else if (scanner->code >= 0x4E00 && scanner->code <= 0x9FA5)
+ scanner->page+= 0xFB40;
+ else
+ scanner->page+= 0xFBC0;
+
+ return scanner->page;
+}
/*
The same two functions for any character set
*/
-static void my_uca_scanner_init_any(my_uca_scanner *scanner,
- CHARSET_INFO *cs __attribute__((unused)),
- const uchar *str, size_t length)
+static void
+my_uca_scanner_init_any(my_uca_scanner *scanner,
+ CHARSET_INFO *cs, const uchar *str, size_t length)
{
/* Note, no needs to initialize scanner->wbeg */
scanner->sbeg= str;
@@ -19807,66 +19905,78 @@ static void my_uca_scanner_init_any(my_u
static int my_uca_scanner_next_any(my_uca_scanner *scanner)
{
-
/*
Check if the weights for the previous character have been
already fully scanned. If yes, then get the next character and
initialize wbeg and wlength to its weight string.
*/
-
- if (scanner->wbeg[0])
- return *scanner->wbeg++;
-
- do
+
+ if (scanner->wbeg[0]) /* More weights left from the previous step: */
+ return *scanner->wbeg++; /* return the next weight from expansion */
+
+ do
{
uint16 *wpage;
- my_wc_t wc;
- int mb_len;
-
- if (((mb_len= scanner->cs->cset->mb_wc(scanner->cs, &wc,
+ my_wc_t wc[MY_UCA_MAX_CONTRACTION];
+ int mblen;
+
+ /* Get next character */
+ if (((mblen= scanner->cs->cset->mb_wc(scanner->cs, wc,
scanner->sbeg,
scanner->send)) <= 0))
return -1;
-
- scanner->sbeg+= mb_len;
- if (wc > scanner->uca->maxchar)
+
+ scanner->sbeg+= mblen;
+ if (wc[0] > scanner->uca->maxchar)
{
/* Return 0xFFFD as weight for all characters outside BMP */
scanner->wbeg= nochar;
return 0xFFFD;
}
- else
- {
- scanner->page= wc >> 8;
- scanner->code= wc & 0xFF;
- }
-
- if (my_uca_have_contractions_quick(scanner->uca) &&
- my_uca_can_be_contraction_head(scanner->uca, wc))
+
+ if (my_uca_have_contractions_quick(scanner->uca))
{
- my_wc_t wc2;
uint16 *cweight;
-
- if (((mb_len= scanner->cs->cset->mb_wc(scanner->cs, &wc2,
- scanner->sbeg,
- scanner->send)) >=0) &&
- my_uca_can_be_contraction_tail(scanner->uca, wc2) &&
- (cweight= my_uca_contraction2_weight(scanner->uca, wc, wc2)))
+ /*
+ If we have scanned a character which can have previous context,
+ and there were some more characters already before,
+ then reconstruct codepoint of the previous character
+ from "page" and "code" into w[1], and verify that {wc[1], wc[0]}
+ together form a real previous context pair.
+ Note, we support only 2-character long sequences with previous
+ context at the moment. CLDR does not have longer sequences.
+ */
+ if (my_uca_can_be_previous_context_tail(scanner->uca, wc[0]) &&
+ scanner->wbeg != nochar && /* if not the very first character */
+ my_uca_can_be_previous_context_head(scanner->uca,
+ (wc[1]= ((scanner->page << 8) +
+ scanner->code))) &&
+ (cweight= my_uca_previous_context_find(scanner, wc[1], wc[0])))
{
- scanner->implicit[0]= 0;
- scanner->wbeg= scanner->implicit;
- scanner->sbeg+= mb_len;
+ scanner->page= scanner->code= 0; /* Clear for the next character */
return *cweight;
}
+ else if (my_uca_can_be_contraction_head(scanner->uca, wc[0]))
+ {
+ /* Check if w[0] starts a contraction */
+ if ((cweight= my_uca_scanner_contraction_find(scanner, wc)))
+ return *cweight;
+ }
}
-
+
+ /* Process single character */
+ scanner->page= wc[0] >> 8;
+ scanner->code= wc[0] & 0xFF;
+
+ /* If weight page for w[0] does not exist, then calculate algoritmically */
if (!(wpage= scanner->uca->weights[scanner->page]))
return my_uca_scanner_next_implicit(scanner);
-
+
+ /* Calculate pointer to w[0]'s weight, using page and offset */
scanner->wbeg= wpage +
scanner->code * scanner->uca->lengths[scanner->page];
- } while (!scanner->wbeg[0]);
-
+ } while (!scanner->wbeg[0]); /* Skip ignorable characters */
+
return *scanner->wbeg++;
}
@@ -20420,17 +20530,47 @@ int my_wildcmp_uca(CHARSET_INFO *cs,
typedef enum my_coll_lexem_num_en
{
- MY_COLL_LEXEM_EOF = 0,
- MY_COLL_LEXEM_DIFF = 1,
- MY_COLL_LEXEM_SHIFT = 4,
- MY_COLL_LEXEM_CHAR = 5,
- MY_COLL_LEXEM_ERROR = 6,
+ MY_COLL_LEXEM_EOF = 0,
+ MY_COLL_LEXEM_SHIFT = 1,
+ MY_COLL_LEXEM_RESET = 4,
+ MY_COLL_LEXEM_CHAR = 5,
+ MY_COLL_LEXEM_ERROR = 6,
MY_COLL_LEXEM_OPTION = 7,
+ MY_COLL_LEXEM_EXTEND = 8,
+ MY_COLL_LEXEM_CONTEXT = 9,
} my_coll_lexem_num;
+/**
+ Convert collation customization lexem to string,
+ for nice error reporting
+
+ @param term lexem code
+
+ @return lexem name
+*/
+
+static const char *
+my_coll_lexem_num_to_str(my_coll_lexem_num term)
+{
+ switch (term)
+ {
+ case MY_COLL_LEXEM_EOF: return "EOF";
+ case MY_COLL_LEXEM_SHIFT: return "Shift";
+ case MY_COLL_LEXEM_RESET: return "&";
+ case MY_COLL_LEXEM_CHAR: return "Character";
+ case MY_COLL_LEXEM_OPTION: return "Bracket option";
+ case MY_COLL_LEXEM_EXTEND: return "/";
+ case MY_COLL_LEXEM_CONTEXT:return "|";
+ case MY_COLL_LEXEM_ERROR: return "ERROR";
+ }
+ return NULL;
+}
+
+
typedef struct my_coll_lexem_st
{
+ my_coll_lexem_num term;
const char *beg;
const char *end;
const char *prev;
@@ -20464,6 +20604,27 @@ static void my_coll_lexem_init(MY_COLL_L
}
+/**
+ Compare lexem to string with length
+
+ @param lexem lexem
+ @param pattern string
+ @param patternlen string length
+
+ @return
+ @retval 0 if lexem is equal to string, non-0 otherwise.
+*/
+
+static int
+lex_cmp(MY_COLL_LEXEM *lexem, const char *pattern, size_t patternlen)
+{
+ size_t lexemlen= lexem->beg - lexem->prev;
+ if (lexemlen < patternlen)
+ return 1; /* Not a prefix */
+ return strncasecmp(lexem->prev, pattern, patternlen);
+}
+
+
/*
Print collation customization expression parse error, with context.
@@ -20487,7 +20648,8 @@ static void my_coll_lexem_print_error(MY
size_t len= lexem->end - lexem->prev;
strmake (tail, lexem->prev, (size_t) min(len, sizeof(tail)-1));
errstr[errsize-1]= '\0';
- my_snprintf(errstr,errsize-1,"%s at '%s'", txt, tail);
+ my_snprintf(errstr, errsize - 1,
+ "%s at '%s'", txt[0] ? txt : "Syntax error", tail);
}
@@ -20538,57 +20700,75 @@ static my_coll_lexem_num my_coll_lexem_n
{
const char *beg;
my_coll_lexem_num rc;
-
+
for (beg= lexem->beg ; beg < lexem->end ; beg++)
{
- if (*beg == ' ' || *beg == '\t' || *beg == '\r' || *beg == '\n')
- continue;
-
- if (*beg == '[')
+ switch (*beg)
{
- if ((beg= (const char *) memchr(beg, ']', lexem->end - beg )))
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ continue;
+
+ case '[': /* Bracket expression, e.g. "[optimize [a-z]]" */
{
- rc= MY_COLL_LEXEM_OPTION;
- beg++;
- }
- else
+ size_t nbrackets; /* Indicates nested recursion level */
+ for (beg++, nbrackets= 1 ; beg < lexem->end; beg++)
+ {
+ if (*beg == '[') /* Enter nested bracket expression */
+ nbrackets++;
+ else if (*beg == ']')
+ {
+ if (--nbrackets == 0)
+ {
+ rc= MY_COLL_LEXEM_OPTION;
+ beg++;
+ goto ex;
+ }
+ }
+ }
rc= MY_COLL_LEXEM_ERROR;
+ goto ex;
+ }
+
+ case '&':
+ beg++;
+ rc= MY_COLL_LEXEM_RESET;
goto ex;
- }
-
- if (*beg == '&')
- {
+
+ case '=':
beg++;
+ lexem->diff= 0;
rc= MY_COLL_LEXEM_SHIFT;
goto ex;
- }
-
- if (beg[0] == '=')
- {
+
+ case '/':
beg++;
- lexem->diff= 0;
- rc= MY_COLL_LEXEM_DIFF;
- goto ex;
- }
-
- if (beg[0] == '<')
- {
- for (beg++, lexem->diff= 1;
- (beg < lexem->end) &&
- (*beg == '<') && (lexem->diff<3);
- beg++, lexem->diff++);
- rc= MY_COLL_LEXEM_DIFF;
+ rc= MY_COLL_LEXEM_EXTEND;
goto ex;
- }
-
- if ((*beg >= 'a' && *beg <= 'z') || (*beg >= 'A' && *beg <= 'Z'))
- {
- lexem->code= *beg++;
- rc= MY_COLL_LEXEM_CHAR;
+
+ case '|':
+ beg++;
+ rc= MY_COLL_LEXEM_CONTEXT;
goto ex;
+
+ case '<': /* Shift: '<' or '<<' or '<<<' or '<<<<' */
+ {
+ /* Scan up to 3 additional '<' characters */
+ for (beg++, lexem->diff= 1;
+ (beg < lexem->end) && (*beg == '<') && (lexem->diff <= 3);
+ beg++, lexem->diff++);
+ rc= MY_COLL_LEXEM_SHIFT;
+ goto ex;
+ }
+ default:
+ break;
}
-
- if ((*beg == '\\') && (beg+2 < lexem->end) && (beg[1] == 'u'))
+
+ /* Escaped character, e.g. \u1234 */
+ if ((*beg == '\\') && (beg + 2 < lexem->end) &&
+ (beg[1] == 'u') && my_isxdigit(&my_charset_utf8_general_ci, beg[2]))
{
int ch;
@@ -20602,204 +20782,856 @@ static my_coll_lexem_num my_coll_lexem_n
rc= MY_COLL_LEXEM_CHAR;
goto ex;
}
-
+
+ /*
+ Unescaped single byte character:
+ allow printable ASCII range except SPACE and
+ special characters parsed above []<&/|=
+ */
+ if (*beg >= 0x21 && *beg <= 0x7E)
+ {
+ lexem->code= *beg++;
+ rc= MY_COLL_LEXEM_CHAR;
+ goto ex;
+ }
+
+ if (((uchar) *beg) > 0x7F) /* Unescaped multibyte character */
+ {
+ CHARSET_INFO *cs= &my_charset_utf8_general_ci;
+ my_wc_t wc;
+ int nbytes= cs->cset->mb_wc(cs, &wc,
+ (uchar *) beg, (uchar *) lexem->end);
+ if (nbytes > 0)
+ {
+ rc= MY_COLL_LEXEM_CHAR;
+ beg+= nbytes;
+ lexem->code= (int) wc;
+ goto ex;
+ }
+ }
+
rc= MY_COLL_LEXEM_ERROR;
goto ex;
}
- rc= MY_COLL_LEXEM_EOF;
-
-ex:
- lexem->prev= lexem->beg;
- lexem->beg= beg;
- return rc;
+ rc= MY_COLL_LEXEM_EOF;
+
+ex:
+ lexem->prev= lexem->beg;
+ lexem->beg= beg;
+ lexem->term= rc;
+ return rc;
+}
+
+
+/*
+ Collation rule item
+*/
+
+#define MY_UCA_MAX_EXPANSION 6 /* Maximum expansion length */
+
+typedef struct my_coll_rule_item_st
+{
+ my_wc_t base[MY_UCA_MAX_EXPANSION]; /* Base character */
+ my_wc_t curr[MY_UCA_MAX_CONTRACTION]; /* Current character */
+ int diff[4]; /* Primary, Secondary, Tertiary, Quaternary difference */
+ size_t before_level; /* "reset before" indicator */
+ my_bool with_context;
+} MY_COLL_RULE;
+
+
+/**
+ Return length of a 0-terminated wide string, analog to strnlen().
+
+ @param s Pointer to wide string
+ @param maxlen Mamixum string length
+
+ @return string length, or maxlen if no '\0' is met.
+*/
+static size_t
+my_wstrnlen(my_wc_t *s, size_t maxlen)
+{
+ size_t i;
+ for (i= 0; i < maxlen; i++)
+ {
+ if (s[i] == 0)
+ return i;
+ }
+ return maxlen;
+}
+
+
+/**
+ Return length of the "reset" string of a rule.
+
+ @param r Collation customization rule
+
+ @return Length of r->base
+*/
+
+static inline size_t
+my_coll_rule_reset_length(MY_COLL_RULE *r)
+{
+ return my_wstrnlen(r->base, MY_UCA_MAX_EXPANSION);
+}
+
+
+/**
+ Return length of the "shift" string of a rule.
+
+ @param r Collation customization rule
+
+ @return Length of r->base
+*/
+
+static inline size_t
+my_coll_rule_shift_length(MY_COLL_RULE *r)
+{
+ return my_wstrnlen(r->curr, MY_UCA_MAX_CONTRACTION);
+}
+
+
+/**
+ Append new character to the end of a 0-terminated wide string.
+
+ @param wc Wide string
+ @param limit Maximum possible result length
+ @param code Character to add
+
+ @return 1 if character was added, 0 if string was too long
+*/
+
+static int
+my_coll_rule_expand(my_wc_t *wc, size_t limit, my_wc_t code)
+{
+ size_t i;
+ for (i= 0; i <= limit; i++)
+ {
+ if (wc[i] == 0)
+ {
+ wc[i]= code;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/**
+ Initialize collation customization rule
+
+ @param wc Rule
+*/
+
+static void
+my_coll_rule_reset(MY_COLL_RULE *r)
+{
+ bzero((void *) r, sizeof(*r));
+}
+
+
+typedef struct my_coll_rules_st
+{
+ uint version; /* Unicode version, e.g. 400 or 520 */
+ MY_UCA_INFO *uca; /* Unicode weight data */
+ size_t nrules; /* Number of rules in the rule array */
+ size_t mrules; /* Number of allocated rules */
+ MY_COLL_RULE *rule; /* Rule array */
+ MY_CHARSET_LOADER *loader;
+} MY_COLL_RULES;
+
+
+/**
+ Realloc rule array to a new size.
+ Reallocate memory for 128 additional rules at once,
+ to reduce the number of reallocs, which is important
+ for long tailorings (e.g. for East Asian collations).
+
+ @param rules Rule container
+ @param n new number of rules
+
+ @return 0 on success, -1 on error.
+*/
+
+static int
+my_coll_rules_realloc(MY_COLL_RULES *rules, size_t n)
+{
+ if (rules->nrules < rules->mrules ||
+ (rules->rule= rules->loader->realloc(rules->rule,
+ sizeof(MY_COLL_RULE) *
+ (rules->mrules= n + 128))))
+ return 0;
+ return -1;
+}
+
+
+/**
+ Append one new rule to a rule array
+
+ @param rules Rule container
+ @param rule New rule to add
+
+ @return 0 on success, -1 on error.
+*/
+
+static int
+my_coll_rules_add(MY_COLL_RULES *rules, MY_COLL_RULE *rule)
+{
+ if (my_coll_rules_realloc(rules, rules->nrules + 1))
+ return -1;
+ rules->rule[rules->nrules++]= rule[0];
+ return 0;
+}
+
+
+/**
+ Apply difference at level
+
+ @param r Rule
+ @param level Level (0,1,2,3,4)
+*/
+
+static void
+my_coll_rule_shift_at_level(MY_COLL_RULE *r, int level)
+{
+ switch (level)
+ {
+ case 4: /* Quaternary difference */
+ r->diff[3]++;
+ break;
+ case 3: /* Tertiary difference */
+ r->diff[2]++;
+ r->diff[3]= 0;
+ break;
+ case 2: /* Secondary difference */
+ r->diff[1]++;
+ r->diff[2]= r->diff[3]= 0;
+ break;
+ case 1: /* Primary difference */
+ r->diff[0]++;
+ r->diff[1]= r->diff[2]= r->diff[3]= 0;
+ break;
+ case 0:
+ /* Do nothing for '=': use the previous offsets for all levels */
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+}
+
+
+typedef struct my_coll_rule_parser_st
+{
+ MY_COLL_LEXEM tok[2]; /* Current token and next token for look-ahead */
+ MY_COLL_RULE rule; /* Currently parsed rule */
+ MY_COLL_RULES *rules; /* Rule list pointer */
+ char errstr[128]; /* Error message */
+} MY_COLL_RULE_PARSER;
+
+
+/**
+ Current parser token
+
+ @param p Collation customization parser
+
+ @return Pointer to the current token
+*/
+
+static MY_COLL_LEXEM *
+my_coll_parser_curr(MY_COLL_RULE_PARSER *p)
+{
+ return &p->tok[0];
+}
+
+
+/**
+ Next parser token, to look ahead.
+
+ @param p Collation customization parser
+
+ @return Pointer to the next token
+*/
+
+static MY_COLL_LEXEM *
+my_coll_parser_next(MY_COLL_RULE_PARSER *p)
+{
+ return &p->tok[1];
+}
+
+
+/**
+ Scan one token from the input stream
+
+ @param p Collation customization parser
+
+ @return 1, for convenience, to use in logical expressions easier.
+*/
+static int
+my_coll_parser_scan(MY_COLL_RULE_PARSER *p)
+{
+ my_coll_parser_curr(p)[0]= my_coll_parser_next(p)[0];
+ my_coll_lexem_next(my_coll_parser_next(p));
+ return 1;
+}
+
+
+/**
+ Initialize collation customization parser
+
+ @param p Collation customization parser
+ @param rules Where to store rules
+ @param str Beginning of a collation customization sting
+ @param str_end End of the collation customizations string
+*/
+
+static void
+my_coll_parser_init(MY_COLL_RULE_PARSER *p,
+ MY_COLL_RULES *rules,
+ const char *str, const char *str_end)
+{
+ /*
+ Initialize parser to the input buffer and scan two tokens,
+ to make the current token and the next token known.
+ */
+ bzero((void *) p, sizeof(*p));
+ p->rules= rules;
+ p->errstr[0]= '\0';
+ my_coll_lexem_init(my_coll_parser_curr(p), str, str_end);
+ my_coll_lexem_next(my_coll_parser_curr(p));
+ my_coll_parser_next(p)[0]= my_coll_parser_curr(p)[0];
+ my_coll_lexem_next(my_coll_parser_next(p));
+}
+
+
+/**
+ Display error when an unexpected token found
+
+ @param p Collation customization parser
+ @param term Which lexem was expected
+
+ @return 0, to use in "return" and boolean expressions.
+*/
+
+static int
+my_coll_parser_expected_error(MY_COLL_RULE_PARSER *p, my_coll_lexem_num term)
+{
+ my_snprintf(p->errstr, sizeof(p->errstr),
+ "%s expected", my_coll_lexem_num_to_str(term));
+ return 0;
+}
+
+
+/**
+ Display error when a too long character sequence is met
+
+ @param p Collation customization parser
+ @param name Which kind of sequence: contraction, expansion, etc.
+
+ @return 0, to use in "return" and boolean expressions.
+*/
+
+static int
+my_coll_parser_too_long_error(MY_COLL_RULE_PARSER *p, const char *name)
+{
+ my_snprintf(p->errstr, sizeof(p->errstr), "%s is too long", name);
+ return 0;
+}
+
+
+/**
+ Scan the given lexem from input stream, or display "expected" error.
+
+ @param p Collation customization parser
+ @param term Which lexem is expected.
+
+ @return
+ @retval 0 if the required term was not found.
+ @retval 1 if the required term was found.
+*/
+static int
+my_coll_parser_scan_term(MY_COLL_RULE_PARSER *p, my_coll_lexem_num term)
+{
+ if (my_coll_parser_curr(p)->term != term)
+ return my_coll_parser_expected_error(p, term);
+ return my_coll_parser_scan(p);
+}
+
+
+/*
+ In the following code we have a few functions to parse
+ various collation customization non-terminal symbols.
+ Unlike our usual coding convension, they return
+ - 0 on "error" (when the rule was not scanned) and
+ - 1 on "success"(when the rule was scanned).
+ This is done intentionally to make body of the functions look easier
+ and repeat the grammar of the rules in straightforward manner.
+ For example:
+
+ // <x> ::= <y> | <z>
+ int parse_x() { return parse_y() || parser_z(); }
+
+ // <x> ::= <y> <z>
+ int parse_x() { return parse_y() && parser_z(); }
+
+ Using 1 on "not found" and 0 on "found" in the parser code would
+ make the code more error prone and harder to read because
+ of having to use inverse boolean logic.
+*/
+
+
+/**
+ Scan a collation setting in brakets, for example UCA version.
+
+ @param p Collation customization parser
+
+ @return
+ @retval 0 if setting was scanned.
+ @retval 1 if setting was not scanned.
+*/
+
+static int
+my_coll_parser_scan_setting(MY_COLL_RULE_PARSER *p)
+{
+ MY_COLL_RULES *rules= p->rules;
+ MY_COLL_LEXEM *lexem= my_coll_parser_curr(p);
+
+ if (!lex_cmp(lexem, C_STRING_WITH_LEN("[version 4.0.0]")))
+ {
+ rules->version= 400;
+ rules->uca= &my_uca_v400;
+ }
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[version 5.2.0]")))
+ {
+ rules->version= 520;
+ rules->uca= &my_uca_v520;
+ }
+ else
+ {
+ return 0;
+ }
+ return my_coll_parser_scan(p);
+}
+
+
+/**
+ Scan multiple collation settings
+
+ @param p Collation customization parser
+
+ @return
+ @retval 0 if no settings were scanned.
+ @retval 1 if one or more settings were scanned.
+*/
+
+static int
+my_coll_parser_scan_settings(MY_COLL_RULE_PARSER *p)
+{
+ /* Scan collation setting or special purpose command */
+ while (my_coll_parser_curr(p)->term == MY_COLL_LEXEM_OPTION)
+ {
+ if (!my_coll_parser_scan_setting(p))
+ return 0;
+ }
+ return 1;
+}
+
+
+/**
+ Scan [before xxx] reset option
+
+ @param p Collation customization parser
+
+ @return
+ @retval 0 if reset option was not scanned.
+ @retval 1 if reset option was scanned.
+*/
+
+static int
+my_coll_parser_scan_reset_before(MY_COLL_RULE_PARSER *p)
+{
+ MY_COLL_LEXEM *lexem= my_coll_parser_curr(p);
+ if (!lex_cmp(lexem, C_STRING_WITH_LEN("[before primary]")) ||
+ !lex_cmp(lexem, C_STRING_WITH_LEN("[before 1]")))
+ {
+ p->rule.before_level= 1;
+ }
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[before secondary]")) ||
+ !lex_cmp(lexem, C_STRING_WITH_LEN("[before 2]")))
+ {
+ p->rule.before_level= 2;
+ }
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[before tertiary]")) ||
+ !lex_cmp(lexem, C_STRING_WITH_LEN("[before 3]")))
+ {
+ p->rule.before_level= 3;
+ }
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[before quaternary]")) ||
+ !lex_cmp(lexem, C_STRING_WITH_LEN("[before 4]")))
+ {
+ p->rule.before_level= 4;
+ }
+ else
+ {
+ p->rule.before_level= 0;
+ return 0; /* Don't scan thr next character */
+ }
+ return my_coll_parser_scan(p);
+}
+
+
+/**
+ Scan logical position and add to the wide string.
+
+ @param p Collation customization parser
+ @param pwc Wide string to add code to
+ @param limit The result string cannot be longer than 'limit' characters
+
+ @return
+ @retval 0 if logical position was not scanned.
+ @retval 1 if logical position was scanned.
+*/
+
+static int
+my_coll_parser_scan_logical_position(MY_COLL_RULE_PARSER *p,
+ my_wc_t *pwc, size_t limit)
+{
+ MY_COLL_RULES *rules= p->rules;
+ MY_COLL_LEXEM *lexem= my_coll_parser_curr(p);
+
+ if (!lex_cmp(lexem, C_STRING_WITH_LEN("[first non-ignorable]")))
+ lexem->code= rules->uca->first_non_ignorable;
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[last non-ignorable]")))
+ lexem->code= rules->uca->last_non_ignorable;
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[first primary ignorable]")))
+ lexem->code= rules->uca->first_primary_ignorable;
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[last primary ignorable]")))
+ lexem->code= rules->uca->last_primary_ignorable;
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[first secondary ignorable]")))
+ lexem->code= rules->uca->first_secondary_ignorable;
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[last secondary ignorable]")))
+ lexem->code= rules->uca->last_secondary_ignorable;
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[first tertiary ignorable]")))
+ lexem->code= rules->uca->first_tertiary_ignorable;
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[last tertiary ignorable]")))
+ lexem->code= rules->uca->last_tertiary_ignorable;
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[first trailing]")))
+ lexem->code= rules->uca->first_trailing;
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[last trailing]")))
+ lexem->code= rules->uca->last_trailing;
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[first variable]")))
+ lexem->code= rules->uca->first_variable;
+ else if (!lex_cmp(lexem, C_STRING_WITH_LEN("[last variable]")))
+ lexem->code= rules->uca->last_variable;
+ else
+ return 0; /* Don't scan the next token */
+
+ if (!my_coll_rule_expand(pwc, limit, lexem->code))
+ {
+ /*
+ Logical position can not be in a contraction,
+ so the above call should never fail.
+ Let's assert in debug version and print
+ a nice error message in production version.
+ */
+ DBUG_ASSERT(0);
+ return my_coll_parser_too_long_error(p, "Logical position");
+ }
+ return my_coll_parser_scan(p);
+}
+
+
+/**
+ Scan character list
+
+ <character list> ::= CHAR [ CHAR... ]
+
+ @param p Collation customization parser
+ @param pwc Character string to add code to
+ @param limit The result string cannot be longer than 'limit' characters
+ @param name E.g. "contraction", "expansion"
+
+ @return
+ @retval 0 if character sequence was not scanned.
+ @retval 1 if character sequence was scanned.
+*/
+
+static int
+my_coll_parser_scan_character_list(MY_COLL_RULE_PARSER *p,
+ my_wc_t *pwc, size_t limit,
+ const char *name)
+{
+ if (my_coll_parser_curr(p)->term != MY_COLL_LEXEM_CHAR)
+ return my_coll_parser_expected_error(p, MY_COLL_LEXEM_CHAR);
+
+ if (!my_coll_rule_expand(pwc, limit, my_coll_parser_curr(p)->code))
+ return my_coll_parser_too_long_error(p, name);
+
+ if (!my_coll_parser_scan_term(p, MY_COLL_LEXEM_CHAR))
+ return 0;
+
+ while (my_coll_parser_curr(p)->term == MY_COLL_LEXEM_CHAR)
+ {
+ if (!my_coll_rule_expand(pwc, limit, my_coll_parser_curr(p)->code))
+ return my_coll_parser_too_long_error(p, name);
+ my_coll_parser_scan(p);
+ }
+ return 1;
+}
+
+
+/**
+ Scan reset sequence
+
+ <reset sequence> ::=
+ [ <reset before option> ] <character list>
+ | [ <reset before option> ] <logical reset position>
+
+ @param p Collation customization parser
+
+ @return
+ @retval 0 if reset sequence was not scanned.
+ @retval 1 if reset sequence was scanned.
+*/
+
+static int
+my_coll_parser_scan_reset_sequence(MY_COLL_RULE_PARSER *p)
+{
+ my_coll_rule_reset(&p->rule);
+
+ /* Scan "[before x]" option, if exists */
+ if (my_coll_parser_curr(p)->term == MY_COLL_LEXEM_OPTION)
+ my_coll_parser_scan_reset_before(p);
+
+ /* Try logical reset position */
+ if (my_coll_parser_curr(p)->term == MY_COLL_LEXEM_OPTION)
+ {
+ if (!my_coll_parser_scan_logical_position(p, p->rule.base, 1))
+ return 0;
+ }
+ else
+ {
+ /* Scan single reset character or expansion */
+ if (!my_coll_parser_scan_character_list(p, p->rule.base,
+ MY_UCA_MAX_EXPANSION, "Expansion"))
+ return 0;
+ }
+
+ if (p->rule.before_level == 1) /* Apply "before primary" option */
+ {
+ /*
+ Suppose we have this rule: &B[before primary] < C
+ i.e. we need to put C before B, but after A, so
+ the result order is: A < C < B.
+
+ Let primary weight of B be [BBBB].
+
+ We cannot just use [BBBB-1] as weight for C:
+ DUCET does not have enough unused weights between any two characters,
+ so using [BBBB-1] will likely make C equal to the previous character,
+ which is A, so we'll get this order instead of the desired: A = C < B.
+
+ To guarantee that that C is sorted after A, we'll use expansion
+ with a kind of "biggest possible character".
+ As "biggest possible character" we'll use "last_non_ignorable":
+
+ We'll compose weight for C as: [BBBB-1][MMMM+1]
+ where [MMMM] is weight for "last_non_ignorable".
+
+ At this point we only need to store codepoints
+ 'B' and 'last_non_ignorable'. Actual weights for 'C'
+ will be calculated according to the above formula later,
+ in create_tailoring().
+ */
+ if (!my_coll_rule_expand(p->rule.base, MY_UCA_MAX_EXPANSION,
+ p->rules->uca->last_non_ignorable))
+ return my_coll_parser_too_long_error(p, "Expansion");
+ }
+ return 1;
}
-/*
- Collation rule item
+/**
+ Scan shift sequence
+
+ <shift sequence> ::=
+ <character list> [ / <character list> ]
+ | <character list> [ | <character list> ]
+
+ @param p Collation customization parser
+
+ @return
+ @retval 0 if shift sequence was not scanned.
+ @retval 1 if shift sequence was scanned.
*/
-typedef struct my_coll_rule_item_st
+static int
+my_coll_parser_scan_shift_sequence(MY_COLL_RULE_PARSER *p)
{
- my_wc_t base[2]; /* Base character */
- my_wc_t curr[2]; /* Current character */
- int diff[3]; /* Primary, Secondary and Tertiary difference */
-} MY_COLL_RULE;
+ MY_COLL_RULE before_extend;
+ bzero((void *) &p->rule.curr, sizeof(p->rule.curr));
-#define MY_MAX_COLL_RULE 256
+ /* Scan single shift character or contraction */
+ if (!my_coll_parser_scan_character_list(p, p->rule.curr,
+ MY_UCA_MAX_CONTRACTION,
+ "Contraction"))
+ return 0;
-typedef struct my_coll_rules_st
+ before_extend= p->rule; /* Remember the part before "/" */
+
+ /* Append the part after "/" as expansion */
+ if (my_coll_parser_curr(p)->term == MY_COLL_LEXEM_EXTEND)
+ {
+ my_coll_parser_scan(p);
+ if (!my_coll_parser_scan_character_list(p, p->rule.base,
+ MY_UCA_MAX_EXPANSION,
+ "Expansion"))
+ return 0;
+ }
+ else if (my_coll_parser_curr(p)->term == MY_COLL_LEXEM_CONTEXT)
+ {
+ /*
+ We support 2-character long context sequences only:
+ one character is the previous context, plus the current character.
+ It's OK as Unicode's CLDR does not have longer examples.
+ */
+ my_coll_parser_scan(p);
+ p->rule.with_context= TRUE;
+ if (!my_coll_parser_scan_character_list(p, p->rule.curr + 1, 1, "context"))
+ return 0;
+ }
+
+ /* Add rule to the rule list */
+ if (my_coll_rules_add(p->rules, &p->rule))
+ return 0;
+
+ p->rule= before_extend; /* Restore to the state before "/" */
+
+ return 1;
+}
+
+
+/**
+ Scan shift operator
+
+ <shift> ::= < | << | <<< | <<<< | =
+
+ @param p Collation customization parser
+
+ @return
+ @retval 0 if shift operator was not scanned.
+ @retval 1 if shift operator was scanned.
+*/
+static int
+my_coll_parser_scan_shift(MY_COLL_RULE_PARSER *p)
{
- uint version;
- MY_COLL_RULE rule[MY_MAX_COLL_RULE];
-} MY_COLL_RULES;
+ if (my_coll_parser_curr(p)->term == MY_COLL_LEXEM_SHIFT)
+ {
+ my_coll_rule_shift_at_level(&p->rule, my_coll_parser_curr(p)->diff);
+ return my_coll_parser_scan(p);
+ }
+ return 0;
+}
+
+
+/**
+ Scan one rule: reset followed by a number of shifts
+
+ <rule> ::=
+ & <reset sequence>
+ <shift> <shift sequence>
+ [ { <shift> <shift sequence> }... ]
+
+ @param p Collation customization parser
+
+ @return
+ @retval 0 if rule was not scanned.
+ @retval 1 if rule was scanned.
+*/
+static int
+my_coll_parser_scan_rule(MY_COLL_RULE_PARSER *p)
+{
+ if (!my_coll_parser_scan_term(p, MY_COLL_LEXEM_RESET) ||
+ !my_coll_parser_scan_reset_sequence(p))
+ return 0;
+
+ /* Scan the first required shift command */
+ if (!my_coll_parser_scan_shift(p))
+ return my_coll_parser_expected_error(p, MY_COLL_LEXEM_SHIFT);
+
+ /* Scan the first shift sequence */
+ if (!my_coll_parser_scan_shift_sequence(p))
+ return 0;
+
+ /* Scan subsequent shift rules */
+ while (my_coll_parser_scan_shift(p))
+ {
+ if (!my_coll_parser_scan_shift_sequence(p))
+ return 0;
+ }
+ return 1;
+}
+
+
+/**
+ Scan collation customization: settings followed by rules
+
+ <collation customization> ::=
+ [ <setting> ... ]
+ [ <rule>... ]
+
+ @param p Collation customization parser
+
+ @return
+ @retval 0 if collation customozation expression was not scanned.
+ @retval 1 if collation customization expression was scanned.
+*/
+
+static int
+my_coll_parser_exec(MY_COLL_RULE_PARSER *p)
+{
+ if (!my_coll_parser_scan_settings(p))
+ return 0;
+
+ while (my_coll_parser_curr(p)->term == MY_COLL_LEXEM_RESET)
+ {
+ if (!my_coll_parser_scan_rule(p))
+ return 0;
+ }
+ /* Make sure no unparsed input data left */
+ return my_coll_parser_scan_term(p, MY_COLL_LEXEM_EOF);
+}
/*
Collation language syntax parser.
Uses lexical parser.
-
- SYNOPSIS
- my_coll_rule_parse
- rule Collation rule list to load to.
- str A string containin collation language expression.
- str_end End of the string.
- USAGE
-
- RETURN VALUES
- A positive number means the number of rules loaded.
- -1 means ERROR, e.g. too many items, syntax error, etc.
-*/
+ @param rules Collation rule list to load to.
+ @param str A string with collation customization.
+ @param str_end End of the string.
+
+ @return
+ @retval 0 on success
+ @retval 1 on error
+*/
static int
-my_coll_rule_parse(MY_COLL_RULES *rules, size_t mitems,
- const char *str, const char *str_end,
- char *errstr, size_t errsize)
-{
- MY_COLL_LEXEM lexem;
- my_coll_lexem_num lexnum;
- my_coll_lexem_num prevlexnum= MY_COLL_LEXEM_ERROR;
- MY_COLL_RULE item;
- int state= 0;
- size_t nitems= 0;
-
- /* Init all variables */
- errstr[0]= '\0';
- bzero(&item, sizeof(item));
- my_coll_lexem_init(&lexem, str, str_end);
-
- while ((lexnum= my_coll_lexem_next(&lexem)))
+my_coll_rule_parse(MY_COLL_RULES *rules,
+ const char *str, const char *str_end)
+{
+ MY_COLL_RULE_PARSER p;
+
+ my_coll_parser_init(&p, rules, str, str_end);
+
+ if (!my_coll_parser_exec(&p))
{
- if (lexnum == MY_COLL_LEXEM_ERROR)
- {
- my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Unknown character");
- return -1;
- }
-
- switch (state) {
- case 0:
- if (lexnum == MY_COLL_LEXEM_OPTION)
- {
- const char v520[]= "[version 5.2.0]";
- const char v400[]= "[version 4.0.0]";
- size_t len= lexem.beg - lexem.prev;
-
- if ((len == sizeof(v520) - 1) && !memcmp(lexem.prev, v520, len))
- {
- rules->version= 520;
- continue;
- }
- else if ((len == sizeof(v400) - 1) && !memcmp(lexem.prev, v400, len))
- {
- rules->version= 400;
- continue;
- }
- else
- {
- my_coll_lexem_print_error(&lexem, errstr, errsize-1,
- "Unknown option");
- return -1;
- }
- }
- if (lexnum != MY_COLL_LEXEM_SHIFT)
- {
- my_coll_lexem_print_error(&lexem,errstr,errsize-1,"& expected");
- return -1;
- }
- prevlexnum= lexnum;
- state= 2;
- continue;
-
- case 1:
- if (lexnum != MY_COLL_LEXEM_SHIFT && lexnum != MY_COLL_LEXEM_DIFF)
- {
- my_coll_lexem_print_error(&lexem,errstr,errsize-1,"& or < expected");
- return -1;
- }
- prevlexnum= lexnum;
- state= 2;
- continue;
-
- case 2:
- if (lexnum != MY_COLL_LEXEM_CHAR)
- {
- my_coll_lexem_print_error(&lexem,errstr,errsize-1,"character expected");
- return -1;
- }
-
- if (prevlexnum == MY_COLL_LEXEM_SHIFT)
- {
- MY_COLL_LEXEM savlex= lexem;
- item.base[0]= lexem.code;
- item.diff[0]= 0;
- item.diff[1]= 0;
- item.diff[2]= 0;
-
- /* Check if shift to a double character (expansion) */
- if ((lexnum= my_coll_lexem_next(&lexem)) == MY_COLL_LEXEM_CHAR)
- {
- item.base[1]= lexem.code;
- }
- else
- {
- item.base[1]= 0;
- lexem= savlex; /* Restore previous parser state */
- }
- }
- else if (prevlexnum == MY_COLL_LEXEM_DIFF)
- {
- MY_COLL_LEXEM savlex;
- savlex= lexem;
- item.curr[0]= lexem.code;
-
- /* Check if diff for a double character (contraction) */
- if ((lexnum= my_coll_lexem_next(&lexem)) == MY_COLL_LEXEM_CHAR)
- {
- item.curr[1]= lexem.code;
- }
- else
- {
- item.curr[1]= 0;
- lexem=savlex; /* Restore previous parser state */
- }
- if (lexem.diff == 3)
- {
- item.diff[2]++;
- }
- else if (lexem.diff == 2)
- {
- item.diff[1]++;
- item.diff[2]= 0;
- }
- else if (lexem.diff == 1)
- {
- item.diff[0]++;
- item.diff[1]= 0;
- item.diff[2]= 0;
- }
- else if (lexem.diff == 0)
- {
- /* Do nothing for '=': use the previous offsets for all levels */
- }
- if (nitems >= mitems)
- {
- my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Too many rules");
- return -1;
- }
- rules->rule[nitems++]= item;
- }
- else
- {
- my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Should never happen");
- return -1;
- }
- state= 1;
- continue;
- }
+ my_coll_lexem_print_error(my_coll_parser_curr(&p),
+ rules->loader->error,
+ sizeof(rules->loader->error) - 1,
+ p.errstr);
+ return 1;
}
- return (int) nitems;
+ return 0;
}
@@ -20808,39 +21640,93 @@ my_coll_rule_parse(MY_COLL_RULES *rules,
Copies UCA weights for a given "uint" string
to the given location.
- @weights source UCA weight array
- @lengths source UCA length array
- @to destination
+ @src_uca source UCA weight data
+ @dst_uca destination UCA weight data
+ @to destination address
@to_length size of destination
- @str string
+ @str qide string
@len string length
@return number of weights put
*/
static size_t
-my_char_weight_put(MY_UCA_INFO *src_uca,
+my_char_weight_put(MY_UCA_INFO *dst_uca,
uint16 *to, size_t to_length,
my_wc_t *str, size_t len)
{
- size_t i, count;
+ size_t count;
if (!to_length)
return 0;
to_length--; /* Without trailing zero */
- for (count=0, i= 0; (i < len) && (count < to_length); i++, str++)
+
+ for (count= 0; len; )
{
- uint16 *from= my_char_weight_addr(src_uca, *str);
- for ( ; from && from[0]; from++)
+ size_t chlen;
+ uint16 *from= NULL;
+
+ for (chlen= len; chlen > 1; chlen--)
+ {
+ if ((from= my_uca_contraction_weight(dst_uca, str, chlen)))
+ {
+ str+= chlen;
+ len-= chlen;
+ break;
+ }
+ }
+
+ if (!from)
+ {
+ from= my_char_weight_addr(dst_uca, *str);
+ str++;
+ len--;
+ }
+
+ for ( ; from && *from && count < to_length; )
{
- *to++= *from;
+ *to++= *from++;
count++;
}
}
+
*to= 0;
return count;
}
+/**
+ Alloc new page and copy the default UCA weights
+ @param loader - Character set loader
+ @param src_uca - Default UCA data to copy from
+ @param dst_uca - UCA data to copy weights to
+ @param page - page number
+
+ @return
+ @retval FALSE on success
+ @retval TRUE on error
+*/
+static my_bool
+my_uca_copy_page(MY_CHARSET_LOADER *loader,
+ MY_UCA_INFO *src_uca,
+ MY_UCA_INFO *dst_uca,
+ size_t page)
+{
+ uint chc, size= 256 * dst_uca->lengths[page] * sizeof(uint16);
+ if (!(dst_uca->weights[page]= (uint16 *) (loader->once_alloc)(size)))
+ return TRUE;
+
+ DBUG_ASSERT(src_uca->lengths[page] <= dst_uca->lengths[page]);
+ bzero((void *) dst_uca->weights[page], size);
+ for (chc=0 ; chc < 256; chc++)
+ {
+ memcpy(dst_uca->weights[page] + chc * dst_uca->lengths[page],
+ src_uca->weights[page] + chc * src_uca->lengths[page],
+ src_uca->lengths[page] * sizeof(uint16));
+ }
+ return FALSE;
+}
+
+
/*
This function copies an UCS2 collation from
the default Unicode Collation Algorithm (UCA)
@@ -20859,33 +21745,32 @@ my_char_weight_put(MY_UCA_INFO *src_uca,
*/
static my_bool
-create_tailoring(CHARSET_INFO *cs, void *(*alloc)(size_t),
- char *error, size_t errsize)
+create_tailoring(CHARSET_INFO *cs, MY_CHARSET_LOADER *loader)
{
MY_COLL_RULES rules;
MY_COLL_RULE *r, *rlast;
MY_UCA_INFO new_uca, *src_uca= NULL;
- int rc, ncontractions= 0;
- size_t npages;
-
- DBUG_ASSERT(error != NULL && errsize > 0);
- *error= '\0';
-
+ int rc= 0, ncontractions= 0;
+ size_t npages, i;
+
+ *loader->error= '\0';
+
if (!cs->tailoring)
return 0; /* Ok to add a collation without tailoring */
-
+
bzero((void *) &rules, sizeof(rules));
+ rules.loader= loader;
+ rules.uca= cs->uca ? cs->uca : &my_uca_v400; /* For logical positions, etc */
bzero((void *) &new_uca, sizeof(new_uca));
-
+
/* Parse ICU Collation Customization expression */
- if ((rc= my_coll_rule_parse(&rules, MY_MAX_COLL_RULE,
+ if ((rc= my_coll_rule_parse(&rules,
cs->tailoring,
- cs->tailoring + strlen(cs->tailoring),
- error, errsize)) < 0)
- return 1;
+ cs->tailoring + strlen(cs->tailoring))))
+ goto ex;
+
+ rlast= rules.rule + rules.nrules;
- rlast= rules.rule + rc;
-
if (rules.version == 520) /* Unicode-5.2.0 requested */
{
src_uca= &my_uca_v520;
@@ -20906,97 +21791,149 @@ create_tailoring(CHARSET_INFO *cs, void
new_uca.maxchar= src_uca->maxchar;
npages= (src_uca->maxchar + 1) / 256;
- if (!(new_uca.weights= (uint16**) (*alloc)(npages * sizeof(uint16*))))
- return 1;
- bzero(new_uca.weights, npages * sizeof(uint16*));
+ /* Allocate memory for pages and their lengths */
+ if (!(new_uca.lengths= (uchar *) (loader->once_alloc)(npages)) ||
+ !(new_uca.weights= (uint16 **) (loader->once_alloc)(npages *
+ sizeof(uint16 *))))
+ {
+ rc= 1;
+ goto ex;
+ }
- if (!(new_uca.lengths= (uchar*) (*alloc)(npages)))
- return 1;
-
+ /* Copy pages lengths and page pointers from the default UCA weights */
memcpy(new_uca.lengths, src_uca->lengths, npages);
-
+ memcpy(new_uca.weights, src_uca->weights, npages * sizeof(uint16 *));
/*
- Calculate maximum lenghts for the pages
- which will be overwritten.
+ Calculate maximum lenghts for the pages which will be overwritten.
+ Mark pages that will be otherwriten as NULL.
+ We'll allocate their own memory.
*/
for (r= rules.rule; r < rlast; r++)
{
if (r->curr[0] > new_uca.maxchar)
{
- my_snprintf(error, errsize,
+ my_snprintf(loader->error, sizeof(loader->error),
"Shift character out of range: u%04X", (uint) r->curr[0]);
- return 1;
+ rc= 1;
+ goto ex;
}
else if (r->base[0] > src_uca->maxchar)
{
- my_snprintf(error, errsize,
+ my_snprintf(loader->error, sizeof(loader->error),
"Reset character out of range: u%04X", (uint) r->base[0]);
- return 1;
+ rc= 1;
+ goto ex;
}
-
+
if (!r->curr[1]) /* If not a contraction */
{
- uint pageb= (r->base[0] >> 8);
uint pagec= (r->curr[0] >> 8);
- if (new_uca.lengths[pagec] < src_uca->lengths[pageb])
- new_uca.lengths[pagec]= src_uca->lengths[pageb];
+ if (r->base[1]) /* Expansion */
+ {
+ /* Reserve space for maximum possible length */
+ new_uca.lengths[pagec]= MY_UCA_MAX_WEIGHT_SIZE;
+ }
+ else
+ {
+ uint pageb= (r->base[0] >> 8);
+ if (new_uca.lengths[pagec] < src_uca->lengths[pageb])
+ new_uca.lengths[pagec]= src_uca->lengths[pageb];
+ }
+ new_uca.weights[pagec]= NULL; /* Mark that we'll overwrite this page */
}
else
ncontractions++;
}
-
-
+
+ /* Allocate pages that we'll overwrite and copy default weights */
+ for (i= 0; i < npages; i++)
+ {
+ /*
+ Don't touch pages with lengths[i]==0, they have implicit weights
+ calculated algorithmically.
+ */
+ if (!new_uca.weights[i] && new_uca.lengths[i] &&
+ (rc= my_uca_copy_page(loader, src_uca, &new_uca, i)))
+ goto ex;
+ }
+
+
if (ncontractions)
{
- if (my_uca_alloc_contractions(&new_uca, alloc, ncontractions))
- return 1;
+ if (my_uca_alloc_contractions(&new_uca, loader, ncontractions))
+ {
+ rc= 1;
+ goto ex;
+ }
}
-
-
+
+ /*
+ Preparatory step is done at this point.
+ Now we have memory allocated for the pages that we'll overwrite,
+ and for contractions, including previous context contractions.
+ Also, for the pages that we'll overwrite, we have copied default weights.
+ Now iterate through the rules, overwrite weights for the characters
+ that appear in the rules, and put all contractions into contraction list.
+ */
for (r= rules.rule; r < rlast; r++)
{
- size_t nweights, nchars= r->base[1] ? 2 : 1;
+ size_t nweights;
+ size_t nreset= my_coll_rule_reset_length(r); /* Length of reset sequence */
+ size_t nshift= my_coll_rule_shift_length(r); /* Length of shift sequence */
uint16 *to;
-
- if (r->curr[1]) /* Contraction */
+
+ if (nshift >= 2) /* Contraction */
{
- /* Mark both letters as "is contraction part" */
- my_uca_add_contraction_flag(&new_uca, r->curr[0], MY_UCA_CNT_HEAD);
- my_uca_add_contraction_flag(&new_uca, r->curr[1], MY_UCA_CNT_TAIL);
- to= my_uca_add_contraction(&new_uca, r->curr, 2)->weight;
- nweights= MY_UCA_MAX_WEIGHT_SIZE;
+ size_t i;
+ int flag;
+ /* Add HEAD, MID and TAIL flags for the contraction parts */
+ my_uca_add_contraction_flag(&new_uca, r->curr[0],
+ r->with_context ?
+ MY_UCA_PREVIOUS_CONTEXT_HEAD :
+ MY_UCA_CNT_HEAD);
+ for (i= 1, flag= MY_UCA_CNT_MID1; i < nshift - 1; i++, flag<<= 1)
+ my_uca_add_contraction_flag(&new_uca, r->curr[i], flag);
+ my_uca_add_contraction_flag(&new_uca, r->curr[i],
+ r->with_context ?
+ MY_UCA_PREVIOUS_CONTEXT_TAIL :
+ MY_UCA_CNT_TAIL);
+ /* Add new contraction to the contraction list */
+ to= my_uca_add_contraction(&new_uca, r->curr, nshift,
+ r->with_context)->weight;
+ /* Store weights of the "reset to" character */
+ new_uca.contractions.nitems--; /* Temporarily hide - it's incomplete */
+ nweights= my_char_weight_put(&new_uca, to, MY_UCA_MAX_WEIGHT_SIZE,
+ r->base, nreset);
+ new_uca.contractions.nitems++; /* Activate, now it's complete */
}
else
{
my_wc_t pagec= (r->curr[0] >> 8);
- if (!new_uca.weights[pagec])
- {
- /* Alloc new page and copy the default UCA weights */
- uint chc, size= 256 * new_uca.lengths[pagec] * sizeof(uint16);
-
- if (!(new_uca.weights[pagec]= (uint16*) (*alloc)(size)))
- return 1;
- bzero((void *) new_uca.weights[pagec], size);
-
- for (chc=0 ; chc < 256; chc++)
- {
- memcpy(new_uca.weights[pagec] + chc * new_uca.lengths[pagec],
- src_uca->weights[pagec] + chc * src_uca->lengths[pagec],
- src_uca->lengths[pagec] * sizeof(uint16));
- }
- }
+ DBUG_ASSERT(new_uca.weights[pagec]);
to= my_char_weight_addr(&new_uca, r->curr[0]);
- nweights= new_uca.lengths[pagec];
+ /* Store weights of the "reset to" character */
+ nweights= my_char_weight_put(&new_uca, to, new_uca.lengths[pagec],
+ r->base, nreset);
}
- /* Store weights of the "shift to" character */
- nweights= my_char_weight_put(src_uca, to, nweights, r->base, nchars);
-
- /* Apply primary difference */
+ /* Apply primary difference. */
if (nweights)
{
to[nweights - 1]+= r->diff[0];
+ if (r->before_level == 1) /* Apply "&[before primary]" */
+ {
+ if (nweights >= 2)
+ to[nweights - 2]--; /* Reset before */
+ else
+ {
+ my_snprintf(loader->error, sizeof(loader->error),
+ "Can't reset before "
+ "a primary ignorable character U+%04X", r->base[0]);
+ rc= 1;
+ goto ex;
+ }
+ }
}
else
{
@@ -21005,23 +21942,20 @@ create_tailoring(CHARSET_INFO *cs, void
to[0]= r->diff[0];
}
}
-
-
- /* Copy non-overwritten pages from the default UCA weights */
+
+
+ if (!(cs->uca= (MY_UCA_INFO *) (loader->once_alloc)(sizeof(MY_UCA_INFO))))
{
- size_t i;
- for (i= 0; i < npages; i++)
- {
- if (!new_uca.weights[i])
- new_uca.weights[i]= src_uca->weights[i];
- }
+ rc= 1;
+ goto ex;
}
-
- if (!(cs->uca= (MY_UCA_INFO *) (*alloc)(sizeof(MY_UCA_INFO))))
- return 1;
cs->uca[0]= new_uca;
- return 0;
+ex:
+ (loader->free)(rules.rule);
+ if (rc != 0 && loader->error[0])
+ loader->reporter(ERROR_LEVEL, "%s", loader->error);
+ return rc;
}
@@ -21032,14 +21966,13 @@ create_tailoring(CHARSET_INFO *cs, void
*/
static my_bool
-my_coll_init_uca(CHARSET_INFO *cs, void *(*alloc)(size_t),
- char *error, size_t errsize)
+my_coll_init_uca(CHARSET_INFO *cs, MY_CHARSET_LOADER *loader)
{
cs->pad_char= ' ';
cs->ctype= my_charset_utf8_unicode_ci.ctype;
if (!cs->caseinfo)
cs->caseinfo= &my_unicase_default;
- return create_tailoring(cs, alloc, error, errsize);
+ return create_tailoring(cs, loader);
}
static int my_strnncoll_any_uca(CHARSET_INFO *cs,
@@ -21086,7 +22019,7 @@ static int my_strnncoll_ucs2_uca(CHARSET
const uchar *t, size_t tlen,
my_bool t_is_prefix)
{
- return my_strnncoll_uca(cs, &my_ucs2_uca_scanner_handler,
+ return my_strnncoll_uca(cs, &my_any_uca_scanner_handler,
s, slen, t, tlen, t_is_prefix);
}
@@ -21095,7 +22028,7 @@ static int my_strnncollsp_ucs2_uca(CHARS
const uchar *t, size_t tlen,
my_bool diff_if_only_endspace_difference)
{
- return my_strnncollsp_uca(cs, &my_ucs2_uca_scanner_handler,
+ return my_strnncollsp_uca(cs, &my_any_uca_scanner_handler,
s, slen, t, tlen,
diff_if_only_endspace_difference);
}
@@ -21104,14 +22037,14 @@ static void my_hash_sort_ucs2_uca(CHARSE
const uchar *s, size_t slen,
ulong *n1, ulong *n2)
{
- my_hash_sort_uca(cs, &my_ucs2_uca_scanner_handler, s, slen, n1, n2);
+ my_hash_sort_uca(cs, &my_any_uca_scanner_handler, s, slen, n1, n2);
}
static size_t my_strnxfrm_ucs2_uca(CHARSET_INFO *cs,
uchar *dst, size_t dstlen, uint nweights,
const uchar *src, size_t srclen, uint flags)
{
- return my_strnxfrm_uca(cs, &my_ucs2_uca_scanner_handler,
+ return my_strnxfrm_uca(cs, &my_any_uca_scanner_handler,
dst, dstlen, nweights, src, srclen, flags);
}
=== modified file 'strings/ctype.c'
--- a/strings/ctype.c 2010-07-23 21:26:21 +0000
+++ b/strings/ctype.c 2010-12-20 08:30:44 +0000
@@ -39,6 +39,18 @@
*/
+
+/*
+ Avoid using my_snprintf
+ We cannot use my_snprintf() here, because ctype.o is
+ used to build conf_to_src, which must require minimun
+ dependency.
+*/
+
+#undef my_snprinf
+#define my_snprintf "We cannot use my_snprintf in this file"
+
+
static char *mstr(char *str,const char *src,size_t l1,size_t l2)
{
l1= l1<l2 ? l1 : l2;
@@ -70,12 +82,74 @@ struct my_cs_file_section_st
#define _CS_PRIMARY_ID 15
#define _CS_BINARY_ID 16
#define _CS_CSDESCRIPT 17
-#define _CS_RESET 18
-#define _CS_DIFF1 19
-#define _CS_DIFF2 20
-#define _CS_DIFF3 21
-#define _CS_IDENTICAL 22
-#define _CS_UCA_VERSION 23
+
+
+/* Special purpose commands */
+#define _CS_UCA_VERSION 100
+#define _CS_CL_SUPPRESS_CONTRACTIONS 101
+#define _CS_CL_OPTIMIZE 102
+
+
+/* Collation Settings */
+#define _CS_ST_SETTINGS 200
+#define _CS_ST_STRENGTH 201
+#define _CS_ST_ALTERNATE 202
+#define _CS_ST_BACKWARDS 203
+#define _CS_ST_NORMALIZATION 204
+#define _CS_ST_CASE_LEVEL 205
+#define _CS_ST_CASE_FIRST 206
+#define _CS_ST_HIRAGANA_QUATERNARY 207
+#define _CS_ST_NUMERIC 208
+#define _CS_ST_VARIABLE_TOP 209
+#define _CS_ST_MATCH_BOUNDARIES 210
+#define _CS_ST_MATCH_STYLE 211
+
+
+/* Rules */
+#define _CS_RULES 300
+#define _CS_RESET 301
+#define _CS_DIFF1 302
+#define _CS_DIFF2 303
+#define _CS_DIFF3 304
+#define _CS_DIFF4 305
+#define _CS_IDENTICAL 306
+
+/* Rules: Expansions */
+#define _CS_EXP_X 320
+#define _CS_EXP_EXTEND 321
+#define _CS_EXP_DIFF1 322
+#define _CS_EXP_DIFF2 323
+#define _CS_EXP_DIFF3 324
+#define _CS_EXP_DIFF4 325
+#define _CS_EXP_IDENTICAL 326
+
+/* Rules: Abbreviating Ordering Specifications */
+#define _CS_A_DIFF1 351
+#define _CS_A_DIFF2 352
+#define _CS_A_DIFF3 353
+#define _CS_A_DIFF4 354
+#define _CS_A_IDENTICAL 355
+
+/* Rules: previous context */
+#define _CS_CONTEXT 370
+
+/* Rules: Placing Characters Before Others*/
+#define _CS_RESET_BEFORE 380
+
+/* Rules: Logical Reset Positions */
+#define _CS_RESET_FIRST_PRIMARY_IGNORABLE 401
+#define _CS_RESET_LAST_PRIMARY_IGNORABLE 402
+#define _CS_RESET_FIRST_SECONDARY_IGNORABLE 403
+#define _CS_RESET_LAST_SECONDARY_IGNORABLE 404
+#define _CS_RESET_FIRST_TERTIARY_IGNORABLE 405
+#define _CS_RESET_LAST_TERTIARY_IGNORABLE 406
+#define _CS_RESET_FIRST_TRAILING 407
+#define _CS_RESET_LAST_TRAILING 408
+#define _CS_RESET_FIRST_VARIABLE 409
+#define _CS_RESET_LAST_VARIABLE 410
+#define _CS_RESET_FIRST_NON_IGNORABLE 411
+#define _CS_RESET_LAST_NON_IGNORABLE 412
+
static struct my_cs_file_section_st sec[] =
@@ -85,6 +159,8 @@ static struct my_cs_file_section_st sec[
{_CS_MISC, "xml/encoding"},
{_CS_MISC, "charsets"},
{_CS_MISC, "charsets/max-id"},
+ {_CS_MISC, "charsets/copyright"},
+ {_CS_MISC, "charsets/description"},
{_CS_CHARSET, "charsets/charset"},
{_CS_PRIMARY_ID, "charsets/charset/primary-id"},
{_CS_BINARY_ID, "charsets/charset/binary-id"},
@@ -106,29 +182,89 @@ static struct my_cs_file_section_st sec[
{_CS_ORDER, "charsets/charset/collation/order"},
{_CS_FLAG, "charsets/charset/collation/flag"},
{_CS_COLLMAP, "charsets/charset/collation/map"},
- {_CS_RESET, "charsets/charset/collation/rules/reset"},
- {_CS_DIFF1, "charsets/charset/collation/rules/p"},
- {_CS_DIFF2, "charsets/charset/collation/rules/s"},
- {_CS_DIFF3, "charsets/charset/collation/rules/t"},
- {_CS_IDENTICAL, "charsets/charset/collation/rules/i"},
- {_CS_UCA_VERSION, "charsets/charset/collation/version"},
+
+ /* Special purpose commands */
+ {_CS_UCA_VERSION, "charsets/charset/collation/version"},
+ {_CS_CL_SUPPRESS_CONTRACTIONS, "charsets/charset/collation/suppress_contractions"},
+ {_CS_CL_OPTIMIZE, "charsets/charset/collation/optimize"},
+
+ /* Collation Settings */
+ {_CS_ST_SETTINGS, "charsets/charset/collation/settings"},
+ {_CS_ST_STRENGTH, "charsets/charset/collation/settings/strength"},
+ {_CS_ST_ALTERNATE, "charsets/charset/collation/settings/alternate"},
+ {_CS_ST_BACKWARDS, "charsets/charset/collation/settings/backwards"},
+ {_CS_ST_NORMALIZATION, "charsets/charset/collation/settings/normalization"},
+ {_CS_ST_CASE_LEVEL, "charsets/charset/collation/settings/caseLevel"},
+ {_CS_ST_CASE_FIRST, "charsets/charset/collation/settings/caseFirst"},
+ {_CS_ST_HIRAGANA_QUATERNARY, "charsets/charset/collation/settings/hiraganaQuaternary"},
+ {_CS_ST_NUMERIC, "charsets/charset/collation/settings/numeric"},
+ {_CS_ST_VARIABLE_TOP, "charsets/charset/collation/settings/variableTop"},
+ {_CS_ST_MATCH_BOUNDARIES, "charsets/charset/collation/settings/match-boundaries"},
+ {_CS_ST_MATCH_STYLE, "charsets/charset/collation/settings/match-style"},
+
+ /* Rules */
+ {_CS_RULES, "charsets/charset/collation/rules"},
+ {_CS_RESET, "charsets/charset/collation/rules/reset"},
+ {_CS_DIFF1, "charsets/charset/collation/rules/p"},
+ {_CS_DIFF2, "charsets/charset/collation/rules/s"},
+ {_CS_DIFF3, "charsets/charset/collation/rules/t"},
+ {_CS_DIFF4, "charsets/charset/collation/rules/q"},
+ {_CS_IDENTICAL, "charsets/charset/collation/rules/i"},
+
+ /* Rules: expansions */
+ {_CS_EXP_X, "charsets/charset/collation/rules/x"},
+ {_CS_EXP_EXTEND, "charsets/charset/collation/rules/x/extend"},
+ {_CS_EXP_DIFF1, "charsets/charset/collation/rules/x/p"},
+ {_CS_EXP_DIFF2, "charsets/charset/collation/rules/x/s"},
+ {_CS_EXP_DIFF3, "charsets/charset/collation/rules/x/t"},
+ {_CS_EXP_DIFF4, "charsets/charset/collation/rules/x/q"},
+ {_CS_EXP_IDENTICAL, "charsets/charset/collation/rules/x/i"},
+
+ /* Rules: previous context */
+ {_CS_CONTEXT, "charsets/charset/collation/rules/x/context"},
+
+ /* Rules: Abbreviating Ordering Specifications */
+ {_CS_A_DIFF1, "charsets/charset/collation/rules/pc"},
+ {_CS_A_DIFF2, "charsets/charset/collation/rules/sc"},
+ {_CS_A_DIFF3, "charsets/charset/collation/rules/tc"},
+ {_CS_A_DIFF4, "charsets/charset/collation/rules/qc"},
+ {_CS_A_IDENTICAL, "charsets/charset/collation/rules/ic"},
+
+ /* Rules: Placing Characters Before Others*/
+ {_CS_RESET_BEFORE, "charsets/charset/collation/rules/reset/before"},
+
+ /* Rules: Logical Reset Positions */
+ {_CS_RESET_FIRST_NON_IGNORABLE, "charsets/charset/collation/rules/reset/first_non_ignorable"},
+ {_CS_RESET_LAST_NON_IGNORABLE, "charsets/charset/collation/rules/reset/last_non_ignorable"},
+ {_CS_RESET_FIRST_PRIMARY_IGNORABLE, "charsets/charset/collation/rules/reset/first_primary_ignorable"},
+ {_CS_RESET_LAST_PRIMARY_IGNORABLE, "charsets/charset/collation/rules/reset/last_primary_ignorable"},
+ {_CS_RESET_FIRST_SECONDARY_IGNORABLE, "charsets/charset/collation/rules/reset/first_secondary_ignorable"},
+ {_CS_RESET_LAST_SECONDARY_IGNORABLE, "charsets/charset/collation/rules/reset/last_secondary_ignorable"},
+ {_CS_RESET_FIRST_TERTIARY_IGNORABLE, "charsets/charset/collation/rules/reset/first_tertiary_ignorable"},
+ {_CS_RESET_LAST_TERTIARY_IGNORABLE, "charsets/charset/collation/rules/reset/last_tertiary_ignorable"},
+ {_CS_RESET_FIRST_TRAILING, "charsets/charset/collation/rules/reset/first_trailing"},
+ {_CS_RESET_LAST_TRAILING, "charsets/charset/collation/rules/reset/last_trailing"},
+ {_CS_RESET_FIRST_VARIABLE, "charsets/charset/collation/rules/reset/first_variable"},
+ {_CS_RESET_LAST_VARIABLE, "charsets/charset/collation/rules/reset/last_variable"},
+
{0, NULL}
};
static struct my_cs_file_section_st * cs_file_sec(const char *attr, size_t len)
{
struct my_cs_file_section_st *s;
- for (s=sec; s->str; s++)
+ for (s= sec; s->str; s++)
{
- if (!strncmp(attr,s->str,len))
+ if (!strncmp(attr, s->str, len) && s->str[len] == 0)
return s;
}
return NULL;
}
#define MY_CS_CSDESCR_SIZE 64
-#define MY_CS_TAILORING_SIZE 1024
+#define MY_CS_TAILORING_SIZE 32*1024
#define MY_CS_UCA_VERSION_SIZE 64
+#define MY_CS_CONTEXT_SIZE 64
typedef struct my_cs_file_info
{
@@ -140,12 +276,59 @@ typedef struct my_cs_file_info
uchar sort_order[MY_CS_SORT_ORDER_TABLE_SIZE];
uint16 tab_to_uni[MY_CS_TO_UNI_TABLE_SIZE];
char comment[MY_CS_CSDESCR_SIZE];
- char tailoring[MY_CS_TAILORING_SIZE];
+ char *tailoring;
size_t tailoring_length;
+ size_t tailoring_alloced_length;
+ char context[MY_CS_CONTEXT_SIZE];
CHARSET_INFO cs;
- int (*add_collation)(CHARSET_INFO *cs);
-} MY_CHARSET_LOADER;
+ MY_CHARSET_LOADER *loader;
+} MY_CHARSET_FILE;
+
+
+static void
+my_charset_file_reset_charset(MY_CHARSET_FILE *i)
+{
+ bzero(&i->cs, sizeof(i->cs));
+}
+
+
+static void
+my_charset_file_reset_collation(MY_CHARSET_FILE *i)
+{
+ i->tailoring_length= 0;
+ i->context[0]= '\0';
+}
+
+
+static void
+my_charset_file_init(MY_CHARSET_FILE *i)
+{
+ my_charset_file_reset_charset(i);
+ my_charset_file_reset_collation(i);
+ i->tailoring= NULL;
+ i->tailoring_alloced_length= 0;
+}
+
+static void
+my_charset_file_free(MY_CHARSET_FILE *i)
+{
+ i->loader->free(i->tailoring);
+}
+
+
+static int
+my_charset_file_tailoring_realloc(MY_CHARSET_FILE *i, size_t newlen)
+{
+ if (i->tailoring_alloced_length > newlen ||
+ (i->tailoring= i->loader->realloc(i->tailoring,
+ (i->tailoring_alloced_length=
+ (newlen + 32*1024)))))
+ {
+ return MY_XML_OK;
+ }
+ return MY_XML_ERROR;
+}
static int fill_uchar(uchar *a,uint size,const char *str, size_t len)
@@ -183,17 +366,119 @@ static int fill_uint16(uint16 *a,uint si
}
+
+
+static int
+tailoring_append(MY_XML_PARSER *st,
+ const char *fmt, size_t len, const char *attr)
+{
+ struct my_cs_file_info *i= (struct my_cs_file_info *) st->user_data;
+ size_t newlen= i->tailoring_length + len + 64; /* 64 for format */
+ if (MY_XML_OK == my_charset_file_tailoring_realloc(i, newlen))
+ {
+ char *dst= i->tailoring + i->tailoring_length;
+ sprintf(dst, fmt, (int) len, attr);
+ i->tailoring_length+= strlen(dst);
+ return MY_XML_OK;
+ }
+ return MY_XML_ERROR;
+}
+
+
+static int
+tailoring_append2(MY_XML_PARSER *st,
+ const char *fmt,
+ size_t len1, const char *attr1,
+ size_t len2, const char *attr2)
+{
+ struct my_cs_file_info *i= (struct my_cs_file_info *) st->user_data;
+ size_t newlen= i->tailoring_length + len1 + len2 + 64; /* 64 for format */
+ if (MY_XML_OK == my_charset_file_tailoring_realloc(i, newlen))
+ {
+ char *dst= i->tailoring + i->tailoring_length;
+ sprintf(dst, fmt, (int) len1, attr1, (int) len2, attr2);
+ i->tailoring_length+= strlen(dst);
+ return MY_XML_OK;
+ }
+ return MY_XML_ERROR;
+}
+
+
+static size_t
+scan_one_character(const char *s, const char *e, my_wc_t *wc)
+{
+ CHARSET_INFO *cs= &my_charset_utf8_general_ci;
+ if (s >= e)
+ return 0;
+
+ /* Escape sequence: \uXXXX */
+ if (s[0] == '\\' && s + 2 < e && s[1] == 'u' && my_isxdigit(cs, s[2]))
+ {
+ size_t len= 3; /* We have at least one digit */
+ for (s+= 3; s < e && my_isxdigit(cs, s[0]); s++, len++)
+ {
+ }
+ wc[0]= 0;
+ return len;
+ }
+ else if (s[0] > 0) /* 7-bit character */
+ {
+ wc[0]= 0;
+ return 1;
+ }
+ else /* Non-escaped character */
+ {
+ int rc= cs->cset->mb_wc(cs, wc, (uchar *) s, (uchar *) e);
+ if (rc > 0)
+ return (size_t) rc;
+ }
+ return 0;
+}
+
+
+static int
+tailoring_append_abbreviation(MY_XML_PARSER *st,
+ const char *fmt, size_t len, const char *attr)
+{
+ size_t clen;
+ const char *attrend= attr + len;
+ my_wc_t wc;
+
+ for ( ; (clen= scan_one_character(attr, attrend, &wc)) > 0; attr+= clen)
+ {
+ DBUG_ASSERT(attr < attrend);
+ if (tailoring_append(st, fmt, clen, attr) != MY_XML_OK)
+ return MY_XML_ERROR;
+ }
+ return MY_XML_OK;
+}
+
+
static int cs_enter(MY_XML_PARSER *st,const char *attr, size_t len)
{
struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
struct my_cs_file_section_st *s= cs_file_sec(attr,len);
+ int state= s ? s->state : 0;
- if ( s && (s->state == _CS_CHARSET))
- bzero(&i->cs,sizeof(i->cs));
-
- if (s && (s->state == _CS_COLLATION))
- i->tailoring_length= 0;
+ switch (state) {
+ case 0:
+ i->loader->reporter(WARNING_LEVEL, "Unknown LDML tag: '%.*s'", len, attr);
+ break;
+ case _CS_CHARSET:
+ my_charset_file_reset_charset(i);
+ break;
+
+ case _CS_COLLATION:
+ my_charset_file_reset_collation(i);
+ break;
+
+ case _CS_RESET:
+ return tailoring_append(st, " &", 0, NULL);
+
+ default:
+ break;
+ }
return MY_XML_OK;
}
@@ -207,8 +492,60 @@ static int cs_leave(MY_XML_PARSER *st,co
switch(state){
case _CS_COLLATION:
- rc= i->add_collation ? i->add_collation(&i->cs) : MY_XML_OK;
+ if (i->tailoring_length)
+ i->cs.tailoring= i->tailoring;
+ rc= i->loader->add_collation ? i->loader->add_collation(&i->cs) : MY_XML_OK;
+ break;
+
+ /* Rules: Logical Reset Positions */
+ case _CS_RESET_FIRST_NON_IGNORABLE:
+ rc= tailoring_append(st, "[first non-ignorable]", 0, NULL);
+ break;
+
+ case _CS_RESET_LAST_NON_IGNORABLE:
+ rc= tailoring_append(st, "[last non-ignorable]", 0, NULL);
+ break;
+
+ case _CS_RESET_FIRST_PRIMARY_IGNORABLE:
+ rc= tailoring_append(st, "[first primary ignorable]", 0, NULL);
+ break;
+
+ case _CS_RESET_LAST_PRIMARY_IGNORABLE:
+ rc= tailoring_append(st, "[last primary ignorable]", 0, NULL);
+ break;
+
+ case _CS_RESET_FIRST_SECONDARY_IGNORABLE:
+ rc= tailoring_append(st, "[first secondary ignorable]", 0, NULL);
+ break;
+
+ case _CS_RESET_LAST_SECONDARY_IGNORABLE:
+ rc= tailoring_append(st, "[last secondary ignorable]", 0, NULL);
+ break;
+
+ case _CS_RESET_FIRST_TERTIARY_IGNORABLE:
+ rc= tailoring_append(st, "[first tertiary ignorable]", 0, NULL);
+ break;
+
+ case _CS_RESET_LAST_TERTIARY_IGNORABLE:
+ rc= tailoring_append(st, "[last tertiary ignorable]", 0, NULL);
break;
+
+ case _CS_RESET_FIRST_TRAILING:
+ rc= tailoring_append(st, "[first trailing]", 0, NULL);
+ break;
+
+ case _CS_RESET_LAST_TRAILING:
+ rc= tailoring_append(st, "[last trailing]", 0, NULL);
+ break;
+
+ case _CS_RESET_FIRST_VARIABLE:
+ rc= tailoring_append(st, "[first variable]", 0, NULL);
+ break;
+
+ case _CS_RESET_LAST_VARIABLE:
+ rc= tailoring_append(st, "[last variable]", 0, NULL);
+ break;
+
default:
rc=MY_XML_OK;
}
@@ -216,14 +553,39 @@ static int cs_leave(MY_XML_PARSER *st,co
}
+static const char *diff_fmt[5]=
+{
+ "<%.*s",
+ "<<%.*s",
+ "<<<%.*s",
+ "<<<<%.*s",
+ "=%.*s"
+};
+
+
+static const char *context_diff_fmt[5]=
+{
+ "<%.*s|%.*s",
+ "<<%.*s|%.*s",
+ "<<<%.*s|%.*s",
+ "<<<<%.*s|%.*s",
+ "=%.*s|%.*s"
+};
+
+
static int cs_value(MY_XML_PARSER *st,const char *attr, size_t len)
{
struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
struct my_cs_file_section_st *s;
int state= (int)((s=cs_file_sec(st->attr, strlen(st->attr))) ? s->state :
0);
-
+ int rc= MY_XML_OK;
+
switch (state) {
+ case _CS_MISC:
+ case _CS_FAMILY:
+ case _CS_ORDER:
+ break;
case _CS_ID:
i->cs.number= strtol(attr,(char**)NULL,10);
break;
@@ -242,18 +604,6 @@ static int cs_value(MY_XML_PARSER *st,co
case _CS_CSDESCRIPT:
i->cs.comment=mstr(i->comment,attr,len,MY_CS_CSDESCR_SIZE-1);
break;
- case _CS_UCA_VERSION:
- if (sizeof(i->tailoring) > len + sizeof("[version %.*s]"))
- {
- /*
- We cannot use my_snprintf() here, because ctype.o is
- used to build conf_to_src, which must require minimun
- dependency.
- */
- sprintf(i->tailoring, "[version %.*s]", (int) len, attr);
- i->tailoring_length= strlen(i->tailoring);
- }
- break;
case _CS_FLAG:
if (!strncmp("primary",attr,len))
i->cs.state|= MY_CS_PRIMARY;
@@ -282,55 +632,176 @@ static int cs_value(MY_XML_PARSER *st,co
fill_uchar(i->ctype,MY_CS_CTYPE_TABLE_SIZE,attr,len);
i->cs.ctype=i->ctype;
break;
+
+ /* Special purpose commands */
+ case _CS_UCA_VERSION:
+ rc= tailoring_append(st, "[version %.*s]", len, attr);
+ break;
+
+ case _CS_CL_SUPPRESS_CONTRACTIONS:
+ rc= tailoring_append(st, "[suppress contractions %.*s]", len, attr);
+ break;
+
+ case _CS_CL_OPTIMIZE:
+ rc= tailoring_append(st, "[optimize %.*s]", len, attr);
+ break;
+
+ /* Collation Settings */
+ case _CS_ST_STRENGTH:
+ /* 1, 2, 3, 4, 5, or primary, secondary, tertiary, quaternary, identical */
+ rc= tailoring_append(st, "[strength %.*s]", len, attr);
+ break;
+
+ case _CS_ST_ALTERNATE:
+ /* non-ignorable, shifted */
+ rc= tailoring_append(st, "[alternate %.*s]", len, attr);
+ break;
+
+ case _CS_ST_BACKWARDS:
+ /* on, off, 2 */
+ rc= tailoring_append(st, "[backwards %.*s]", len, attr);
+ break;
+
+ case _CS_ST_NORMALIZATION:
+ /*
+ TODO for WL#896: check collations for normalization: vi.xml
+ We want precomposed characters work well at this point.
+ */
+ /* on, off */
+ rc= tailoring_append(st, "[normalization %.*s]", len, attr);
+ break;
+
+ case _CS_ST_CASE_LEVEL:
+ /* on, off */
+ rc= tailoring_append(st, "[caseLevel %.*s]", len, attr);
+ break;
+
+ case _CS_ST_CASE_FIRST:
+ /* upper, lower, off */
+ rc= tailoring_append(st, "[caseFirst %.*s]", len, attr);
+ break;
+
+ case _CS_ST_HIRAGANA_QUATERNARY:
+ /* on, off */
+ rc= tailoring_append(st, "[hiraganaQ %.*s]", len, attr);
+ break;
+
+ case _CS_ST_NUMERIC:
+ /* on, off */
+ rc= tailoring_append(st, "[numeric %.*s]", len, attr);
+ break;
+
+ case _CS_ST_VARIABLE_TOP:
+ /* TODO for WL#896: check value format */
+ rc= tailoring_append(st, "[variableTop %.*s]", len, attr);
+ break;
+
+ case _CS_ST_MATCH_BOUNDARIES:
+ /* none, whole-character, whole-word */
+ rc= tailoring_append(st, "[match-boundaries %.*s]", len, attr);
+ break;
+
+ case _CS_ST_MATCH_STYLE:
+ /* minimal, medial, maximal */
+ rc= tailoring_append(st, "[match-style %.*s]", len, attr);
+ break;
+
+
+ /* Rules */
case _CS_RESET:
+ rc= tailoring_append(st, "%.*s", len, attr);
+ break;
+
case _CS_DIFF1:
case _CS_DIFF2:
case _CS_DIFF3:
+ case _CS_DIFF4:
case _CS_IDENTICAL:
+ rc= tailoring_append(st, diff_fmt[state - _CS_DIFF1], len, attr);
+ break;
+
+
+ /* Rules: Expansion */
+ case _CS_EXP_EXTEND:
+ rc= tailoring_append(st, " / %.*s", len, attr);
+ break;
+
+ case _CS_EXP_DIFF1:
+ case _CS_EXP_DIFF2:
+ case _CS_EXP_DIFF3:
+ case _CS_EXP_DIFF4:
+ case _CS_EXP_IDENTICAL:
+ if (i->context[0])
{
- /*
- Convert collation description from
- Locale Data Markup Language (LDML)
- into ICU Collation Customization expression.
- */
- char arg[16];
- const char *cmd[]= {"&","<","<<","<<<","="};
- i->cs.tailoring= i->tailoring;
- mstr(arg,attr,len,sizeof(arg)-1);
- if (i->tailoring_length + 20 < sizeof(i->tailoring))
- {
- char *dst= i->tailoring_length + i->tailoring;
- i->tailoring_length+= sprintf(dst," %s %s",cmd[state-_CS_RESET],arg);
- }
+ rc= tailoring_append2(st, context_diff_fmt[state - _CS_EXP_DIFF1],
+ strlen(i->context), i->context, len, attr);
+ i->context[0]= 0;
}
+ else
+ rc= tailoring_append(st, diff_fmt[state - _CS_EXP_DIFF1], len, attr);
+ break;
+
+ /* Rules: Context */
+ case _CS_CONTEXT:
+ if (len < sizeof(i->context) + 1)
+ {
+ memcpy(i->context, attr, len);
+ i->context[len]= '\0';
+ }
+ break;
+
+ /* Rules: Abbreviating Ordering Specifications */
+ case _CS_A_DIFF1:
+ case _CS_A_DIFF2:
+ case _CS_A_DIFF3:
+ case _CS_A_DIFF4:
+ case _CS_A_IDENTICAL:
+ rc= tailoring_append_abbreviation(st, diff_fmt[state - _CS_A_DIFF1], len, attr);
+ break;
+
+ /* Rules: Placing Characters Before Others */
+ case _CS_RESET_BEFORE:
+ /*
+ TODO for WL#896: Add this check into text customization parser:
+ It is an error if the strength of the before relation is not identical
+ to the relation after the reset. We'll need this for WL#896.
+ */
+ rc= tailoring_append(st, "[before %.*s]", len, attr);
+ break;
+
+
+ default:
+ break;
}
- return MY_XML_OK;
+
+ return rc;
}
-my_bool my_parse_charset_xml(const char *buf, size_t len,
- int (*add_collation)(CHARSET_INFO *cs),
- char *error, size_t errsize)
+my_bool
+my_parse_charset_xml(MY_CHARSET_LOADER *loader, const char *buf, size_t len)
{
MY_XML_PARSER p;
- struct my_cs_file_info i;
+ struct my_cs_file_info info;
my_bool rc;
+ my_charset_file_init(&info);
my_xml_parser_create(&p);
my_xml_set_enter_handler(&p,cs_enter);
my_xml_set_value_handler(&p,cs_value);
my_xml_set_leave_handler(&p,cs_leave);
- i.add_collation= add_collation;
- my_xml_set_user_data(&p,(void*)&i);
+ info.loader= loader;
+ my_xml_set_user_data(&p, (void *) &info);
rc= (my_xml_parse(&p,buf,len) == MY_XML_OK) ? FALSE : TRUE;
my_xml_parser_free(&p);
+ my_charset_file_free(&info);
if (rc != MY_XML_OK)
{
const char *errstr= my_xml_error_string(&p);
- if (errsize > 32 + strlen(errstr))
+ if (sizeof(loader->error) > 32 + strlen(errstr))
{
/* We cannot use my_snprintf() here. See previous comment. */
- sprintf(error, "at line %d pos %d: %s",
+ sprintf(loader->error, "at line %d pos %d: %s",
my_xml_error_lineno(&p)+1,
(int) my_xml_error_pos(&p),
my_xml_error_string(&p));
Attachment: [text/bzr-bundle] bzr/bar@mysql.com-20101220083044-g1cxtta5cmemr8hp.bundle
| Thread |
|---|
| • bzr commit into mysql-trunk-bugfixing branch (bar:3447) WL#5624 | Alexander Barkov | 20 Dec |