OSDN Git Service

Generic I/O for directories: switch rename_entry().
[android-x86/external-exfat.git] / libexfat / utf.c
index 6465661..f410eb6 100644 (file)
@@ -1,11 +1,24 @@
 /*
- *  utf.c
- *  exFAT file system implementation library.
- *
- *  Created by Andrew Nayenko on 13.09.09.
- *  This software is distributed under the GNU General Public License 
- *  version 3 or any later.
- */
+       utf.c (13.09.09)
+       exFAT file system implementation library.
+
+       Free exFAT implementation.
+       Copyright (C) 2010-2016  Andrew Nayenko
+
+       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.,
+       51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
 
 #include "exfat.h"
 #include <errno.h>
@@ -78,6 +91,7 @@ static const le16_t* utf16_to_wchar(const le16_t* input, wchar_t* wc,
                        return NULL;
                *wc = ((wchar_t) (le16_to_cpu(input[0]) & 0x3ff) << 10);
                *wc |= (le16_to_cpu(input[1]) & 0x3ff);
+               *wc += 0x10000;
                return input + 2;
        }
        else
@@ -94,7 +108,7 @@ int utf16_to_utf8(char* output, const le16_t* input, size_t outsize,
        char* outp = output;
        wchar_t wc;
 
-       while (inp - input < insize && le16_to_cpu(*inp))
+       while (inp - input < insize)
        {
                inp = utf16_to_wchar(inp, &wc, insize - (inp - input));
                if (inp == NULL)
@@ -108,6 +122,13 @@ int utf16_to_utf8(char* output, const le16_t* input, size_t outsize,
                        exfat_error("name is too long");
                        return -ENAMETOOLONG;
                }
+               if (wc == 0)
+                       return 0;
+       }
+       if (outp - output >= outsize)
+       {
+               exfat_error("name is too long");
+               return -ENAMETOOLONG;
        }
        *outp = '\0';
        return 0;
@@ -169,18 +190,13 @@ static le16_t* wchar_to_utf16(le16_t* output, wchar_t wc, size_t outsize)
        if (wc <= 0xffff) /* if character is from BMP */
        {
                if (outsize == 0)
-               {
-                       exfat_error("name is too long");
                        return NULL;
-               }
                output[0] = cpu_to_le16(wc);
                return output + 1;
        }
        if (outsize < 2)
-       {
-               exfat_error("name is too long");
                return NULL;
-       }
+       wc -= 0x10000;
        output[0] = cpu_to_le16(0xd800 | ((wc >> 10) & 0x3ff));
        output[1] = cpu_to_le16(0xdc00 | (wc & 0x3ff));
        return output + 2;
@@ -193,7 +209,7 @@ int utf8_to_utf16(le16_t* output, const char* input, size_t outsize,
        le16_t* outp = output;
        wchar_t wc;
 
-       while (inp - input < insize && *inp)
+       while (inp - input < insize)
        {
                inp = utf8_to_wchar(inp, &wc, insize - (inp - input));
                if (inp == NULL)
@@ -207,7 +223,23 @@ int utf8_to_utf16(le16_t* output, const char* input, size_t outsize,
                        exfat_error("name is too long");
                        return -ENAMETOOLONG;
                }
+               if (wc == 0)
+                       break;
+       }
+       if (outp - output >= outsize)
+       {
+               exfat_error("name is too long");
+               return -ENAMETOOLONG;
        }
        *outp = cpu_to_le16(0);
        return 0;
 }
+
+size_t utf16_length(const le16_t* str)
+{
+       size_t i = 0;
+
+       while (le16_to_cpu(str[i]))
+               i++;
+       return i;
+}