This source file includes following definitions.
- IsNormalizedString
- NormalizeString
- IsValid
- TryToNormalizeText
#include "encodings/compact_lang_det/win/normalizedunicodetext.h"
#include <tchar.h>
#include <windows.h>
#include <winnls.h>
#include "encodings/compact_lang_det/win/cld_scopedptr.h"
namespace {
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);
class NormalizationAPI {
public:
NormalizationAPI()
: library_(_T("Normaliz.dll")) {
if (library_.IsValid()) {
is_normalized_string_.Bind(library_.handle(), "IsNormalizedString");
normalize_string_.Bind(library_.handle(), "NormalizeString");
}
}
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);
}
bool IsValid() const {
return is_normalized_string_.IsValid() && normalize_string_.IsValid();
}
private:
ScopedLibrary library_;
FunctionFromDll<IsNormalizedStringFunction> is_normalized_string_;
FunctionFromDll<NormalizeStringFunction> normalize_string_;
DISALLOW_COPY_AND_ASSIGN(NormalizationAPI);
};
static NormalizationAPI normalization_api;
}
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()) {
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();
}
if (normalization_api.IsNormalizedString(normalization_form, text, -1))
return 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) {
return text_.get();
}
if (ERROR_INSUFFICIENT_BUFFER != ::GetLastError()) {
*error_code = ::GetLastError();
break;
}
normalized_text_size_guess = -normalized_text_size;
}
text_.reset();
return text;
}