diff options
Diffstat (limited to 'wcsmbs')
-rw-r--r-- | wcsmbs/btowc.c | 69 | ||||
-rw-r--r-- | wcsmbs/wcsmbsload.c | 5 |
2 files changed, 45 insertions, 29 deletions
diff --git a/wcsmbs/btowc.c b/wcsmbs/btowc.c index ca75e28..1ba0221 100644 --- a/wcsmbs/btowc.c +++ b/wcsmbs/btowc.c @@ -30,12 +30,6 @@ wint_t __btowc (c) int c; { - wchar_t result; - struct __gconv_step_data data; - unsigned char inbuf[1]; - const unsigned char *inptr = inbuf; - size_t dummy; - int status; const struct gconv_fcts *fcts; /* If the parameter does not fit into one byte or it is the EOF value @@ -43,32 +37,51 @@ __btowc (c) if (c < SCHAR_MIN || c > UCHAR_MAX || c == EOF) return WEOF; - /* Tell where we want the result. */ - data.__outbuf = (unsigned char *) &result; - data.__outbufend = data.__outbuf + sizeof (wchar_t); - data.__invocation_counter = 0; - data.__internal_use = 1; - data.__flags = __GCONV_IS_LAST; - data.__statep = &data.__state; - data.__trans = NULL; - - /* Make sure we start in the initial state. */ - memset (&data.__state, '\0', sizeof (mbstate_t)); - /* Get the conversion functions. */ fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); - /* Create the input string. */ - inbuf[0] = c; + if (__builtin_expect (fcts->towc_nsteps == 1, 1) + && __builtin_expect (fcts->towc->__btowc_fct != NULL, 1)) + { + /* Use the shortcut function. */ + return DL_CALL_FCT (fcts->towc->__btowc_fct, + (fcts->towc, (unsigned char) c)); + } + else + { + /* Fall back to the slow but generic method. */ + wchar_t result; + struct __gconv_step_data data; + unsigned char inbuf[1]; + const unsigned char *inptr = inbuf; + size_t dummy; + int status; + + /* Tell where we want the result. */ + data.__outbuf = (unsigned char *) &result; + data.__outbufend = data.__outbuf + sizeof (wchar_t); + data.__invocation_counter = 0; + data.__internal_use = 1; + data.__flags = __GCONV_IS_LAST; + data.__statep = &data.__state; + data.__trans = NULL; + + /* Make sure we start in the initial state. */ + memset (&data.__state, '\0', sizeof (mbstate_t)); + + /* Create the input string. */ + inbuf[0] = c; + + status = DL_CALL_FCT (fcts->towc->__fct, + (fcts->towc, &data, &inptr, inptr + 1, + NULL, &dummy, 0, 1)); - status = DL_CALL_FCT (fcts->towc->__fct, - (fcts->towc, &data, &inptr, inptr + 1, - NULL, &dummy, 0, 1)); - /* The conversion failed. */ - if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT - && status != __GCONV_EMPTY_INPUT) - result = WEOF; + if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT + && status != __GCONV_EMPTY_INPUT) + /* The conversion failed. */ + result = WEOF; - return result; + return result; + } } weak_alias (__btowc, btowc) diff --git a/wcsmbs/wcsmbsload.c b/wcsmbs/wcsmbsload.c index bf23d25..2fea6c3 100644 --- a/wcsmbs/wcsmbsload.c +++ b/wcsmbs/wcsmbsload.c @@ -37,6 +37,7 @@ static struct __gconv_step to_wc = .__from_name = (char *) "ANSI_X3.4-1968//TRANSLIT", .__to_name = (char *) "INTERNAL", .__fct = __gconv_transform_ascii_internal, + .__btowc_fct = __gconv_btwoc_ascii, .__init_fct = NULL, .__end_fct = NULL, .__min_needed_from = 1, @@ -55,6 +56,7 @@ static struct __gconv_step to_mb = .__from_name = (char *) "INTERNAL", .__to_name = (char *) "ANSI_X3.4-1968//TRANSLIT", .__fct = __gconv_transform_internal_ascii, + .__btowc_fct = NULL, .__init_fct = NULL, .__end_fct = NULL, .__min_needed_from = 4, @@ -225,7 +227,8 @@ __wcsmbs_clone_conv (struct gconv_fcts *copy) /* Copy the data. */ *copy = *orig; - /* Now increment the usage counters. */ + /* Now increment the usage counters. + Note: This assumes copy->towc_nsteps == 1 and copy->tomb_nsteps == 1. */ if (copy->towc->__shlib_handle != NULL) ++copy->towc->__counter; if (copy->tomb->__shlib_handle != NULL) |