diff options
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/Makefile.am | 9 | ||||
-rw-r--r-- | mysys/charset.c | 450 | ||||
-rw-r--r-- | mysys/charset2html.c | 129 | ||||
-rw-r--r-- | mysys/default.c | 10 | ||||
-rw-r--r-- | mysys/hash.c | 44 | ||||
-rw-r--r-- | mysys/mf_casecnv.c | 254 | ||||
-rw-r--r-- | mysys/mf_dirname.c | 6 | ||||
-rw-r--r-- | mysys/mf_format.c | 6 | ||||
-rw-r--r-- | mysys/mf_iocache2.c | 2 | ||||
-rw-r--r-- | mysys/mf_soundex.c | 21 | ||||
-rw-r--r-- | mysys/mf_wfile.c | 7 | ||||
-rw-r--r-- | mysys/my_error.c | 2 | ||||
-rw-r--r-- | mysys/my_getwd.c | 3 | ||||
-rw-r--r-- | mysys/my_handler.c | 404 | ||||
-rw-r--r-- | mysys/my_init.c | 3 | ||||
-rw-r--r-- | mysys/my_vsnprintf.c | 2 | ||||
-rw-r--r-- | mysys/test_charset.c | 41 | ||||
-rw-r--r-- | mysys/tree.c | 190 | ||||
-rw-r--r-- | mysys/typelib.c | 4 |
19 files changed, 1073 insertions, 514 deletions
diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 4ff1b04fc79..8da25ad101a 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -51,15 +51,17 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\ default.c my_compress.c checksum.c raid.cc \ my_net.c my_semaphore.c my_port.c \ my_vsnprintf.c charset.c my_bitmap.c my_bit.c md5.c \ - my_gethostbyname.c rijndael.c my_aes.c sha1.c + my_gethostbyname.c rijndael.c my_aes.c sha1.c \ + my_handler.c EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ thr_mutex.c thr_rwlock.c libmysys_a_LIBADD = @THREAD_LOBJECTS@ # test_fn removed 980815 since it not upp to date test_dir -noinst_PROGRAMS = test_charset @THREAD_LPROGRAMS@ +noinst_PROGRAMS = test_charset charset2html @THREAD_LPROGRAMS@ # test_dir_DEPENDENCIES= $(LIBRARIES) # testhash_DEPENDENCIES= $(LIBRARIES) test_charset_DEPENDENCIES= $(LIBRARIES) +charset2html_DEPENDENCIES= $(LIBRARIES) EXTRA_PROGRAMS = DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ @@ -112,6 +114,9 @@ test_dir: test_dir.c $(LIBRARIES) test_charset: test_charset.c $(LIBRARIES) $(LINK) $(FLAGS) -DMAIN $(srcdir)/test_charset.c $(LDADD) $(LIBS) +charset2html: charset2html.c $(LIBRARIES) + $(LINK) $(FLAGS) -DMAIN $(srcdir)/charset2html.c $(LDADD) $(LIBS) + testhash: testhash.c $(LIBRARIES) $(LINK) $(FLAGS) -DMAIN $(srcdir)/testhash.c $(LDADD) $(LIBS) diff --git a/mysys/charset.c b/mysys/charset.c index 1001b76f417..691a4233269 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -20,15 +20,10 @@ #include <m_string.h> #include <my_dir.h> -typedef struct cs_id_st { - char *name; - uint number; -} CS_ID; const char *charsets_dir = NULL; -static DYNAMIC_ARRAY cs_info_table; -static CS_ID **available_charsets; static int charset_initialized=0; +CHARSET_INFO all_charsets[256]; #define MAX_LINE 1024 @@ -36,6 +31,7 @@ static int charset_initialized=0; #define TO_LOWER_TABLE_SIZE 256 #define TO_UPPER_TABLE_SIZE 256 #define SORT_ORDER_TABLE_SIZE 256 +#define TO_UNI_TABLE_SIZE 256 struct simpleconfig_buf_st { FILE *f; @@ -43,24 +39,6 @@ struct simpleconfig_buf_st { char *p; }; -static uint num_from_csname(CS_ID **cs, const char *name) -{ - CS_ID **c; - for (c = cs; *c; ++c) - if (!strcmp((*c)->name, name)) - return (*c)->number; - return 0; /* this mimics find_type() */ -} - -static char *name_from_csnum(CS_ID **cs, uint number) -{ - CS_ID **c; - if(cs) - for (c = cs; *c; ++c) - if ((*c)->number == number) - return (*c)->name; - return (char*) "?"; /* this mimics find_type() */ -} static my_bool get_word(struct simpleconfig_buf_st *fb, char *buf) { @@ -68,7 +46,7 @@ static my_bool get_word(struct simpleconfig_buf_st *fb, char *buf) for (;;) { - while (isspace(*endptr)) + while (my_isspace(system_charset_info, *endptr)) ++endptr; if (*endptr && *endptr != '#') /* Not comment */ break; /* Found something */ @@ -77,7 +55,7 @@ static my_bool get_word(struct simpleconfig_buf_st *fb, char *buf) endptr = fb->buf; } - while (!isspace(*endptr)) + while (!my_isspace(system_charset_info, *endptr)) *buf++= *endptr++; *buf=0; fb->p = endptr; @@ -108,13 +86,11 @@ char *get_charsets_dir(char *buf) } -static my_bool read_charset_index(CS_ID ***charsets, myf myflags) +static my_bool read_charset_index(myf myflags) { struct simpleconfig_buf_st fb; char buf[MAX_LINE], num_buf[MAX_LINE]; - DYNAMIC_ARRAY cs; - CS_ID *csid; - + strmov(get_charsets_dir(buf), "Index"); if ((fb.f = my_fopen(buf, O_RDONLY, myflags)) == NULL) @@ -122,13 +98,12 @@ static my_bool read_charset_index(CS_ID ***charsets, myf myflags) fb.buf[0] = '\0'; fb.p = fb.buf; - if (my_init_dynamic_array(&cs, sizeof(CS_ID *), 32, 32)) - return TRUE; - + while (!get_word(&fb, buf) && !get_word(&fb, num_buf)) { uint csnum; uint length; + CHARSET_INFO *cs; if (!(csnum = atoi(num_buf))) { @@ -137,64 +112,76 @@ static my_bool read_charset_index(CS_ID ***charsets, myf myflags) return TRUE; } - if (!(csid = (CS_ID*) my_once_alloc(sizeof(CS_ID), myflags)) || - !(csid->name= + cs=&all_charsets[csnum]; + + if (!(cs->name= (char*) my_once_alloc(length= (uint) strlen(buf)+1, myflags))) { my_fclose(fb.f,myflags); return TRUE; } - memcpy(csid->name,buf,length); - csid->number = csnum; - - insert_dynamic(&cs, (gptr) &csid); + memcpy((char*)cs->name,buf,length); + cs->number=csnum; } my_fclose(fb.f,myflags); - - if (!(*charsets = - (CS_ID **) my_once_alloc((cs.elements + 1) * sizeof(CS_ID *), myflags))) - return TRUE; - /* unwarranted chumminess with dynamic_array implementation? */ - memcpy((byte *) *charsets, cs.buffer, cs.elements * sizeof(CS_ID *)); - (*charsets)[cs.elements] = NULL; - delete_dynamic(&cs); - return FALSE; } +static void set_max_sort_char(CHARSET_INFO *cs) +{ + uchar max_char; + uint i; + + if (!cs->sort_order) + return; + + max_char=cs->sort_order[(uchar) cs->max_sort_char]; + for (i = 0; i < 256; i++) + { + if ((uchar) cs->sort_order[i] > max_char) + { + max_char=(uchar) cs->sort_order[i]; + cs->max_sort_char= (char) i; + } + } +} static my_bool init_available_charsets(myf myflags) { - my_bool error=0; + my_bool error=FALSE; /* We have to use charset_initialized to not lock on THR_LOCK_charset inside get_internal_charset... */ if (!charset_initialized) { + CHARSET_INFO *cs; /* To make things thread safe we are not allowing other threads to interfere while we may changing the cs_info_table */ pthread_mutex_lock(&THR_LOCK_charset); - if (!cs_info_table.buffer) /* If not initialized */ + + bzero(&all_charsets,sizeof(all_charsets)); + + /* Copy compiled charsets */ + + for (cs=compiled_charsets; cs->name; cs++) { - my_init_dynamic_array(&cs_info_table, sizeof(CHARSET_INFO*), 16, 8); - error = read_charset_index(&available_charsets, myflags); + all_charsets[cs->number]=cs[0]; + set_max_sort_char(&all_charsets[cs->number]); } + error = read_charset_index(myflags); charset_initialized=1; pthread_mutex_unlock(&THR_LOCK_charset); } - if(!available_charsets || !available_charsets[0]) - error = TRUE; return error; } void free_charsets(void) { - delete_dynamic(&cs_info_table); charset_initialized=0; } @@ -214,27 +201,123 @@ static my_bool fill_array(uchar *array, int sz, struct simpleconfig_buf_st *fb) return 0; } +static my_bool fill_uint16_array(uint16 *array, int sz, struct simpleconfig_buf_st *fb) +{ + char buf[MAX_LINE]; + while (sz--) + { + if (get_word(fb, buf)) + { + DBUG_PRINT("error",("get_word failed, expecting %d more words", sz + 1)); + return 1; + } + *array++ = (uint16) strtol(buf, NULL, 16); + } + return 0; +} + -static void get_charset_conf_name(uint cs_number, char *buf) +static void get_charset_conf_name(const char *cs_name, char *buf) { - strxmov(get_charsets_dir(buf), - name_from_csnum(available_charsets, cs_number), ".conf", NullS); + strxmov(get_charsets_dir(buf), cs_name, ".conf", NullS); } +typedef struct { + int nchars; + MY_UNI_IDX uidx; +} uni_idx; + +#define PLANE_SIZE 0x100 +#define PLANE_NUM 0x100 +#define PLANE_NUMBER(x) (((x)>>8) % PLANE_NUM) + +static int pcmp(const void * f, const void * s) +{ + const uni_idx *F=(const uni_idx*)f; + const uni_idx *S=(const uni_idx*)s; + int res; + + if(!(res=((S->nchars)-(F->nchars)))) + res=((F->uidx.from)-(S->uidx.to)); + return res; +} -static my_bool read_charset_file(uint cs_number, CHARSET_INFO *set, +static my_bool create_fromuni(CHARSET_INFO *cs){ + uni_idx idx[PLANE_NUM]; + int i,n; + + /* Clear plane statistics */ + bzero(idx,sizeof(idx)); + + /* Count number of characters in each plane */ + for(i=0;i<0x100;i++) + { + uint16 wc=cs->tab_to_uni[i]; + int pl= PLANE_NUMBER(wc); + + if(wc || !i) + { + if(!idx[pl].nchars) + { + idx[pl].uidx.from=wc; + idx[pl].uidx.to=wc; + }else + { + idx[pl].uidx.from=wc<idx[pl].uidx.from?wc:idx[pl].uidx.from; + idx[pl].uidx.to=wc>idx[pl].uidx.to?wc:idx[pl].uidx.to; + } + idx[pl].nchars++; + } + } + + /* Sort planes in descending order */ + qsort(&idx,PLANE_NUM,sizeof(uni_idx),&pcmp); + + for(i=0;i<PLANE_NUM;i++) + { + int ch,numchars; + + /* Skip empty plane */ + if(!idx[i].nchars) + break; + + numchars=idx[i].uidx.to-idx[i].uidx.from+1; + idx[i].uidx.tab=(unsigned char*)my_once_alloc(numchars*sizeof(*idx[i].uidx.tab),MYF(MY_WME)); + bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab)); + + for(ch=1;ch<PLANE_SIZE;ch++) + { + uint16 wc=cs->tab_to_uni[ch]; + if(wc>=idx[i].uidx.from && wc<=idx[i].uidx.to && wc) + { + int ofs=wc-idx[i].uidx.from; + idx[i].uidx.tab[ofs]=ch; + } + } + } + + /* Allocate and fill reverse table for each plane */ + n=i; + cs->tab_from_uni=(MY_UNI_IDX*)my_once_alloc(sizeof(MY_UNI_IDX)*(n+1),MYF(MY_WME)); + for(i=0;i<n;i++) + cs->tab_from_uni[i]=idx[i].uidx; + + /* Set end-of-list marker */ + bzero(&cs->tab_from_uni[i],sizeof(MY_UNI_IDX)); + return FALSE; +} + + +static my_bool read_charset_file(const char *cs_name, CHARSET_INFO *set, myf myflags) { struct simpleconfig_buf_st fb; char buf[FN_REFLEN]; my_bool result; DBUG_ENTER("read_charset_file"); - DBUG_PRINT("enter",("cs_number: %d", cs_number)); - - if (cs_number <= 0) - DBUG_RETURN(TRUE); + DBUG_PRINT("enter",("cs_name: %s", cs_name)); - get_charset_conf_name(cs_number, buf); + get_charset_conf_name(cs_name, buf); DBUG_PRINT("info",("file name: %s", buf)); if ((fb.f = my_fopen(buf, O_RDONLY, myflags)) == NULL) @@ -247,7 +330,8 @@ static my_bool read_charset_file(uint cs_number, CHARSET_INFO *set, if (fill_array(set->ctype, CTYPE_TABLE_SIZE, &fb) || fill_array(set->to_lower, TO_LOWER_TABLE_SIZE, &fb) || fill_array(set->to_upper, TO_UPPER_TABLE_SIZE, &fb) || - fill_array(set->sort_order, SORT_ORDER_TABLE_SIZE, &fb)) + fill_array(set->sort_order, SORT_ORDER_TABLE_SIZE, &fb) || + fill_uint16_array(set->tab_to_uni,TO_UNI_TABLE_SIZE,&fb)) result=TRUE; my_fclose(fb.f, MYF(0)); @@ -255,84 +339,84 @@ static my_bool read_charset_file(uint cs_number, CHARSET_INFO *set, } -uint get_charset_number(const char *charset_name) -{ - uint number=compiled_charset_number(charset_name); - if (number) - return number; - if (init_available_charsets(MYF(0))) /* If it isn't initialized */ - return 0; - return num_from_csname(available_charsets, charset_name); -} - -const char *get_charset_name(uint charset_number) -{ - const char *name=compiled_charset_name(charset_number); - if (*name != '?') - return name; - if (init_available_charsets(MYF(0))) /* If it isn't initialized */ - return "?"; - return name_from_csnum(available_charsets, charset_number); -} - - -static CHARSET_INFO *find_charset(CHARSET_INFO **table, uint cs_number, - size_t tablesz) +static CHARSET_INFO *add_charset(uint cs_number, myf flags) { - uint i; - for (i = 0; i < tablesz; ++i) - if (table[i]->number == cs_number) - return table[i]; - return NULL; -} + CHARSET_INFO *cs; + uchar tmp_ctype[CTYPE_TABLE_SIZE]; + uchar tmp_to_lower[TO_LOWER_TABLE_SIZE]; + uchar tmp_to_upper[TO_UPPER_TABLE_SIZE]; + uchar tmp_sort_order[SORT_ORDER_TABLE_SIZE]; + uint16 tmp_to_uni[TO_UNI_TABLE_SIZE]; -static CHARSET_INFO *find_charset_by_name(CHARSET_INFO **table, - const char *name, size_t tablesz) -{ - uint i; - for (i = 0; i < tablesz; ++i) - if (!strcmp(table[i]->name,name)) - return table[i]; - return NULL; -} + /* Note: cs->name is already initialized */ + + cs=&all_charsets[cs_number]; -static CHARSET_INFO *add_charset(uint cs_number, const char *cs_name, myf flags) -{ - CHARSET_INFO tmp_cs,*cs; - uchar tmp_ctype[CTYPE_TABLE_SIZE]; - uchar tmp_to_lower[TO_LOWER_TABLE_SIZE]; - uchar tmp_to_upper[TO_UPPER_TABLE_SIZE]; - uchar tmp_sort_order[SORT_ORDER_TABLE_SIZE]; - - /* Don't allocate memory if we are not sure we can find the char set */ - cs= &tmp_cs; - bzero((char*) cs, sizeof(*cs)); cs->ctype=tmp_ctype; cs->to_lower=tmp_to_lower; cs->to_upper=tmp_to_upper; cs->sort_order=tmp_sort_order; - if (read_charset_file(cs_number, cs, flags)) + cs->tab_to_uni=tmp_to_uni; + if (read_charset_file(cs->name, cs, flags)) return NULL; - cs = (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO), - MYF(MY_WME)); - *cs=tmp_cs; - cs->name = (char *) my_once_alloc((uint) strlen(cs_name)+1, MYF(MY_WME)); cs->ctype = (uchar*) my_once_alloc(CTYPE_TABLE_SIZE, MYF(MY_WME)); cs->to_lower = (uchar*) my_once_alloc(TO_LOWER_TABLE_SIZE, MYF(MY_WME)); cs->to_upper = (uchar*) my_once_alloc(TO_UPPER_TABLE_SIZE, MYF(MY_WME)); cs->sort_order=(uchar*) my_once_alloc(SORT_ORDER_TABLE_SIZE, MYF(MY_WME)); + cs->tab_to_uni=(uint16*)my_once_alloc(TO_UNI_TABLE_SIZE*sizeof(uint16), MYF(MY_WME)); cs->number = cs_number; - memcpy((char*) cs->name, (char*) cs_name, strlen(cs_name) + 1); memcpy((char*) cs->ctype, (char*) tmp_ctype, sizeof(tmp_ctype)); memcpy((char*) cs->to_lower, (char*) tmp_to_lower, sizeof(tmp_to_lower)); memcpy((char*) cs->to_upper, (char*) tmp_to_upper, sizeof(tmp_to_upper)); memcpy((char*) cs->sort_order, (char*) tmp_sort_order, sizeof(tmp_sort_order)); - insert_dynamic(&cs_info_table, (gptr) &cs); + memcpy((char*) cs->tab_to_uni, (char*) tmp_to_uni, sizeof(tmp_to_uni)); + + cs->caseup_str = my_caseup_str_8bit; + cs->casedn_str = my_casedn_str_8bit; + cs->caseup = my_caseup_8bit; + cs->casedn = my_casedn_8bit; + cs->strcasecmp = my_strcasecmp_8bit; + cs->strncasecmp = my_strncasecmp_8bit; + cs->mb_wc = my_mb_wc_8bit; + cs->wc_mb = my_wc_mb_8bit; + + set_max_sort_char(cs); + create_fromuni(cs); + return cs; } + +uint get_charset_number(const char *charset_name) +{ + CHARSET_INFO *cs; + if (init_available_charsets(MYF(0))) /* If it isn't initialized */ + return 0; + + for (cs = all_charsets; cs < all_charsets+255; ++cs) + if ( cs->name && !strcmp(cs->name, charset_name)) + return cs->number; + + return 0; /* this mimics find_type() */ +} + + +const char *get_charset_name(uint charset_number) +{ + CHARSET_INFO *cs; + if (init_available_charsets(MYF(0))) /* If it isn't initialized */ + return "?"; + + cs=&all_charsets[charset_number]; + if ( (cs->number==charset_number) && cs->name ) + return (char*) cs->name; + + return (char*) "?"; /* this mimics find_type() */ +} + + static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) { CHARSET_INFO *cs; @@ -341,10 +425,11 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) while we may changing the cs_info_table */ pthread_mutex_lock(&THR_LOCK_charset); - if (!(cs = find_charset((CHARSET_INFO**) cs_info_table.buffer, cs_number, - cs_info_table.elements))) - if (!(cs = find_compiled_charset(cs_number))) - cs=add_charset(cs_number, get_charset_name(cs_number), flags); + + cs = &all_charsets[cs_number]; + if (!(cs->state & (MY_CS_COMPILED | MY_CS_LOADED))) + cs=add_charset(cs_number, flags); + pthread_mutex_unlock(&THR_LOCK_charset); return cs; } @@ -352,25 +437,20 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) static CHARSET_INFO *get_internal_charset_by_name(const char *name, myf flags) { - CHARSET_INFO *cs; - /* - To make things thread safe we are not allowing other threads to interfere - while we may changing the cs_info_table - */ - pthread_mutex_lock(&THR_LOCK_charset); - if (!(cs = find_charset_by_name((CHARSET_INFO**) cs_info_table.buffer, name, - cs_info_table.elements))) - if (!(cs = find_compiled_charset_by_name(name))) - cs=add_charset(get_charset_number(name), name, flags); - pthread_mutex_unlock(&THR_LOCK_charset); - return cs; + uint cs_number=get_charset_number(name); + return cs_number ? get_internal_charset(cs_number,flags) : NULL; } + CHARSET_INFO *get_charset(uint cs_number, myf flags) { CHARSET_INFO *cs; (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + + if (!cs_number) + return NULL; + cs=get_internal_charset(cs_number, flags); if (!cs && (flags & MY_WME)) @@ -396,6 +476,7 @@ my_bool set_default_charset(uint cs, myf flags) DBUG_RETURN(TRUE); /* error */ } default_charset_info = new_charset; + system_charset_info = new_charset; DBUG_RETURN(FALSE); } @@ -428,6 +509,7 @@ my_bool set_default_charset_by_name(const char *cs_name, myf flags) } default_charset_info = new_charset; + system_charset_info = new_charset; DBUG_RETURN(FALSE); } @@ -466,7 +548,7 @@ char * list_charsets(myf want_flags) (void)init_available_charsets(MYF(0)); init_dynamic_string(&s, NullS, 256, 1024); - if (want_flags & MY_COMPILED_SETS) + if (want_flags & MY_CS_COMPILED) { CHARSET_INFO *cs; for (cs = compiled_charsets; cs->number > 0; cs++) @@ -476,82 +558,42 @@ char * list_charsets(myf want_flags) } } - if (want_flags & MY_CONFIG_SETS) + if (want_flags & MY_CS_CONFIG) { - CS_ID **c; + CHARSET_INFO *cs; char buf[FN_REFLEN]; MY_STAT status; - if((c=available_charsets)) - for (; *c; ++c) - { - if (charset_in_string((*c)->name, &s)) - continue; - get_charset_conf_name((*c)->number, buf); - if (!my_stat(buf, &status, MYF(0))) - continue; /* conf file doesn't exist */ - dynstr_append(&s, (*c)->name); - dynstr_append(&s, " "); - } + for (cs=all_charsets; cs < all_charsets+255; cs++) + { + if (!cs->name || charset_in_string(cs->name, &s)) + continue; + get_charset_conf_name(cs->name, buf); + if (!my_stat(buf, &status, MYF(0))) + continue; /* conf file doesn't exist */ + dynstr_append(&s, cs->name); + dynstr_append(&s, " "); + } } - if (want_flags & MY_INDEX_SETS) + if (want_flags & (MY_CS_INDEX|MY_CS_LOADED)) { - CS_ID **c; - for (c = available_charsets; *c; ++c) - charset_append(&s, (*c)->name); + CHARSET_INFO *cs; + for (cs = all_charsets; cs < all_charsets + 255; cs++) + if (cs->name && (cs->state & want_flags) ) + charset_append(&s, cs->name); } - - if (want_flags & MY_LOADED_SETS) + + if (s.length) { - uint i; - for (i = 0; i < cs_info_table.elements; i++) - charset_append(&s, - dynamic_element(&cs_info_table, i, CHARSET_INFO *)->name); + s.str[s.length - 1] = '\0'; /* chop trailing space */ + p = my_strdup(s.str, MYF(MY_WME)); } - s.str[s.length - 1] = '\0'; /* chop trailing space */ - p = my_strdup(s.str, MYF(MY_WME)); - dynstr_free(&s); - - return p; -} - -/**************************************************************************** -* Code for debugging. -****************************************************************************/ - - -static void _print_array(uint8 *data, uint size) -{ - uint i; - for (i = 0; i < size; ++i) + else { - if (i == 0 || i % 16 == size % 16) printf(" "); - printf(" %02x", data[i]); - if ((i+1) % 16 == size % 16) printf("\n"); + p = my_strdup("", MYF(MY_WME)); } -} - -/* _print_csinfo is called from test_charset.c */ -void _print_csinfo(CHARSET_INFO *cs) -{ - printf("%s #%d\n", cs->name, cs->number); - printf("ctype:\n"); _print_array(cs->ctype, 257); - printf("to_lower:\n"); _print_array(cs->to_lower, 256); - printf("to_upper:\n"); _print_array(cs->to_upper, 256); - printf("sort_order:\n"); _print_array(cs->sort_order, 256); - printf("collate: %3s (%d, %p, %p, %p, %p, %p)\n", - cs->strxfrm_multiply ? "yes" : "no", - cs->strxfrm_multiply, - cs->strcoll, - cs->strxfrm, - cs->strnncoll, - cs->strnxfrm, - cs->like_range); - printf("multi-byte: %3s (%d, %p, %p, %p)\n", - cs->mbmaxlen ? "yes" : "no", - cs->mbmaxlen, - cs->ismbchar, - cs->ismbhead, - cs->mbcharlen); + dynstr_free(&s); + + return p; } diff --git a/mysys/charset2html.c b/mysys/charset2html.c new file mode 100644 index 00000000000..0d6450a8116 --- /dev/null +++ b/mysys/charset2html.c @@ -0,0 +1,129 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + Written by Alexander Barkov to check what + a charset is in your favorite web browser +*/ + +#include <my_global.h> +#include <m_ctype.h> +#include <my_sys.h> +#include <mysql_version.h> + +#include <stdio.h> + +typedef struct char_info_st +{ + int cod; + int srt; + int uni; + int low; + int upp; + int ctp; +} MY_CH; + +static int chcmp(const void *vf, const void *vs) +{ + const MY_CH *f=vf; + const MY_CH *s=vs; + + return f->srt-s->srt ? f->srt-s->srt : f->uni-s->uni; +} + +static void print_cs(CHARSET_INFO *cs) +{ + uint i; + int srt; + int clr=0; + MY_CH ch[256]; + + printf("<HTML>\n"); + printf("<HEAD>\n"); + printf("</HEAD>\n"); + printf("<BODY><PRE>\n"); + printf("Charset %s\n",cs->name); + + printf("<TABLE>\n"); + printf("<TR><TH>Code<TH>Uni<TH>Sort<TH>Ctype<TH>Ch<TH>Lo<TH>Up</TR>"); + + for (i=0; i<256; i++) + { + ch[i].cod=i; + ch[i].srt=cs->sort_order[i]; + ch[i].uni=cs->tab_to_uni[i]; + ch[i].low=cs->tab_to_uni[cs->to_lower[i]]; + ch[i].upp=cs->tab_to_uni[cs->to_upper[i]]; + ch[i].ctp=cs->ctype[i+1]; + } + + qsort(ch,256,sizeof(MY_CH),&chcmp); + srt=ch[0].srt; + + for (i=0; i<256; i++) + { + clr = (srt!=ch[i].srt) ? !clr : clr; + + printf("<TR bgcolor=#%s>",clr ? "DDDDDD" : "EEEE99"); + printf("<TD>%02X",ch[i].cod); + printf("<TD>%04X",ch[i].uni); + printf("<TD>%d",ch[i].srt); + + printf("<TD>%s%s%s%s%s%s%s%s", + ch[i].ctp & _U ? "U" : "", + ch[i].ctp & _L ? "L" : "", + ch[i].ctp & _NMR ? "N" : "", + ch[i].ctp & _SPC ? "S" : "", + ch[i].ctp & _PNT ? "P" : "", + ch[i].ctp & _CTR ? "C" : "", + ch[i].ctp & _B ? "B" : "", + ch[i].ctp & _X ? "X" : ""); + + printf("<TD>&#%d;",ch[i].uni); + printf("<TD>&#%d;",ch[i].low); + printf("<TD>&#%d;",ch[i].upp); + printf("</TR>\n"); + srt=ch[i].srt; + } + printf("</TABLE>\n"); + printf("</PRE></BODY>\n"); + printf("</HTML>\n"); +} + + +int main(int argc, char **argv) { + const char *the_set = MYSQL_CHARSET; + int argcnt = 1; + + my_init(); + + if (argc > argcnt && argv[argcnt][0] == '-' && argv[argcnt][1] == '#') + DBUG_PUSH(argv[argcnt++]+2); + + if (argc > argcnt) + the_set = argv[argcnt++]; + + if (argc > argcnt) + charsets_dir = argv[argcnt++]; + + if (set_default_charset_by_name(the_set, MYF(MY_WME))) + return 1; + + print_cs(default_charset_info); + + return 0; +} diff --git a/mysys/default.c b/mysys/default.c index fdeeabf83eb..f5ada19dd78 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -247,7 +247,7 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, { line++; /* Ignore comment and empty lines */ - for (ptr=buff ; isspace(*ptr) ; ptr++ ) ; + for (ptr=buff ; my_isspace(system_charset_info,*ptr) ; ptr++ ) ; if (*ptr == '#' || *ptr == ';' || !*ptr) continue; if (*ptr == '[') /* Group name */ @@ -260,7 +260,7 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, name,line); goto err; } - for ( ; isspace(end[-1]) ; end--) ; /* Remove end space */ + for ( ; my_isspace(system_charset_info,end[-1]) ; end--) ;/* Remove end space */ end[0]=0; read_values=find_type(ptr,group,3) > 0; continue; @@ -276,7 +276,7 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, continue; if (!(end=value=strchr(ptr,'='))) end=strend(ptr); /* Option without argument */ - for ( ; isspace(end[-1]) ; end--) ; + for ( ; my_isspace(system_charset_info,end[-1]) ; end--) ; if (!value) { if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3))) @@ -289,9 +289,9 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, { /* Remove pre- and end space */ char *value_end; - for (value++ ; isspace(*value); value++) ; + for (value++ ; my_isspace(system_charset_info,*value); value++) ; value_end=strend(value); - for ( ; isspace(value_end[-1]) ; value_end--) ; + for ( ; my_isspace(system_charset_info,value_end[-1]) ; value_end--) ; if (value_end < value) /* Empty string */ value_end=value; if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3 + diff --git a/mysys/hash.c b/mysys/hash.c index eaea6d7503f..7fb634a05b9 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -31,12 +31,13 @@ static uint hash_mask(uint hashnr,uint buffmax,uint maxlength); static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); -static uint calc_hashnr(const byte *key,uint length); -static uint calc_hashnr_caseup(const byte *key,uint length); +static uint calc_hashnr(CHARSET_INFO *cs,const byte *key,uint length); +static uint calc_hashnr_caseup(CHARSET_INFO *cs, const byte *key,uint length); static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length); - -my_bool _hash_init(HASH *hash,uint size,uint key_offset,uint key_length, +my_bool +_hash_init(HASH *hash,CHARSET_INFO *charset, + uint size,uint key_offset,uint key_length, hash_get_key get_key, void (*free_element)(void*),uint flags CALLER_INFO_PROTO) { @@ -56,8 +57,14 @@ my_bool _hash_init(HASH *hash,uint size,uint key_offset,uint key_length, hash->get_key=get_key; hash->free=free_element; hash->flags=flags; + hash->charset=charset; if (flags & HASH_CASE_INSENSITIVE) - hash->calc_hashnr=calc_hashnr_caseup; + { + if (charset->hash_caseup) + hash->calc_hashnr=charset->hash_caseup; + else + hash->calc_hashnr=calc_hashnr_caseup; + } else hash->calc_hashnr=calc_hashnr; DBUG_RETURN(0); @@ -104,14 +111,16 @@ static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax, { uint length; byte *key=hash_key(hash,pos->data,&length,0); - return hash_mask((*hash->calc_hashnr)(key,length),buffmax,maxlength); + return hash_mask((*hash->calc_hashnr)(hash->charset,key,length), + buffmax,maxlength); } #ifndef NEW_HASH_FUNCTION /* Calc hashvalue for a key */ -static uint calc_hashnr(const byte *key,uint length) +static uint calc_hashnr(CHARSET_INFO *cs __attribute__((unused)), + const byte *key,uint length) { register uint nr=1, nr2=4; while (length--) @@ -124,12 +133,15 @@ static uint calc_hashnr(const byte *key,uint length) /* Calc hashvalue for a key, case indepenently */ -static uint calc_hashnr_caseup(const byte *key,uint length) +static uint calc_hashnr_caseup(CHARSET_INFO *cs, const byte *key,uint length) { register uint nr=1, nr2=4; + register uchar *map=cs->to_upper; + while (length--) { - nr^= (((nr & 63)+nr2)*((uint) (uchar) toupper(*key++)))+ (nr << 8); + nr^= (((nr & 63)+nr2)* + ((uint) (uchar) map[(uchar)*key++])) + (nr << 8); nr2+=3; } return((uint) nr); @@ -150,7 +162,7 @@ static uint calc_hashnr_caseup(const byte *key,uint length) * This works well on both numbers and strings. */ -uint calc_hashnr(const byte *key, uint len) +uint calc_hashnr(CHARSET_INFO *cs, const byte *key, uint len) { const byte *end=key+len; uint hash; @@ -162,14 +174,14 @@ uint calc_hashnr(const byte *key, uint len) return (hash); } -uint calc_hashnr_caseup(const byte *key, uint len) +uint calc_hashnr_caseup(CHARSET_INFO *cs, const byte *key, uint len) { const byte *end=key+len; uint hash; for (hash = 0; key < end; key++) { hash *= 16777619; - hash ^= (uint) (uchar) toupper(*key); + hash ^= (uint) (uchar) my_toupper(cs,*key); } return (hash); } @@ -184,7 +196,7 @@ uint rec_hashnr(HASH *hash,const byte *record) { uint length; byte *key=hash_key(hash,record,&length,0); - return (*hash->calc_hashnr)(key,length); + return (*hash->calc_hashnr)(hash->charset,key,length); } @@ -200,7 +212,7 @@ gptr hash_search(HASH *hash,const byte *key,uint length) flag=1; if (hash->records) { - idx=hash_mask((*hash->calc_hashnr)(key,length ? length : + idx=hash_mask((*hash->calc_hashnr)(hash->charset,key,length ? length : hash->key_length), hash->blength,hash->records); do @@ -273,7 +285,7 @@ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) byte *rec_key=hash_key(hash,pos->data,&rec_keylength,1); return (length && length != rec_keylength) || (hash->flags & HASH_CASE_INSENSITIVE ? - my_casecmp(rec_key,key,rec_keylength) : + my_strncasecmp(hash->charset, rec_key,key,rec_keylength) : memcmp(rec_key,key,rec_keylength)); } @@ -513,7 +525,7 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length) /* Search after record with key */ - idx=hash_mask((*hash->calc_hashnr)(old_key,(old_key_length ? + idx=hash_mask((*hash->calc_hashnr)(hash->charset, old_key,(old_key_length ? old_key_length : hash->key_length)), blength,records); diff --git a/mysys/mf_casecnv.c b/mysys/mf_casecnv.c index c037cbd0f16..631db18b1ed 100644 --- a/mysys/mf_casecnv.c +++ b/mysys/mf_casecnv.c @@ -28,269 +28,53 @@ #include <m_string.h> #endif -/* - Upcase string - - SYNOPSIS - str IN/OUT String to upcase - - RETURN VALUE - none - DESCRIPTION - Function changes input parameter so all chars it consist from - are replaced with matching one in upper case. - String should be writable with exception read-only empty string - constant is handled correctly. -*/ - - -void caseup_str(my_string str) -{ -#ifdef USE_MB - if (use_mb(default_charset_info)) - { - register uint32 l; - register char *end=str+strlen(str); - while (*str) - { - if ((l=my_ismbchar(default_charset_info, str,end))) str+=l; - else *str=toupper(*str),++str; - } - } - else -#endif - while (*str!=0) /* iterate till the end of string */ - { - *str= toupper(*str); - str++; - } -} /* caseup_str */ - - -/* - Downcase string - - SYNOPSIS - str IN/OUT String to downcase - - RETURN VALUE - none - DESCRIPTION - Function changes input parameter so all chars it consist from - are replaced with matching one in lower case. - String should be writable with exception read-only empty string - constant is handled correctly. -*/ - - -void casedn_str(my_string str) -{ -#ifdef USE_MB - if (use_mb(default_charset_info)) - { - register uint32 l; - register char *end=str+strlen(str); - while (*str) - { - if ((l=my_ismbchar(default_charset_info, str,end))) str+=l; - else *str=tolower(*str),++str; - } - } - else -#endif - while (*str!=0) /* iterate till the end of string */ - { - *str= tolower(*str); - str++; - } -} /* casedn_str */ - - - /* to uppercase */ - -void caseup(my_string str, uint length) -{ -#ifdef USE_MB - if (use_mb(default_charset_info)) - { - register uint32 l; - register char *end=str+length; - while (str<end) - { - if ((l=my_ismbchar(default_charset_info, str,end))) str+=l; - else *str=toupper(*str),++str; - } - } - else -#endif - for ( ; length>0 ; length--, str++) - *str= toupper(*str); -} /* caseup */ - - /* to lowercase */ - -void casedn(my_string str, uint length) -{ -#ifdef USE_MB - if (use_mb(default_charset_info)) - { - register uint32 l; - register char *end=str+length; - while (str<end) - { - if ((l=my_ismbchar(default_charset_info, str,end))) str+=l; - else *str=tolower(*str),++str; - } - } - else -#endif - for ( ; length>0 ; length--, str++) - *str= tolower(*str); -} /* casedn */ /* to sort-string that can be compared to get text in order */ -void case_sort(my_string str, uint length) +void case_sort(CHARSET_INFO *cs, my_string str, uint length) { + register uchar *map=cs->sort_order; + for ( ; length>0 ; length--, str++) - *str= (char) my_sort_order[(uchar) *str]; + *str= (char) map[(uchar) *str]; } /* case_sort */ - /* find string in another with no case_sensivity */ - -/* ToDo: This function should be modified to support multibyte charset. - However it is not used untill 3.23.5. - Wei He (hewei@mail.ied.ac.cn) -*/ - -my_string my_strcasestr(const char *str, const char *search) -{ - uchar *i,*j,*pos; - - pos=(uchar*) str; -skipp: - while (*pos != '\0') - { - if (toupper((uchar) *pos++) == toupper((uchar) *search)) - { - i=(uchar*) pos; j=(uchar*) search+1; - while (*j) - if (toupper(*i++) != toupper(*j++)) goto skipp; - return ((char*) pos-1); - } - } - return ((my_string) 0); -} /* strcstr */ - - - /* compare strings without regarding to case */ - -int my_strcasecmp(const char *s, const char *t) -{ -#ifdef USE_MB - if (use_mb(default_charset_info)) - { - register uint32 l; - register const char *end=s+strlen(s); - while (s<end) - { - if ((l=my_ismbchar(default_charset_info, s,end))) - { - while (l--) - if (*s++ != *t++) return 1; - } - else if (my_ismbhead(default_charset_info, *t)) return 1; - else if (toupper((uchar) *s++) != toupper((uchar) *t++)) return 1; - } - return *t; - } - else -#endif - { - while (toupper((uchar) *s) == toupper((uchar) *t++)) - if (!*s++) return 0; - return ((int) toupper((uchar) s[0]) - (int) toupper((uchar) t[-1])); - } -} - - -int my_casecmp(const char *s, const char *t, uint len) -{ -#ifdef USE_MB - if (use_mb(default_charset_info)) - { - register uint32 l; - register const char *end=s+len; - while (s<end) - { - if ((l=my_ismbchar(default_charset_info, s,end))) - { - while (l--) - if (*s++ != *t++) return 1; - } - else if (my_ismbhead(default_charset_info, *t)) return 1; - else if (toupper((uchar) *s++) != toupper((uchar) *t++)) return 1; - } - return 0; - } - else -#endif - { - while (len-- != 0 && toupper(*s++) == toupper(*t++)) ; - return (int) len+1; - } -} - - -int my_strsortcmp(const char *s, const char *t) -{ -#ifdef USE_STRCOLL - if (use_strcoll(default_charset_info)) - return my_strcoll(default_charset_info, (uchar *)s, (uchar *)t); - else -#endif - { - while (my_sort_order[(uchar) *s] == my_sort_order[(uchar) *t++]) - if (!*s++) return 0; - return ((int) my_sort_order[(uchar) s[0]] - - (int) my_sort_order[(uchar) t[-1]]); - } -} -int my_sortcmp(const char *s, const char *t, uint len) +int my_sortcmp(CHARSET_INFO *cs, const char *s, const char *t, uint len) { #ifdef USE_STRCOLL - if (use_strcoll(default_charset_info)) - return my_strnncoll(default_charset_info, - (uchar *)s, len, (uchar *)t, len); + if (use_strcoll(cs)) + return my_strnncoll(cs,(uchar *)s, len, (uchar *)t, len); else #endif { + register uchar *map=cs->sort_order; while (len--) { - if (my_sort_order[(uchar) *s++] != my_sort_order[(uchar) *t++]) - return ((int) my_sort_order[(uchar) s[-1]] - - (int) my_sort_order[(uchar) t[-1]]); + if (map[(uchar) *s++] != map[(uchar) *t++]) + return ((int) map[(uchar) s[-1]] - (int) map[(uchar) t[-1]]); } return 0; } } -int my_sortncmp(const char *s, uint s_len, const char *t, uint t_len) +int my_sortncmp(CHARSET_INFO *cs, + const char *s, uint s_len, + const char *t, uint t_len) { #ifdef USE_STRCOLL - if (use_strcoll(default_charset_info)) - return my_strnncoll(default_charset_info, - (uchar *)s, s_len, (uchar *)t, t_len); + if (use_strcoll(cs)) + return my_strnncoll(cs, (uchar *)s, s_len, (uchar *)t, t_len); else #endif { uint len= min(s_len,t_len); + register uchar *map=cs->sort_order; + while (len--) { - if (my_sort_order[(uchar) *s++] != my_sort_order[(uchar) *t++]) - return ((int) my_sort_order[(uchar) s[-1]] - - (int) my_sort_order[(uchar) t[-1]]); + if (map[(uchar) *s++] != map[(uchar) *t++]) + return ((int) map[(uchar) s[-1]] - (int) map[(uchar) t[-1]]); } return (int) (s_len - t_len); } diff --git a/mysys/mf_dirname.c b/mysys/mf_dirname.c index 6523abcdb12..320917c8f3e 100644 --- a/mysys/mf_dirname.c +++ b/mysys/mf_dirname.c @@ -108,11 +108,5 @@ char *convert_dirname(char *to, const char *from, const char *from_end) *to++=FN_LIBCHAR; *to=0; } -#ifdef FN_UPPER_CASE - caseup_str(to_org); -#endif -#ifdef FN_LOWER_CASE - casedn_str(to_org); -#endif return to; /* Pointer to end of dir */ } /* convert_dirname */ diff --git a/mysys/mf_format.c b/mysys/mf_format.c index ab1904da162..e68f7df9d83 100644 --- a/mysys/mf_format.c +++ b/mysys/mf_format.c @@ -91,12 +91,6 @@ my_string fn_format(my_string to, const char *name, const char *dir, name=buff; } pos=strmake(strmov(to,dev),name,length); -#ifdef FN_UPPER_CASE - caseup_str(to); -#endif -#ifdef FN_LOWER_CASE - casedn_str(to); -#endif (void) strmov(pos,ext); /* Don't convert extension */ } /* diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c index 344b7ac2251..8a7dfc7be09 100644 --- a/mysys/mf_iocache2.c +++ b/mysys/mf_iocache2.c @@ -267,7 +267,7 @@ uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args) /* Found one '%' */ } /* Skipp if max size is used (to be compatible with printf) */ - while (isdigit(*fmt) || *fmt == '.' || *fmt == '-') + while (my_isdigit(system_charset_info, *fmt) || *fmt == '.' || *fmt == '-') fmt++; if (*fmt == 's') /* String parameter */ { diff --git a/mysys/mf_soundex.c b/mysys/mf_soundex.c index 4f7aa7da601..459e304dfd7 100644 --- a/mysys/mf_soundex.c +++ b/mysys/mf_soundex.c @@ -34,24 +34,25 @@ #include <m_ctype.h> #include "my_static.h" -static char get_scode(char **ptr,pbool remove_garbage); +static char get_scode(CHARSET_INFO * cs, char **ptr,pbool remove_garbage); /* outputed string is 4 byte long */ /* out_pntr can be == in_pntr */ -void soundex(register my_string out_pntr, my_string in_pntr, +void soundex(CHARSET_INFO * cs,register my_string out_pntr, my_string in_pntr, pbool remove_garbage) { char ch,last_ch; reg3 my_string end; + register uchar *map=cs->to_upper; if (remove_garbage) { - while (*in_pntr && isspace(*in_pntr)) /* Skipp pre-space */ + while (*in_pntr && my_isspace(cs,*in_pntr)) /* Skipp pre-space */ in_pntr++; } - *out_pntr++ = toupper(*in_pntr); /* Copy first letter */ - last_ch = get_scode(&in_pntr,0); /* code of the first letter */ + *out_pntr++ = map[(uchar)*in_pntr]; /* Copy first letter */ + last_ch = get_scode(cs,&in_pntr,0); /* code of the first letter */ /* for the first 'double-letter */ /* check. */ end=out_pntr+3; /* Loop on input letters until */ @@ -59,7 +60,7 @@ void soundex(register my_string out_pntr, my_string in_pntr, /* letter code count = 3 */ in_pntr++; - while (out_pntr < end && (ch = get_scode(&in_pntr,remove_garbage)) != 0) + while (out_pntr < end && (ch = get_scode(cs,&in_pntr,remove_garbage)) != 0) { in_pntr++; if ((ch != '0') && (ch != last_ch)) /* if not skipped or double */ @@ -81,19 +82,19 @@ void soundex(register my_string out_pntr, my_string in_pntr, else return 0 */ -static char get_scode(char **ptr, pbool remove_garbage) +static char get_scode(CHARSET_INFO * cs,char **ptr, pbool remove_garbage) { uchar ch; if (remove_garbage) { - while (**ptr && !isalpha(**ptr)) + while (**ptr && !my_isalpha(cs,**ptr)) (*ptr)++; } - ch=toupper(**ptr); + ch=my_toupper(cs,**ptr); if (ch < 'A' || ch > 'Z') { - if (isalpha(ch)) /* If exetended alfa (country spec) */ + if (my_isalpha(cs,ch)) /* If exetended alfa (country spec) */ return '0'; /* threat as vokal */ return 0; /* Can't map */ } diff --git a/mysys/mf_wfile.c b/mysys/mf_wfile.c index e9e12c72755..3c10de1f238 100644 --- a/mysys/mf_wfile.c +++ b/mysys/mf_wfile.c @@ -54,13 +54,6 @@ WF_PACK *wf_comp(my_string str) for (pos=str ; *pos ; pos++) ant+= test(*pos == ' ' || *pos == ','); -#ifdef FN_UPPER_CASE - caseup(str,(int) (pos-str)); -#endif -#ifdef FN_LOWER_CASE - casedn(str,(int) (pos-str)); -#endif - if ((ret= (WF_PACK*) my_malloc((uint) ant*(sizeof(my_string*)+2)+ sizeof(WF_PACK)+ (uint) strlen(str)+1, MYF(MY_WME))) diff --git a/mysys/my_error.c b/mysys/my_error.c index 5ce061212b5..eaa126a31c1 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -69,7 +69,7 @@ int my_error(int nr,myf MyFlags, ...) else { /* Skipp if max size is used (to be compatible with printf) */ - while (isdigit(*tpos) || *tpos == '.' || *tpos == '-') + while (my_isdigit(system_charset_info, *tpos) || *tpos == '.' || *tpos == '-') tpos++; if (*tpos == 'l') /* Skipp 'l' argument */ tpos++; diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c index 22c6a4dbc2b..240b17ef87f 100644 --- a/mysys/my_getwd.c +++ b/mysys/my_getwd.c @@ -109,7 +109,8 @@ int my_setwd(const char *dir, myf MyFlags) uint drive,drives; pos++; /* Skipp FN_DEVCHAR */ - drive=(uint) (toupper(dir[0])-'A'+1); drives= (uint) -1; + drive=(uint) (my_toupper(system_charset_info,dir[0])-'A'+1); + drives= (uint) -1; if ((pos-(byte*) dir) == 2 && drive > 0 && drive < 32) { #ifdef OS2 diff --git a/mysys/my_handler.c b/mysys/my_handler.c new file mode 100644 index 00000000000..5b68b427f3a --- /dev/null +++ b/mysys/my_handler.c @@ -0,0 +1,404 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +#include "my_handler.h" + +int mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length, + uchar *b, uint b_length, my_bool part_key) +{ + int flag; + +#ifdef USE_STRCOLL + if (use_strcoll(charset_info)) + { + if (part_key && b_length < a_length) + a_length=b_length; + return my_strnncoll(charset_info, a, a_length, b, b_length); + } + else +#endif + { + uint length= min(a_length,b_length); + uchar *end= a+ length; + uchar *sort_order=charset_info->sort_order; + while (a < end) + if ((flag= (int) sort_order[*a++] - (int) sort_order[*b++])) + return flag; + } + if (part_key && b_length < a_length) + return 0; + return (int) (a_length-b_length); +} + +static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length, + my_bool part_key) +{ + uint length= min(a_length,b_length); + uchar *end= a+ length; + int flag; + + while (a < end) + if ((flag= (int) *a++ - (int) *b++)) + return flag; + if (part_key && b_length < a_length) + return 0; + return (int) (a_length-b_length); +} + +#define FCMP(A,B) ((int) (A) - (int) (B)) + +/* + Compare two keys + Returns <0, 0, >0 acording to which is bigger + Key_length specifies length of key to use. Number-keys can't be splited + If flag <> SEARCH_FIND compare also position +*/ + +int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, + register uchar *b, uint key_length, uint nextflag, + uint *diff_pos) +{ + int flag; + int16 s_1,s_2; + int32 l_1,l_2; + uint32 u_1,u_2; + float f_1,f_2; + double d_1,d_2; + uint next_key_length; + + *diff_pos=0; + for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++) + { + uchar *end; + uint piks=! (keyseg->flag & HA_NO_SORT); + (*diff_pos)++; + + /* Handle NULL part */ + if (keyseg->null_bit) + { + key_length--; + if (*a != *b && piks) + { + flag = (int) *a - (int) *b; + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + } + b++; + if (!*a++) /* If key was NULL */ + { + if (nextflag == (SEARCH_FIND | SEARCH_UPDATE)) + nextflag=SEARCH_SAME; /* Allow duplicate keys */ + next_key_length=key_length; + continue; /* To next key part */ + } + } + end= a+ min(keyseg->length,key_length); + next_key_length=key_length-keyseg->length; + + switch ((enum ha_base_keytype) keyseg->type) { + case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */ + if (keyseg->flag & HA_SPACE_PACK) + { + int a_length,b_length,pack_length; + get_key_length(a_length,a); + get_key_pack_length(b_length,pack_length,b); + next_key_length=key_length-b_length-pack_length; + + if (piks && + (flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length, + (my_bool) ((nextflag & SEARCH_PREFIX) && + next_key_length <= 0)))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a+=a_length; + b+=b_length; + break; + } + else + { + uint length=(uint) (end-a), a_length=length, b_length=length; + if (!(nextflag & SEARCH_PREFIX)) + { + while (a_length && a[a_length-1] == ' ') + a_length--; + while (b_length && b[b_length-1] == ' ') + b_length--; + } + if (piks && + (flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length, + (my_bool) ((nextflag & SEARCH_PREFIX) && + next_key_length <= 0)))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a=end; + b+=length; + } + break; + case HA_KEYTYPE_BINARY: + if (keyseg->flag & HA_SPACE_PACK) + { + int a_length,b_length,pack_length; + get_key_length(a_length,a); + get_key_pack_length(b_length,pack_length,b); + next_key_length=key_length-b_length-pack_length; + + if (piks && + (flag=compare_bin(a,a_length,b,b_length, + (my_bool) ((nextflag & SEARCH_PREFIX) && + next_key_length <= 0)))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a+=a_length; + b+=b_length; + break; + } + else + { + uint length=keyseg->length; + if (piks && + (flag=compare_bin(a,length,b,length, + (my_bool) ((nextflag & SEARCH_PREFIX) && + next_key_length <= 0)))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a+=length; + b+=length; + } + break; + case HA_KEYTYPE_VARTEXT: + { + int a_length,b_length,pack_length; + get_key_length(a_length,a); + get_key_pack_length(b_length,pack_length,b); + next_key_length=key_length-b_length-pack_length; + + if (piks && + (flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length, + (my_bool) ((nextflag & SEARCH_PREFIX) && + next_key_length <= 0)))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a+=a_length; + b+=b_length; + break; + } + break; + case HA_KEYTYPE_VARBINARY: + { + int a_length,b_length,pack_length; + get_key_length(a_length,a); + get_key_pack_length(b_length,pack_length,b); + next_key_length=key_length-b_length-pack_length; + + if (piks && + (flag=compare_bin(a,a_length,b,b_length, + (my_bool) ((nextflag & SEARCH_PREFIX) && + next_key_length <= 0)))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a+=a_length; + b+=b_length; + break; + } + break; + case HA_KEYTYPE_INT8: + { + int i_1= (int) *((signed char*) a); + int i_2= (int) *((signed char*) b); + if (piks && (flag = CMP_NUM(i_1,i_2))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a= end; + b++; + break; + } + case HA_KEYTYPE_SHORT_INT: + s_1= mi_sint2korr(a); + s_2= mi_sint2korr(b); + if (piks && (flag = CMP_NUM(s_1,s_2))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a= end; + b+= 2; /* sizeof(short int); */ + break; + case HA_KEYTYPE_USHORT_INT: + { + uint16 us_1,us_2; + us_1= mi_sint2korr(a); + us_2= mi_sint2korr(b); + if (piks && (flag = CMP_NUM(us_1,us_2))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a= end; + b+=2; /* sizeof(short int); */ + break; + } + case HA_KEYTYPE_LONG_INT: + l_1= mi_sint4korr(a); + l_2= mi_sint4korr(b); + if (piks && (flag = CMP_NUM(l_1,l_2))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a= end; + b+= 4; /* sizeof(long int); */ + break; + case HA_KEYTYPE_ULONG_INT: + u_1= mi_sint4korr(a); + u_2= mi_sint4korr(b); + if (piks && (flag = CMP_NUM(u_1,u_2))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a= end; + b+= 4; /* sizeof(long int); */ + break; + case HA_KEYTYPE_INT24: + l_1=mi_sint3korr(a); + l_2=mi_sint3korr(b); + if (piks && (flag = CMP_NUM(l_1,l_2))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a= end; + b+= 3; + break; + case HA_KEYTYPE_UINT24: + l_1=mi_uint3korr(a); + l_2=mi_uint3korr(b); + if (piks && (flag = CMP_NUM(l_1,l_2))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a= end; + b+= 3; + break; + case HA_KEYTYPE_FLOAT: + mi_float4get(f_1,a); + mi_float4get(f_2,b); + if (piks && (flag = CMP_NUM(f_1,f_2))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a= end; + b+= 4; /* sizeof(float); */ + break; + case HA_KEYTYPE_DOUBLE: + mi_float8get(d_1,a); + mi_float8get(d_2,b); + if (piks && (flag = CMP_NUM(d_1,d_2))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a= end; + b+= 8; /* sizeof(double); */ + break; + case HA_KEYTYPE_NUM: /* Numeric key */ + { + int swap_flag= 0; + int alength,blength; + + if (keyseg->flag & HA_REVERSE_SORT) + { + swap(uchar*,a,b); + swap_flag=1; /* Remember swap of a & b */ + end= a+ (int) (end-b); + } + if (keyseg->flag & HA_SPACE_PACK) + { + alength= *a++; blength= *b++; + end=a+alength; + next_key_length=key_length-blength-1; + } + else + { + alength= (int) (end-a); + blength=keyseg->length; + /* remove pre space from keys */ + for ( ; alength && *a == ' ' ; a++, alength--) ; + for ( ; blength && *b == ' ' ; b++, blength--) ; + } + + if (piks) + { + if (*a == '-') + { + if (*b != '-') + return -1; + a++; b++; + swap(uchar*,a,b); + swap(int,alength,blength); + swap_flag=1-swap_flag; + alength--; blength--; + end=a+alength; + } + else if (*b == '-') + return 1; + while (alength && (*a == '+' || *a == '0')) + { + a++; alength--; + } + while (blength && (*b == '+' || *b == '0')) + { + b++; blength--; + } + if (alength != blength) + return (alength < blength) ? -1 : 1; + while (a < end) + if (*a++ != *b++) + return ((int) a[-1] - (int) b[-1]); + } + else + { + b+=(end-a); + a=end; + } + + if (swap_flag) /* Restore pointers */ + swap(uchar*,a,b); + break; + } +#ifdef HAVE_LONG_LONG + case HA_KEYTYPE_LONGLONG: + { + longlong ll_a,ll_b; + ll_a= mi_sint8korr(a); + ll_b= mi_sint8korr(b); + if (piks && (flag = CMP_NUM(ll_a,ll_b))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a= end; + b+= 8; + break; + } + case HA_KEYTYPE_ULONGLONG: + { + ulonglong ll_a,ll_b; + ll_a= mi_uint8korr(a); + ll_b= mi_uint8korr(b); + if (piks && (flag = CMP_NUM(ll_a,ll_b))) + return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); + a= end; + b+= 8; + break; + } +#endif + case HA_KEYTYPE_END: /* Ready */ + goto end; /* diff_pos is incremented */ + } + } + (*diff_pos)++; +end: + if (!(nextflag & SEARCH_FIND)) + { + uint i; + if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */ + return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1; + flag=0; + for (i=keyseg->length ; i-- > 0 ; ) + { + if (*a++ != *b++) + { + flag= FCMP(a[-1],b[-1]); + break; + } + } + if (nextflag & SEARCH_SAME) + return (flag); /* read same */ + if (nextflag & SEARCH_BIGGER) + return (flag <= 0 ? -1 : 1); /* read next */ + return (flag < 0 ? -1 : 1); /* read previous */ + } + return 0; +} /* ha_key_cmp */ diff --git a/mysys/my_init.c b/mysys/my_init.c index f47286159f7..ee39f7201ca 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -17,7 +17,6 @@ #include "mysys_priv.h" #include "my_static.h" #include "mysys_err.h" -#include "m_ctype.h" #include <m_string.h> #include <m_ctype.h> #ifdef HAVE_GETRUSAGE @@ -47,7 +46,7 @@ my_bool my_init_done=0; static ulong atoi_octal(const char *str) { long int tmp; - while (*str && isspace(*str)) + while (*str && my_isspace(system_charset_info, *str)) str++; str2int(str, (*str == '0' ? 8 : 10), /* Octalt or decimalt */ diff --git a/mysys/my_vsnprintf.c b/mysys/my_vsnprintf.c index 7490ab4a9f2..2af5bf8903d 100644 --- a/mysys/my_vsnprintf.c +++ b/mysys/my_vsnprintf.c @@ -42,7 +42,7 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap) } /* Skip if max size is used (to be compatible with printf) */ fmt++; - while (isdigit(*fmt) || *fmt == '.' || *fmt == '-') + while (my_isdigit(system_charset_info,*fmt) || *fmt == '.' || *fmt == '-') fmt++; if (*fmt == 'l') fmt++; diff --git a/mysys/test_charset.c b/mysys/test_charset.c index 15e46f3ff82..47ed9062c05 100644 --- a/mysys/test_charset.c +++ b/mysys/test_charset.c @@ -21,7 +21,38 @@ #include <stdio.h> -extern void _print_csinfo(CHARSET_INFO *cs); +static void _print_array(uint8 *data, uint size) +{ + uint i; + for (i = 0; i < size; ++i) + { + if (i == 0 || i % 16 == size % 16) printf(" "); + printf(" %02x", data[i]); + if ((i+1) % 16 == size % 16) printf("\n"); + } +} + +static void _print_csinfo(CHARSET_INFO *cs) +{ + printf("%s #%d\n", cs->name, cs->number); + printf("ctype:\n"); _print_array(cs->ctype, 257); + printf("to_lower:\n"); _print_array(cs->to_lower, 256); + printf("to_upper:\n"); _print_array(cs->to_upper, 256); + printf("sort_order:\n"); _print_array(cs->sort_order, 256); + printf("collate: %3s (%d, %p, %p, %p)\n", + cs->strxfrm_multiply ? "yes" : "no", + cs->strxfrm_multiply, + cs->strnncoll, + cs->strnxfrm, + cs->like_range); + printf("multi-byte: %3s (%d, %p, %p, %p)\n", + cs->mbmaxlen ? "yes" : "no", + cs->mbmaxlen, + cs->ismbchar, + cs->ismbhead, + cs->mbcharlen); +} + int main(int argc, char **argv) { const char *the_set = MYSQL_CHARSET; @@ -46,13 +77,13 @@ int main(int argc, char **argv) { _print_csinfo(default_charset_info); fflush(stdout); - cs_list = list_charsets(MYF(MY_COMPILED_SETS | MY_CONFIG_SETS)); + cs_list = list_charsets(MYF(MY_CS_COMPILED | MY_CS_CONFIG)); printf("LIST OF CHARSETS (compiled + *.conf):\n%s\n", cs_list); - free(cs_list); + my_free(cs_list,MYF(0)); - cs_list = list_charsets(MYF(MY_INDEX_SETS | MY_LOADED_SETS)); + cs_list = list_charsets(MYF(MY_CS_INDEX | MY_CS_LOADED)); printf("LIST OF CHARSETS (index + loaded):\n%s\n", cs_list); - free(cs_list); + my_free(cs_list,MYF(0)); return 0; } diff --git a/mysys/tree.c b/mysys/tree.c index 2ac2c88fd66..489262fcdc7 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -42,6 +42,7 @@ #include "mysys_priv.h" #include <m_string.h> #include <my_tree.h> +#include "my_base.h" #define BLACK 1 #define RED 0 @@ -85,6 +86,7 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit, tree->custom_arg = custom_arg; tree->null_element.colour=BLACK; tree->null_element.left=tree->null_element.right=0; + tree->flag= 0; if (!free_element && size >= 0 && ((uint) size <= sizeof(void*) || ((uint) size & (sizeof(void*)-1)))) { @@ -167,7 +169,8 @@ static void delete_tree_element(TREE *tree, TREE_ELEMENT *element) parent[0] = & parent[-1][0]->right */ -TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size) +TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size, + void* custom_arg) { int cmp; TREE_ELEMENT *element,***parent; @@ -177,8 +180,8 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size) for (;;) { if (element == &tree->null_element || - (cmp=(*tree->compare)(tree->custom_arg, - ELEMENT_KEY(tree,element),key)) == 0) + (cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), + key)) == 0) break; if (cmp < 0) { @@ -198,7 +201,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size) && tree->allocated > tree->memory_limit) { reset_tree(tree); - return tree_insert(tree, key, key_size); + return tree_insert(tree, key, key_size, custom_arg); } key_size+=tree->size_of_element; @@ -229,13 +232,16 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size) rb_insert(tree,parent,element); /* rebalance tree */ } else + { + if (tree->flag & TREE_NO_DUPS) + return(NULL); element->count++; + } DBUG_EXECUTE("check_tree", test_rb_tree(tree->root);); return element; } - -int tree_delete(TREE *tree, void *key) +int tree_delete(TREE *tree, void *key, void *custom_arg) { int cmp,remove_colour; TREE_ELEMENT *element,***parent, ***org_parent, *nod; @@ -248,8 +254,8 @@ int tree_delete(TREE *tree, void *key) { if (element == &tree->null_element) return 1; /* Was not in tree */ - if ((cmp=(*tree->compare)(tree->custom_arg, - ELEMENT_KEY(tree,element),key)) == 0) + if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), + key)) == 0) break; if (cmp < 0) { @@ -296,7 +302,7 @@ int tree_delete(TREE *tree, void *key) } -void *tree_search(TREE *tree, void *key) +void *tree_search(TREE *tree, void *key, void *custom_arg) { int cmp; TREE_ELEMENT *element=tree->root; @@ -305,8 +311,8 @@ void *tree_search(TREE *tree, void *key) { if (element == &tree->null_element) return (void*) 0; - if ((cmp=(*tree->compare)(tree->custom_arg, - ELEMENT_KEY(tree,element),key)) == 0) + if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), + key)) == 0) return ELEMENT_KEY(tree,element); if (cmp < 0) element=element->right; @@ -315,6 +321,168 @@ void *tree_search(TREE *tree, void *key) } } +void *tree_search_key(TREE *tree, const void *key, + TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos, + enum ha_rkey_function flag, void *custom_arg) +{ + int cmp; + TREE_ELEMENT *element = tree->root; + TREE_ELEMENT **last_left_step_parent = NULL; + TREE_ELEMENT **last_equal_element = NULL; + +/* + TODO: handle HA_READ_KEY_OR_PREV, HA_READ_BEFORE_KEY, HA_READ_PREFIX, + HA_READ_PREFIX_LAST flags if needed. +*/ + + *parents = &tree->null_element; + while (element != &tree->null_element) + { + *++parents = element; + if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element), + key)) == 0) + { + switch (flag) { + case HA_READ_KEY_EXACT: + case HA_READ_KEY_OR_NEXT: + last_equal_element = parents; + cmp = 1; + break; + case HA_READ_AFTER_KEY: + cmp = -1; + break; + default: + return NULL; + } + } + if (cmp < 0) /* element < key */ + { + element = element->right; + } + else + { + last_left_step_parent = parents; + element = element->left; + } + } + switch (flag) { + case HA_READ_KEY_EXACT: + *last_pos = last_equal_element; + break; + case HA_READ_KEY_OR_NEXT: + *last_pos = last_equal_element ? last_equal_element : last_left_step_parent; + break; + case HA_READ_AFTER_KEY: + *last_pos = last_left_step_parent; + break; + default: + return NULL; + } + return *last_pos ? ELEMENT_KEY(tree, **last_pos) : NULL; +} + +/* + Search first (the most left) or last (the most right) tree element +*/ +void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents, + TREE_ELEMENT ***last_pos, int child_offs) +{ + TREE_ELEMENT *element= tree->root; + + *parents= &tree->null_element; + while (element != &tree->null_element) + { + *++parents= element; + element= ELEMENT_CHILD(element, child_offs); + } + *last_pos= parents; + return **last_pos != &tree->null_element ? + ELEMENT_KEY(tree, **last_pos) : NULL; +} + +void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs, + int r_offs) +{ + TREE_ELEMENT *x= **last_pos; + + if (ELEMENT_CHILD(x, r_offs) != &tree->null_element) + { + x= ELEMENT_CHILD(x, r_offs); + *++*last_pos= x; + while (ELEMENT_CHILD(x, l_offs) != &tree->null_element) + { + x= ELEMENT_CHILD(x, l_offs); + *++*last_pos= x; + } + return ELEMENT_KEY(tree, x); + } + else + { + TREE_ELEMENT *y= *--*last_pos; + while (y != &tree->null_element && x == ELEMENT_CHILD(y, r_offs)) + { + x= y; + y= *--*last_pos; + } + return y == &tree->null_element ? NULL : ELEMENT_KEY(tree, y); + } +} + +/* + Expected that tree is fully balanced + (each path from root to leaf has the same length) +*/ +uint tree_record_pos(TREE *tree, const void *key, + enum ha_rkey_function flag, void *custom_arg) +{ + int cmp; + TREE_ELEMENT *element= tree->root; + double left= 1; + double right= tree->elements_in_tree; + uint last_equal_pos= HA_POS_ERROR; + + while (element != &tree->null_element) + { + if ((cmp= (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element), + key)) == 0) + { + switch (flag) { + case HA_READ_KEY_EXACT: + last_equal_pos= (left + right) / 2; + cmp= 1; + break; + case HA_READ_BEFORE_KEY: + cmp= 1; + break; + case HA_READ_AFTER_KEY: + cmp= -1; + break; + default: + return HA_POS_ERROR; + } + } + if (cmp < 0) /* element < key */ + { + element= element->right; + left= (left + right) / 2; + } + else + { + element= element->left; + right= (left + right) / 2; + } + } + switch (flag) { + case HA_READ_KEY_EXACT: + return last_equal_pos; + case HA_READ_BEFORE_KEY: + return (uint) right; + case HA_READ_AFTER_KEY: + return (uint) left; + default: + return HA_POS_ERROR; + } +} int tree_walk(TREE *tree, tree_walk_action action, void *argument, TREE_WALK visit) { diff --git a/mysys/typelib.c b/mysys/typelib.c index e2c8eade5c8..e524f903b5d 100644 --- a/mysys/typelib.c +++ b/mysys/typelib.c @@ -47,7 +47,9 @@ int find_type(my_string x, TYPELIB *typelib, uint full_name) find=0; for (pos=0 ; (j=typelib->type_names[pos]) ; pos++) { - for (i=x ; *i && toupper(*i) == toupper(*j) ; i++, j++) ; + for (i=x ; + *i && my_toupper(system_charset_info,*i) == + my_toupper(system_charset_info,*j) ; i++, j++) ; if (! *j) { while (*i == ' ') |