Index: third_party/cld/bar/toolbar/cld/i18n/encodings/compact_lang_det/win/normalizedunicodetext.cc |
=================================================================== |
--- third_party/cld/bar/toolbar/cld/i18n/encodings/compact_lang_det/win/normalizedunicodetext.cc (revision 0) |
+++ third_party/cld/bar/toolbar/cld/i18n/encodings/compact_lang_det/win/normalizedunicodetext.cc (revision 0) |
@@ -0,0 +1,172 @@ |
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "third_party/cld/bar/toolbar/cld/i18n/encodings/compact_lang_det/win/normalizedunicodetext.h" |
+ |
+#include <tchar.h> |
+#include <windows.h> |
+#include <winnls.h> |
+ |
+#include "third_party/cld/bar/toolbar/cld/i18n/encodings/compact_lang_det/win/cld_scopedptr.h" |
+ |
+ |
+namespace { |
+ |
+// Function prototypes copied from MSDN. |
+typedef BOOL (WINAPI *IsNormalizedStringFunction)(NORM_FORM NormForm, |
+ LPCWSTR lpSrcString, |
+ int cwSrcLength); |
+typedef int (WINAPI *NormalizeStringFunction)(NORM_FORM NormForm, |
+ LPCWSTR lpSrcString, |
+ int cwSrcLength, |
+ LPWSTR lpDstString, |
+ int cwDstLength); |
+ |
+// A class to provide an access to Normaliz.dll functions. |
+// New normalization API implemented in Normaliz.dll is available starting |
+// from Windows XP SP2, that's why we have to bind to it dynamically. |
+class NormalizationAPI { |
+ public: |
+ // Creates fully initialized NormalizationAPI object. |
+ // Loads DLL and binds all referenced functions. |
+ NormalizationAPI() |
+ : library_(_T("Normaliz.dll")) { |
+ if (library_.IsValid()) { |
+ is_normalized_string_.Bind(library_.handle(), "IsNormalizedString"); |
+ normalize_string_.Bind(library_.handle(), "NormalizeString"); |
+ } |
+ } |
+ |
+ // Proxy functions for the ones loaded from DLL. |
+ BOOL IsNormalizedString(NORM_FORM NormForm, LPCWSTR lpSrcString, |
+ int cwSrcLength) { |
+ if (!is_normalized_string_.IsValid()) |
+ return FALSE; |
+ return is_normalized_string_.function()(NormForm, lpSrcString, cwSrcLength); |
+ } |
+ int NormalizeString(NORM_FORM NormForm, LPCWSTR lpSrcString, int cwSrcLength, |
+ LPWSTR lpDstString, int cwDstLength) { |
+ if (!normalize_string_.IsValid()) { |
+ ::SetLastError(ERROR_INVALID_FUNCTION); |
+ return 0; |
+ } |
+ return normalize_string_.function()(NormForm, lpSrcString, cwSrcLength, |
+ lpDstString, cwDstLength); |
+ } |
+ |
+ // Returns true if all functions were bound successfully. |
+ // This implies that library_ itself was loaded successfully. |
+ bool IsValid() const { |
+ return is_normalized_string_.IsValid() && normalize_string_.IsValid(); |
+ } |
+ |
+ private: |
+ // Holds a handle to loaded Normaliz.dll. |
+ ScopedLibrary library_; |
+ // Pointers to the functions loaded from Normaliz.dll. |
+ FunctionFromDll<IsNormalizedStringFunction> is_normalized_string_; |
+ FunctionFromDll<NormalizeStringFunction> normalize_string_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(NormalizationAPI); |
+}; |
+ |
+static NormalizationAPI normalization_api; |
+ |
+} // namespace |
+ |
+ |
+// NormalizedUnicodeText |
+ |
+NormalizedUnicodeText::NormalizedUnicodeText() |
+ : normalized_text_(NULL) { |
+} |
+ |
+ |
+DWORD NormalizedUnicodeText::Normalize(NORM_FORM normalization_form, |
+ const WCHAR* text) { |
+ DWORD result = 0; |
+ normalized_text_ = TryToNormalizeText(normalization_form, text, &result); |
+ return result; |
+} |
+ |
+ |
+const WCHAR* NormalizedUnicodeText::TryToNormalizeText( |
+ NORM_FORM normalization_form, const WCHAR* text, DWORD *error_code) { |
+ if (!text) { |
+ text_.reset(); |
+ return text; |
+ } |
+ _ASSERT(NULL != error_code); |
+ if (!error_code) |
+ return text; |
+ |
+ if (!normalization_api.IsValid()) { |
+ // Fall back to the previous version of normalization API. |
+ int folded_text_size = ::FoldStringW(MAP_PRECOMPOSED, text, -1, NULL, 0); |
+ if (!folded_text_size) { |
+ *error_code = ::GetLastError(); |
+ return text; |
+ } |
+ |
+ text_.reset(new WCHAR[folded_text_size]); |
+ if (!text_.get()) { |
+ *error_code = ERROR_OUTOFMEMORY; |
+ return text; |
+ } |
+ |
+ int folding_result = |
+ ::FoldStringW(MAP_PRECOMPOSED, text, -1, text_.get(), folded_text_size); |
+ if (!folding_result) { |
+ *error_code = ::GetLastError(); |
+ text_.reset(); |
+ return text; |
+ } |
+ |
+ return text_.get(); |
+ } |
+ |
+ // No need to allocate anything when text is already normalized. |
+ if (normalization_api.IsNormalizedString(normalization_form, text, -1)) |
+ return text; |
+ |
+ // Get the first approximation for the buffer size required to store |
+ // normalized text. |
+ int normalized_text_size_guess = |
+ normalization_api.NormalizeString(normalization_form, text, -1, NULL, 0); |
+ |
+ while (normalized_text_size_guess > 0) { |
+ text_.reset(new WCHAR[normalized_text_size_guess]); |
+ if (!text_.get()) { |
+ *error_code = ERROR_OUTOFMEMORY; |
+ break; |
+ } |
+ |
+ int normalized_text_size = |
+ normalization_api.NormalizeString(normalization_form, text, -1, |
+ text_.get(), |
+ normalized_text_size_guess); |
+ |
+ if (normalized_text_size > 0) { |
+ // Text was successfully converted. |
+ return text_.get(); |
+ } |
+ |
+ if (ERROR_INSUFFICIENT_BUFFER != ::GetLastError()) { |
+ *error_code = ::GetLastError(); |
+ // Text cannot be normalized, use the original. |
+ // By the way, ERROR_SUCCESS is a puzzling case. |
+ // MSDN says 'The action completed successfully but yielded no results'. |
+ // Does this mean that output buffer was not changed? |
+ // Anyway, just in case, also return the original text. |
+ break; |
+ } |
+ |
+ // Try again with the corrected buffer size. |
+ normalized_text_size_guess = -normalized_text_size; |
+ } |
+ |
+ // Use the original text in case of any problem with normalization. |
+ text_.reset(); |
+ return text; |
+} |
Property changes on: third_party\cld\bar\toolbar\cld\i18n\encodings\compact_lang_det\win\normalizedunicodetext.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |