summary refs log tree commit diff
path: root/wcsmbs/btowc.c
diff options
context:
space:
mode:
Diffstat (limited to 'wcsmbs/btowc.c')
-rw-r--r--wcsmbs/btowc.c69
1 files changed, 41 insertions, 28 deletions
diff --git a/wcsmbs/btowc.c b/wcsmbs/btowc.c
index ca75e281e6..1ba0221403 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)