/// <summary> /// Normalize the string according to the given mode. /// </summary> /// <param name="src"></param> /// <param name="mode"></param> /// <returns></returns> public static string Normalize(string src, UNormalizationMode mode) { if (string.IsNullOrEmpty(src)) { return(string.Empty); } var length = src.Length + 10; var resPtr = Marshal.AllocCoTaskMem(length * 2); try { ErrorCode err; var normalizer = GetNormalizer(mode); var outLength = NativeMethods.unorm2_normalize(normalizer, src, src.Length, resPtr, length, out err); if (err > 0 && err != ErrorCode.BUFFER_OVERFLOW_ERROR) { throw new Exception("Normalizer.Normalize() failed with code " + err); } if (outLength >= length) { Marshal.FreeCoTaskMem(resPtr); length = outLength + 1; // allow room for the terminating NUL (FWR-505) resPtr = Marshal.AllocCoTaskMem(length * 2); outLength = NativeMethods.unorm2_normalize(normalizer, src, src.Length, resPtr, length, out err); } if (err > 0) { throw new Exception("Normalizer.Normalize() failed with code " + err); } var result = Marshal.PtrToStringUni(resPtr); // Strip any garbage left over at the end of the string. if (err == ErrorCode.STRING_NOT_TERMINATED_WARNING && result != null) { return(result.Substring(0, outLength)); } return(result); } finally { Marshal.FreeCoTaskMem(resPtr); } }