/// <summary> /// Get the visual position from a logical text position. /// </summary> /// <param name="logicalIndex">The index of a character in the tex</param> /// <returns>The visual position of this character.</returns> public int GetVisualIndex(int logicalIndex) { var ret = NativeMethods.ubidi_getVisualIndex(_biDi, logicalIndex, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "Get visual index failed! " + errorCode); return(ret); }
/// <summary> /// Get an ICU UEnumeration pointer that will enumerate all converter IDs (canonical names). /// </summary> /// <returns>The opaque enumerator handle. Closing it properly is the responsibility of /// the caller.</returns> private static SafeEnumeratorHandle GetEnumerator() { var result = NativeMethods.ucnv_openAllNames(out var status); ExceptionFromErrorCode.ThrowIfError(status); return(result); }
/// <summary> /// Get the number of runs. /// </summary> /// <returns>The number of runs</returns> public int CountRuns() { var ret = NativeMethods.ubidi_countRuns(_biDi, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "Run count failed! " + errorCode); return(ret); }
/// <summary> /// Set the subject text string upon which the regular expression will look for matches. /// This function may be called any number of times, allowing the regular /// expression pattern to be applied to different strings. /// </summary> /// <param name="str">The subject text string.</param> public void SetText(string str) { ErrorCode e; NativeMethods.uregex_setText(_regexMatcher, str, str.Length, out e); ExceptionFromErrorCode.ThrowIfError(e); }
/// <summary> /// Transliterate <paramref name="text"/>. /// </summary> /// <param name="text">The text to transliterate</param> /// <<param name="textCapacityMultiplier">The capacity for the buffer that holds the /// transliterated text, expressed as a multiplier of the text length.</param> /// <returns> /// The transliterated text, truncated to a maximum of `text.Length * textCapacityMultiplier` characters. /// </returns> public string Transliterate(string text, int textCapacityMultiplier = 3) { if (textCapacityMultiplier < 1) { throw new ArgumentException(nameof(textCapacityMultiplier)); } var unicodeBytes = Encoding.Unicode.GetBytes(text); var textLength = text.Length; var textCapacity = textLength * textCapacityMultiplier; var start = 0; var limit = textLength; const int charSize = sizeof(char); Debug.Assert(textCapacity * charSize >= unicodeBytes.Length); // it's tempting to use Marshal.SystemDefaultCharSize instead of sizeof(char). // However, on Linux for whatever reason that returns 1 instead of the expected 2. var textPtr = Marshal.AllocHGlobal(textCapacity * charSize); Marshal.Copy(unicodeBytes, 0, textPtr, unicodeBytes.Length); NativeMethods.utrans_transUChars(_transliteratorHandle, textPtr, ref textLength, textCapacity, start, ref limit, out var status); ExceptionFromErrorCode.ThrowIfError(status); var result = Marshal.PtrToStringUni(textPtr, textLength); Marshal.FreeHGlobal(textPtr); return(result); }
/// <summary> /// Get the standard name for an encoding converter, accoding to some standard. /// </summary> /// <param name="name">The canonical name of the converter</param> /// <param name="standard">The name of the standard, e.g. "IANA"</param> /// <returns>The name as a string, or <c>null</c> if no name could be determined.</returns> public static string GetStandardName(string name, string standard) { var resultPtr = NativeMethods.ucnv_getStandardName(name, standard, out var status); ExceptionFromErrorCode.ThrowIfError(status); return(resultPtr == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(resultPtr)); }
/// <summary> /// Returns the amount of time to be added to local standard time to get local wall clock time. /// </summary> /// <returns>the amount of saving time in milliseconds</returns> public int GetDstSavings() { int result = NativeMethods.ucal_getDSTSavings(zoneId, out ErrorCode errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode); return(result); }
/// <summary> /// Get a paragraph, given a position within the text. /// </summary> /// <param name="charIndex">The index of a character within the text, in the range [0..<see cref="ProcessedLength"/>-1]</param> /// <param name="paraStart">Will receive the index of the first character of the paragraph in the text</param> /// <param name="paraLimit">Will receive the limit of the paragraph</param> /// <param name="paraLevel">Will receive the level of the paragraph</param> /// <returns>The index of the paragraph containing the specified position</returns> public int GetParagraph(int charIndex, out int paraStart, out int paraLimit, out byte paraLevel) { var ret = NativeMethods.ubidi_getParagraph(_biDi, charIndex, out paraStart, out paraLimit, out paraLevel, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "Paragraph retrieval failed! " + errorCode); return(ret); }
/// <summary> /// Get an ICU Transliterator. /// </summary> /// <param name="id">a valid transliterator ID</param> /// <param name="dir">the desired direction</param> /// <param name="rules">the transliterator rules. If <c>null</c> then a system transliterator /// matching the ID is returned.</param> /// <returns> /// A Transliterator class instance. Be sure to call the instance's `Dispose` method to clean up. /// </returns> public static Transliterator CreateInstance(string id, UTransDirection dir = UTransDirection.Forward, string rules = null) { var handle = NativeMethods.utrans_openU(id, dir, rules, out _, out var status); ExceptionFromErrorCode.ThrowIfError(status); return(new Transliterator(handle)); }
public string Next() { var str = NativeMethods.uenum_unext(this, out var length, out var e); ExceptionFromErrorCode.ThrowIfError(e); return(str == IntPtr.Zero ? null : Marshal.PtrToStringUni(str, length)); }
/// <summary> /// Get a visual-to-logical index map (array) for the characters in the BiDi (paragraph or line) object. /// </summary> /// <returns>An array of <see cref="ResultLength"/>indexes which will reflect the reordering of the character</returns> public int[] GetVisualMap() { var map = new int[ResultLength]; NativeMethods.ubidi_getVisualMap(_biDi, map, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "Get visual map failed! " + errorCode); return(map); }
/// <summary> /// Returns the timezone data version currently used by ICU. /// </summary> /// <returns>the version string, such as "2007f"</returns> public static string GetTZDataVersion() { var ptr = NativeMethods.ucal_getTZDataVersion(out ErrorCode errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode); return(Marshal.PtrToStringAnsi(ptr)); }
/// <summary> /// constructor /// </summary> /// <param name="regexp">a unicode regular expression</param> /// <param name="flags">a bitOred URegexpFlag</param> public RegexMatcher(string regexp, URegexpFlag flags = URegexpFlag.NONE) { _regexp = regexp; ErrorCode e; ParseError parseError; _regexMatcher = NativeMethods.uregex_open(_regexp, _regexp.Length, (uint)flags, out parseError, out e); ExceptionFromErrorCode.ThrowIfError(e); }
/// <summary> /// Returns a reordered string for a piece of text (one or more paragraphs) set by <see cref="SetPara(string, byte, byte[])"/> or /// for a line of text set by <see cref="SetLine(int, int)"/>. /// </summary> /// <param name="options">Options for the reordering that control how the reordered text is written.</param> /// <returns>The reordered string</returns> public string GetReordered(CallReorderingOptions options) { var buff = new char[ProcessedLength * 2]; var len = NativeMethods.ubidi_writeReordered(_biDi, buff, buff.Length * 2, (ushort)options, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "BiDi reordering failed! " + errorCode); return(new string(buff, 0, len)); }
/// <summary> /// Get an enumeration of levels for each character. /// </summary> /// <returns></returns> public IEnumerable <byte> GetLevels() { var levels = NativeMethods.ubidi_getLevels(_biDi, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "BiDi level retrieval failed! " + errorCode); var ret = new byte[ProcessedLength]; Marshal.Copy(levels, ret, 0, ret.Length); return(ret); }
/// <summary> /// Reverse a Right-To-Left run of Unicode text. /// </summary> /// <param name="str">The RTL text.</param> /// <param name="options">Options for the reordering that control how the reordered text is written.</param> /// <returns>The reversed string</returns> public static string ReverseString(string str, CallReorderingOptions options) { if (str == null) { return(""); } var buff = new char[str.Length]; var len = NativeMethods.ubidi_writeReverse(str, str.Length, buff, buff.Length, (ushort)options, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "BiDi reversing failed! " + errorCode); return(new string(buff, 0, len)); }
/// <summary> /// Perform the Unicode Bidi algorithm. /// </summary> /// <param name="text">The text that the Bidi algorithm will be performed on</param> /// <param name="paraLevel">Specifies the default level for the text; it is typically 0 (LTR) or 1 (RTL)</param> /// <param name="embeddingLevels">May be used to preset the embedding and override levels, ignoring characters like LRE and PDF in the text; /// a level overrides the directional property of its corresponding (same index) character if the level has the UBIDI_LEVEL_OVERRIDE bit set</param> /// <remarks> /// This function takes a piece of plain text containing one or more paragraphs, with or without externally specified embedding levels from styled /// text and computes the left-right-directionality of each character. /// /// If the entire text is all of the same directionality, then the function may not perform all the steps described by the algorithm, i.e., /// some levels may not be the same as if all steps were performed.This is not relevant for unidirectional text. /// /// For example, in pure LTR text with numbers the numbers would get a resolved level of 2 higher than the surrounding text according to the /// algorithm.This implementation may set all resolved levels to the same value in such a case. /// /// The text can be composed of multiple paragraphs. Occurrence of a block separator in the text terminates a paragraph, and whatever comes /// next starts a new paragraph.The exception to this rule is when a Carriage Return (CR) is followed by a Line Feed (LF). Both CR and LF are /// block separators, but in that case, the pair of characters is considered as terminating the preceding paragraph, and a new paragraph will /// be started by a character coming after the LF. /// </remarks> public void SetPara(string text, byte paraLevel, byte[] embeddingLevels) { if (_para != IntPtr.Zero) { Marshal.FreeHGlobal(_para); _para = IntPtr.Zero; } if (text == null) { throw new ArgumentNullException(nameof(text)); } // icu BiDi expects the para pointer to live for the life of the structure, so we have to stash it _para = Marshal.StringToHGlobalUni(text); NativeMethods.ubidi_setPara(_biDi, _para, text.Length, paraLevel, embeddingLevels, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "BiDi analysis failed! " + errorCode); }
private static string GetString(Func <IntPtr, int, Tuple <ErrorCode, int> > lambda, bool isUnicodeString = false, int initialLength = 255) { var length = initialLength; var resPtr = Marshal.AllocCoTaskMem(length * 2); try { var(err, outLength) = lambda(resPtr, length); if (err != ErrorCode.BUFFER_OVERFLOW_ERROR && err != ErrorCode.STRING_NOT_TERMINATED_WARNING) { ExceptionFromErrorCode.ThrowIfError(err); } if (outLength >= length) { err = ErrorCode.NoErrors; // ignore possible U_BUFFER_OVERFLOW_ERROR or STRING_NOT_TERMINATED_WARNING Marshal.FreeCoTaskMem(resPtr); length = outLength + 1; // allow room for the terminating NUL (FWR-505) resPtr = Marshal.AllocCoTaskMem(length * 2); (err, outLength) = lambda(resPtr, length); } ExceptionFromErrorCode.ThrowIfError(err); if (outLength < 0) { return(null); } var result = isUnicodeString ? Marshal.PtrToStringUni(resPtr) : Marshal.PtrToStringAnsi(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); } }
/// <summary> /// Returns a string in a resource that has a given <paramref name="key"/>. /// </summary> /// <param name="key">The name of the string to retrieve</param> /// <returns>A string containing the requested string, or <c>string.Empty</c> if the /// string was not found (or if that key represented a different type of data, such as a /// number or a resource bundle subsection). May also throw an Exception in exceptional /// error situations.</returns> /// <remarks>This procedure works only with table resources.</remarks> public string GetStringByKey(string key) { if (IsNull) { return(string.Empty); } var resultPtr = NativeMethods.ures_getStringByKey(_ResourceBundle, key, out var len, out var status); if (status.IsFailure()) { if (status == ErrorCode.MISSING_RESOURCE_ERROR || status == ErrorCode.INVALID_FORMAT_ERROR) { return(string.Empty); } ExceptionFromErrorCode.ThrowIfError(status, $"- GetStringByKey failed for key {key}"); } return(resultPtr == IntPtr.Zero ? string.Empty : Marshal.PtrToStringUni(resultPtr, len)); }
private static IEnumerable <TimeZone> CreateTimeZoneList(Func <Tuple <SafeEnumeratorHandle, ErrorCode> > enumeratorSource) { List <TimeZone> timeZones = new List <TimeZone>(); (SafeEnumeratorHandle enumerator, ErrorCode errorCode) = enumeratorSource(); ExceptionFromErrorCode.ThrowIfError(errorCode); try { string timezoneId = enumerator.Next(); while (timezoneId != null) { timeZones.Add(new TimeZone(timezoneId)); timezoneId = enumerator.Next(); } } finally { enumerator.Dispose(); } return(timeZones); }
/// <summary> /// Sets a BiDi object to contain the reordering information, especially the resolved levels, for all the characters in a line of text. /// </summary> /// <param name="start">The line's first index into the text</param> /// <param name="limit">Position just behind the line's last index into the text (its last index +1)</param> /// <returns></returns> public BiDi SetLine(int start, int limit) { NativeMethods.ubidi_setLine(_biDi, start, limit, out var lineBidi, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "BiDi line creation failed! " + errorCode); return(new BiDi(lineBidi)); }
/// <summary> /// Get a paragraph, given the index of this paragraph. /// </summary> /// <param name="paraIndex">The number of the paragraph, in the range [0..<see cref="CountParagraphs"/>-1]</param> /// <param name="paraStart">Will receive the index of the first character of the paragraph in the text</param> /// <param name="paraLimit">Will receive the limit of the paragraph</param> /// <param name="paraLevel">Will receive the level of the paragraph</param> public void GetParagraphByIndex(int paraIndex, out int paraStart, out int paraLimit, out byte paraLevel) { NativeMethods.ubidi_getParagraphByIndex(_biDi, paraIndex, out paraStart, out paraLimit, out paraLevel, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "Paragraph retrieval failed! " + errorCode); }
/// <summary> /// Sets the default time zone to be the specified time zone. /// </summary> /// <param name="timezone">The given timezone. </param> public static void SetDefault(TimeZone timezone) { NativeMethods.ucal_setDefaultTimeZone(timezone.Id, out ErrorCode errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode); }
/// <summary> /// Creates a new BiDi object with preallocated memory for internal structures. /// </summary> /// <param name="maxLength">The maximum text or line length that internal memory will be preallocated for</param> /// <param name="maxRunCount">The maximum anticipated number of same-level runs that internal memory will be preallocated for</param> public BiDi(int maxLength, int maxRunCount) { _biDi = NativeMethods.ubidi_openSized(maxLength, maxRunCount, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode, "Creating BiDi object failed! " + errorCode); }
/// <summary> /// Constructor /// </summary> /// <param name="packageName">The packageName and locale together point to an ICU udata /// object, as defined by udata_open( packageName, "res", locale, err) or equivalent. /// Typically, packageName will refer to a (.dat) file, or to a package registered with /// udata_setAppData(). Using a full file or directory pathname for packageName is /// deprecated.</param> /// <param name="locale">This is the locale this resource bundle is for.</param> public ResourceBundle(string packageName, string locale) { _ResourceBundle = NativeMethods.ures_open(packageName, locale, out var errorCode); ExceptionFromErrorCode.ThrowIfError(errorCode); }
/// <summary> /// Constructs a new MessageFormat using the given pattern and locale. /// </summary> /// <param name="pattern">Pattern used to construct object. </param> /// <param name="localeId">The locale to use for formatting dates and numbers. </param> /// <remarks>If the pattern cannot be parsed, an exception is thrown.</remarks> public MessageFormatter(string pattern, string localeId) { _Formatter = NativeMethods.umsg_open(pattern, pattern.Length, localeId, out var parseError, out var status); ExceptionFromErrorCode.ThrowIfError(status); }