summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
Diffstat (limited to 'mysys')
-rw-r--r--mysys/Makefile.am9
-rw-r--r--mysys/charset.c450
-rw-r--r--mysys/charset2html.c129
-rw-r--r--mysys/default.c10
-rw-r--r--mysys/hash.c44
-rw-r--r--mysys/mf_casecnv.c254
-rw-r--r--mysys/mf_dirname.c6
-rw-r--r--mysys/mf_format.c6
-rw-r--r--mysys/mf_iocache2.c2
-rw-r--r--mysys/mf_soundex.c21
-rw-r--r--mysys/mf_wfile.c7
-rw-r--r--mysys/my_error.c2
-rw-r--r--mysys/my_getwd.c3
-rw-r--r--mysys/my_handler.c404
-rw-r--r--mysys/my_init.c3
-rw-r--r--mysys/my_vsnprintf.c2
-rw-r--r--mysys/test_charset.c41
-rw-r--r--mysys/tree.c190
-rw-r--r--mysys/typelib.c4
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 == ' ')