]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - wtf/unicode/glib/UnicodeGLib.cpp
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / wtf / unicode / glib / UnicodeGLib.cpp
index a779b36809d1e116b1198ee18f8ca5cb46f4a302..a01c3ee9db57cb43b890a2e663a376eb54061088 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2008 Jürg Billeter <j@bitron.ch>
  *  Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com>
 /*
  *  Copyright (C) 2008 Jürg Billeter <j@bitron.ch>
  *  Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com>
+ *  Copyright (C) 2010 Igalia S.L.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  */
 
  *
  */
 
+#include "config.h"
 #include "UnicodeGLib.h"
 
 #include "UnicodeGLib.h"
 
+#include <wtf/Vector.h>
+#include <wtf/unicode/UTF8.h>
+
+#define UTF8_IS_SURROGATE(character) (character >= 0x10000 && character <= 0x10FFFF)
+
 namespace WTF {
 namespace Unicode {
 
 namespace WTF {
 namespace Unicode {
 
@@ -42,100 +49,71 @@ UChar32 foldCase(UChar32 ch)
     return *ucs4Result;
 }
 
     return *ucs4Result;
 }
 
-int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+static int getUTF16LengthFromUTF8(const gchar* utf8String, int length)
 {
 {
-    *error = false;
-    GOwnPtr<GError> gerror;
+    int utf16Length = 0;
+    const gchar* inputString = utf8String;
 
 
-    GOwnPtr<char> utf8src;
-    utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr()));
-    if (gerror) {
-        *error = true;
-        return -1;
-    }
-
-    GOwnPtr<char> utf8result;
-    utf8result.set(g_utf8_casefold(utf8src.get(), -1));
+    while ((utf8String + length - inputString > 0) && *inputString) {
+        gunichar character = g_utf8_get_char(inputString);
 
 
-    long utf16resultLength = -1;
-    GOwnPtr<UChar> utf16result;
-    utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr()));
-    if (gerror) {
-        *error = true;
-        return -1;
+        utf16Length += UTF8_IS_SURROGATE(character) ? 2 : 1;
+        inputString = g_utf8_next_char(inputString);
     }
 
     }
 
-    if (utf16resultLength > resultLength) {
-        *error = true;
-        return utf16resultLength;
-    }
-    memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar));
-
-    return utf16resultLength;
+    return utf16Length;
 }
 
 }
 
-int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+typedef gchar* (*UTF8CaseFunction)(const gchar*, gssize length);
+
+static int convertCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error, UTF8CaseFunction caseFunction)
 {
     *error = false;
 {
     *error = false;
-    GOwnPtr<GError> gerror;
 
 
-    GOwnPtr<char> utf8src;
-    utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr()));
-    if (gerror) {
+    // Allocate a buffer big enough to hold all the characters.
+    Vector<char> buffer(srcLength * 3);
+    char* utf8Target = buffer.data();
+    const UChar* utf16Source = src;
+    ConversionResult conversionResult = convertUTF16ToUTF8(&utf16Source, utf16Source + srcLength, &utf8Target, utf8Target + buffer.size(), true);
+    if (conversionResult != conversionOK) {
         *error = true;
         return -1;
     }
         *error = true;
         return -1;
     }
+    buffer.shrink(utf8Target - buffer.data());
 
 
-    GOwnPtr<char> utf8result;
-    utf8result.set(g_utf8_strdown(utf8src.get(), -1));
+    GOwnPtr<char> utf8Result(caseFunction(buffer.data(), buffer.size()));
+    long utf8ResultLength = strlen(utf8Result.get());
 
 
-    long utf16resultLength = -1;
-    GOwnPtr<UChar> utf16result;
-    utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr()));
-    if (gerror) {
+    // Calculate the destination buffer size.
+    int realLength = getUTF16LengthFromUTF8(utf8Result.get(), utf8ResultLength);
+    if (realLength > resultLength) {
         *error = true;
         *error = true;
-        return -1;
+        return realLength;
     }
 
     }
 
-    if (utf16resultLength > resultLength) {
+    // Convert the result to UTF-16.
+    UChar* utf16Target = result;
+    const char* utf8Source = utf8Result.get();
+    conversionResult = convertUTF8ToUTF16(&utf8Source, utf8Source + utf8ResultLength, &utf16Target, utf16Target + resultLength, true);
+    long utf16ResultLength = utf16Target - result;
+    if (conversionResult != conversionOK)
         *error = true;
         *error = true;
-        return utf16resultLength;
-    }
-    memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar));
 
 
-    return utf16resultLength;
+    return utf16ResultLength <= 0 ? -1 : utf16ResultLength;
 }
 }
-
-int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
 {
 {
-    *error = false;
-    GOwnPtr<GError> gerror;
-
-    GOwnPtr<char> utf8src;
-    utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr()));
-    if (gerror) {
-        *error = true;
-        return -1;
-    }
-
-    GOwnPtr<char> utf8result;
-    utf8result.set(g_utf8_strup(utf8src.get(), -1));
-
-    long utf16resultLength = -1;
-    GOwnPtr<UChar> utf16result;
-    utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr()));
-    if (gerror) {
-        *error = true;
-        return -1;
-    }
+    return convertCase(result, resultLength, src, srcLength, error, g_utf8_casefold);
+}
 
 
-    if (utf16resultLength > resultLength) {
-        *error = true;
-        return utf16resultLength;
-    }
-    memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar));
+int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+    return convertCase(result, resultLength, src, srcLength, error, g_utf8_strdown);
+}
 
 
-    return utf16resultLength;
+int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+    return convertCase(result, resultLength, src, srcLength, error, g_utf8_strup);
 }
 
 Direction direction(UChar32 c)
 }
 
 Direction direction(UChar32 c)