return res;
 }
 
-int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, const char *astr, int len)
+/*
+ * Convert one or more ASCII characters into a single unicode character.
+ * Returns the number of ASCII characters corresponding to the unicode char.
+ */
+static inline int asc2unichar(struct super_block *sb, const char *astr, int len,
+                             wchar_t *uc)
 {
-       struct nls_table *nls = HFSPLUS_SB(sb).nls;
-       int size, off, decompose;
+       int size = HFSPLUS_SB(sb).nls->char2uni(astr, len, uc);
+       if (size <= 0) {
+               *uc = '?';
+               size = 1;
+       }
+       switch (*uc) {
+       case 0x2400:
+               *uc = 0;
+               break;
+       case ':':
+               *uc = '/';
+               break;
+       }
+       return size;
+}
+
+/* Decomposes a single unicode character. */
+static inline u16 *decompose_unichar(wchar_t uc, int *size)
+{
+       int off;
+
+       off = hfsplus_decompose_table[(uc >> 12) & 0xf];
+       if (off == 0 || off == 0xffff)
+               return NULL;
+
+       off = hfsplus_decompose_table[off + ((uc >> 8) & 0xf)];
+       if (!off)
+               return NULL;
+
+       off = hfsplus_decompose_table[off + ((uc >> 4) & 0xf)];
+       if (!off)
+               return NULL;
+
+       off = hfsplus_decompose_table[off + (uc & 0xf)];
+       *size = off & 3;
+       if (*size == 0)
+               return NULL;
+       return hfsplus_decompose_table + (off / 4);
+}
+
+int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
+                   const char *astr, int len)
+{
+       int size, dsize, decompose;
+       u16 *dstr, outlen = 0;
        wchar_t c;
-       u16 outlen = 0;
 
        decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
-
        while (outlen < HFSPLUS_MAX_STRLEN && len > 0) {
-               size = nls->char2uni(astr, len, &c);
-               if (size <= 0) {
-                       c = '?';
-                       size = 1;
-               }
-               astr += size;
-               len -= size;
-               switch (c) {
-               case 0x2400:
-                       c = 0;
-                       break;
-               case ':':
-                       c = '/';
-                       break;
-               }
-               if (c >= 0xc0 && decompose) {
-                       off = hfsplus_decompose_table[(c >> 12) & 0xf];
-                       if (!off)
-                               goto done;
-                       if (off == 0xffff) {
-                               goto done;
-                       }
-                       off = hfsplus_decompose_table[off + ((c >> 8) & 0xf)];
-                       if (!off)
-                               goto done;
-                       off = hfsplus_decompose_table[off + ((c >> 4) & 0xf)];
-                       if (!off)
-                               goto done;
-                       off = hfsplus_decompose_table[off + (c & 0xf)];
-                       size = off & 3;
-                       if (!size)
-                               goto done;
-                       off /= 4;
-                       if (outlen + size > HFSPLUS_MAX_STRLEN)
+               size = asc2unichar(sb, astr, len, &c);
+
+               if (decompose && (dstr = decompose_unichar(c, &dsize))) {
+                       if (outlen + dsize > HFSPLUS_MAX_STRLEN)
                                break;
                        do {
-                               ustr->unicode[outlen++] = cpu_to_be16(hfsplus_decompose_table[off++]);
-                       } while (--size > 0);
-                       continue;
-               }
-       done:
-               ustr->unicode[outlen++] = cpu_to_be16(c);
+                               ustr->unicode[outlen++] = cpu_to_be16(*dstr++);
+                       } while (--dsize > 0);
+               } else
+                       ustr->unicode[outlen++] = cpu_to_be16(c);
+
+               astr += size;
+               len -= size;
        }
        ustr->length = cpu_to_be16(outlen);
        if (len > 0)