This module contains new string types and utilities to deal with strings in Windows. Windows SDK use following types to represent a char or a string:
type CHAR = char WCHAR = uint16 LPSTR|LPCSTR = ptr CHAR # however, it should be ansi string, not utf8 string LPWSTR|LPCWSTR = ptr WCHAR BSTR = distinct ptr WCHAR # BSTR is not binary compatible with LPWSTR (ptr) array[I, CHAR] # sometimes string defined as array[1, CHAR] but not only one char (ptr) array[I, WCHAR] # sometimes string defined as array[1, WCHAR] but not only one widechar
By default, Nim's string type is utf8 encoding. However, Windows use wide character string (aka. unicode string) or multibyte character string (aka. ansi string). So, this module introduce following string types.
type string # nim built-in string type, utf8 encoding by default, can be ansi string sometimes. cstring # compatible to the type char* in Ansi C wstring = distinct string # new string type to store unicode string mstring = distinct string # new string type to store ansi string
Some type classes are also defined for convenience to deal with strings.
type SomeChar = byte | char | WCHAR SomeString = string | mstring | wstring SomeBuffer[I] = ptr SomeChar | array[I, SomeChar] | ptr array[I, SomeChar] | ptr UncheckedArray[SomeChar] | openArray[SomeChar] | seq[SomeChar] Stringable = SomeChar | SomeString | SomeBuffer | cstring | BSTR
Here are the pseudocode for most useful functions introduced by this module.
proc `&`(s: cstring|string|wstring|mstring): pointer # Get address of the first char of a string. # For string, it has a similar meaning to cstring(s). proc `$`(x: Stringable): string proc `+$`(x: Stringable): wstring proc `-$`(x: Stringable): mstring # Convert any stringable type to string, wstring, or mstring. # These operators assume string|cstring|ptr char|openArray[char] are utf8 encoding. # setOpenArrayStringable() can be used to switch the behavior of `$` operator. proc `$$`(x: Stringable): string proc `+$$`(x: Stringable): wstring proc `-$$`(x: Stringable): mstring # Convert any stringable type to string, wstring, or mstring. # These operators assume string|cstring|ptr char|openArray[char] are ansi encoding. # For mstring|wstring|LPWSTR etc, these operators are the same as `$`, `+$`, `-$`. template `<<`(s: SomeString, b: SomeBuffer) template `<<`(b: SomeBuffer, s: SomeString) template `<<<`(b: SomeBuffer, s: SomeString) template `>>`(a: typed, b: typed) = b << a template `>>>`(a: typed, b: typed) = b <<< a # String << Buffer or Buffer >> String: Fill string by buffer. # Buffer << String or String >> Buffer: Fill buffer by string. # Buffer <<< String or String >>> Buffer: Fill buffer by string, include a null. # These operators don't convert the encoding (copy byte by byte). # Please make sure both side have the same character size. # If destination don't have the length information (e.g. pointer or UncheckedArray), # please make sure the buffer size is large enough. proc nullTerminate(s: var SomeString) # Assume a string is null terminated and set the correct length. proc nullTerminated[T: SomeString](s: T): T # Assume a string is null terminated and return the length-corrected string. template L(s: string): wstring # Generate wstring at compile-time if possible. # Only const string or string literal can be converted to unicode string at compile-time, # otherwise it is just `+$`. template T(s: string): mstring|wstring # Generate wstring or mstring depend on conditional symbol: useWinAnsi. # For example: (this code works under both unicode and ansi mode) MessageBox(0, T"hello, world", T"Nim is Powerful 中文測試", 0) template T(n: Natural): mstring|wstring # Generate wstring or mstring buffer depend on conditional symbol: useWinAnsi. # Use `&` to get the buffer address and then pass to Windows API. converter winstrConverter(s: SomeString): SomeBuffer # With these converters, passing string to Windows API is more easy. # Following converters don't need encoding conversion: # string => LPSTR|ptr char # mstring => LPSTR|ptr char # wstring => LPWSTR|BSTR # cstring => ptr char # BSTR => LPWSTR # # Some converters DO need encoding conversion (utf8 to unicode). # New memory block will be allocated. However, they are useful and convenience. # cstring|string => LPWSTR|BSTR
There are also new string functions to deal with wstring and mstring just like built-in string type.
proc newWString(len: Natural): wstring # Generate wstring buffer proc newMString(len: Natural): mstring # Generate mstring buffer proc setLen(s: var mstring|wstring, newLen: Natural) proc substr(s: wstring|mstring, first = 0): wstring|mstring proc substr(s: wstring|mstring, first, last: int): wstring|mstring proc len(s: wstring|mstring): int proc high(s: wstring|mstring): int proc low(s: wstring|mstring): int proc repr(s: wstring|mstring): string proc toHex(s: wstring|mstring): string proc `[]`(s: wstring|mstring, i: int): WCHAR|mstring proc `[]=`(s: wstring|mstring, i: int, u: WCHAR|CHAR) proc `[]=`(s: wstring|mstring, i: int, u: wstring|mstring) proc `[]`(s: wstring|mstring, x: HSlice) proc `[]=`(s: var wstring|var mstring, x: HSlice[int], b: wstring|mstring) proc `==`(x, y: wstring|mstring): bool proc `<=`(x, y: wstring|mstring): bool proc `<`(x, y: wstring|mstring): bool proc cmp(x, y: wstring|mstring): int proc `&`(s: wstring|mstring, t: wstring|mstring): wstring|mstring iterator items(s: wstring|mstring): WCHAR|mstring iterator mitems(s: var wstring): WCHAR iterator pairs(s: wstring|mstring): tuple[key: int|mIndex, val: WCHAR|mstring] iterator mpairs(s: var wstring): WCHAR
Winim don't use built-in WideCString, but still support it.
converter winstrConverter(s: WideCString): LPWSTR # WideCString can be sent to Windows API directly (unicode only). proc `+$`(s: WideCString): wstring # Converts WideCString to wstring. proc newWideCString(s: wstring): WideCString # Converts wstring to WideCString.
Types
mIndex = distinct int
- Use mIndex in substr, [] or []= for mstring means index by MBCS characters, not by bytes.
mstring = distinct string
- New string type to store multibyte character string (aka. ansi string).
SomeBuffer[I] = ptr SomeChar | array[I, SomeChar] | ptr array[I, SomeChar] | ptr UncheckedArray[SomeChar] | openArray[SomeChar] | seq[SomeChar]
- Type class matching all string buffer types.
SomeString = string | mstring | wstring
- Type class matching all string types.
Stringable = SomeChar | SomeString | SomeBuffer | cstring | BSTR
- Type class matching all stringable types.
wstring = distinct string
- New string type to store wide character string (aka. unicode string).
Procs
proc `$$`(s: Stringable): string {.inline.}
- Convert any stringable type to string. This operator assume string|cstring|ptr char|openArray[char] is ansi encoding.
proc `$`(s: Stringable): string {.inline.}
- Convert any stringable type to string. This operator assume string|cstring|ptr char|openArray[char] is utf8 encoding.
proc `%$`(s: Stringable): string {.inline.}
- Convert any stringable type to string. Always treat openArray[SomeChar] as string. This operator assume string|cstring|ptr char|openArray[char] is utf8 encoding.
proc `&`(s: cstring): ptr char {.inline, ...raises: [], tags: [].}
- Get address of the first char of a cstring.
proc `&`(s: mstring): ptr char {.inline, ...raises: [], tags: [].}
- Get address of the first char of a mstring.
proc `&`(s: string): ptr char {.inline, ...raises: [], tags: [].}
- Get address of the first char of a string.
proc `&`(s: wstring): ptr WCHAR {.inline, ...raises: [], tags: [].}
- Get address of the first WCHAR of a wstring.
proc `+$$`(s: Stringable): wstring {.inline.}
- Convert any stringable type to wstring. This operator assume string|cstring|ptr char|openArray[char] is ansi encoding.
proc `+$`(s: Stringable): wstring {.inline.}
- Convert any stringable type to wstring. This operator assume string|cstring|ptr char|openArray[char] is utf8 encoding.
proc `+$`(s: WideCString): wstring {.inline, ...raises: [], tags: [].}
- Converts WideCString to wstring.
proc `-$$`(s: Stringable): mstring {.inline.}
- Convert any stringable type to mstring. This operator assume string|cstring|ptr char|openArray[char] is ansi encoding.
proc `-$`(s: Stringable): mstring {.inline.}
- Convert any stringable type to mstring. This operator assume string|cstring|ptr char|openArray[char] is utf8 encoding.
proc `<=`(x, y: mstring): bool {.borrow, ...raises: [], tags: [].}
- Lexicographic <= operator for mstring.
proc `<=`(x, y: wstring): bool {.borrow, ...raises: [], tags: [].}
- Lexicographic <= operator for wstring.
proc `<`(x, y: mstring): bool {.borrow, ...raises: [], tags: [].}
- Lexicographic < operator for mstring.
proc `<`(x, y: wstring): bool {.borrow, ...raises: [], tags: [].}
- Lexicographic < operator for wstring.
proc `==`(x, y: mstring): bool {.borrow, ...raises: [], tags: [].}
- Checks for equality between two mstring.
proc `==`(x, y: wstring): bool {.borrow, ...raises: [], tags: [].}
- Checks for equality between two wstring.
proc `[]=`(s: var mstring; i: int; x: char | byte) {.inline.}
- Index assignment operator for mstring, counting by bytes.
proc `[]=`(s: var mstring; i: mIndex; u: mstring) {....raises: [], tags: [].}
- Index assignment operator for mstring, counting by MBCS characters, and only first MBCS characters of u will be used.
proc `[]=`(s: var wstring; i: int; c: WCHAR | char) {.inline.}
- Index assignment operator for wstring.
proc `[]`(s: mstring; i: int): char {.inline, ...raises: [], tags: [].}
- Index operator for mstring, counting by bytes.
proc `[]`(s: mstring; i: mIndex): mstring {....raises: [], tags: [].}
- Index operator for mstring, counting by MBCS characters.
proc `[]`(s: wstring; i: int): WCHAR {.inline, ...raises: [], tags: [].}
- Index operator for wstring.
proc cmp(x, y: mstring): int {.borrow, ...raises: [], tags: [].}
- Compare proc for mstring (in binary format only).
proc cmp(x, y: wstring): int {.borrow, ...raises: [], tags: [].}
- Compare proc for wstring (in binary format only).
proc high(s: mstring): int {.borrow, ...raises: [], tags: [].}
- Returns the highest possible index of mstring.
proc high(s: wstring): int {.inline, ...raises: [], tags: [].}
- Returns the highest possible index of wstring.
proc len(s: mstring): int {.inline, ...raises: [], tags: [].}
- Returns the length of mstring, counting by bytes.
proc len(s: wstring): int {.inline, ...raises: [], tags: [].}
- Returns the length of wstring, counting by wide characters.
proc low(s: mstring): int {.borrow, ...raises: [], tags: [].}
- Returns the lowest possible index of mstring.
proc low(s: wstring): int {.inline, ...raises: [], tags: [].}
- Returns the lowest possible index of wstring.
proc mlen(s: mstring): int {....raises: [], tags: [].}
- Returns the length of mstring, counting by MBCS characters.
proc newMString(L: Natural): mstring {....raises: [], tags: [].}
- Returns a new mstring of length L, counting by bytes.
proc newMString(s: string | cstring | wstring): mstring {.inline, ...deprecated: "use `-$` instead".}
- mstring. Return a new
proc newMStringOfCap(L: Natural): mstring {....raises: [], tags: [].}
- Returns a new mstring of length 0 but with capacity L, counting by bytes.
proc newWideCString(s: wstring): WideCString {.inline, ...raises: [], tags: [].}
- Converts wstring to WideCString.
proc newWString(L: Natural): wstring {....raises: [], tags: [].}
- Returns a new wstring of length L, counting by wide characters.
proc newWString(s: cstring | string | mstring): wstring {.inline, ...deprecated: "use `+$` instead".}
- wstring. Return a new
proc newWStringOfCap(L: Natural): wstring {....raises: [], tags: [].}
- Returns a new wstring of length 0 but with capacity L, counting by wide characters.
proc nullTerminate(s: var SomeString) {.inline.}
- Assume a string is null terminated and set the correct length.
proc nullTerminated[T: SomeString](s: T): T {.inline.}
- Assume a string is null terminated and return the length-corrected string.
proc setLen(s: var mstring; L: Natural) {.inline, ...raises: [], tags: [].}
- Sets the length of mstring s to L, counting by wide bytes.
proc setLen(s: var wstring; L: Natural) {.inline, ...raises: [], tags: [].}
- Sets the length of wstring s to L, counting by wide characters.
proc setOpenArrayStringable(flag: bool): bool {.inline, discardable, ...raises: [], tags: [].}
- Nim's system.$ will return array representation for openArray[SomeChar]. After turn this option on, winstr will overwrite the defualt behavior for $ and treats openArray[SomeChar] as string.
proc substr(s: mstring; first = 0): mstring {.borrow, ...raises: [], tags: [].}
- Copies a slice of s into a new mstring and returns it, counting by bytes.
proc substr(s: mstring; first, last: int): mstring {.borrow, ...raises: [], tags: [].}
- Copies a slice of s into a new mstring and returns it, counting by bytes.
proc substr(s: mstring; first, last: mIndex): mstring {....raises: [], tags: [].}
- Copies a slice of s into a new mstring and returns it, counting by MBCS characters.
proc substr(s: mstring; first: mIndex = 0.mIndex): mstring {....raises: [], tags: [].}
- Copies a slice of s into a new mstring and returns it, counting by MBCS characters.
proc substr(s: wstring; first = 0): wstring {.inline, ...raises: [], tags: [].}
- Copies a slice of s into a new wstring and returns it.
proc substr(s: wstring; first, last: int): wstring {....raises: [], tags: [].}
- Copies a slice of s into a new wstring and returns it.
proc toHex(s: cstring): string {.inline, ...raises: [], tags: [].}
- Converts a cstring to its hexadecimal representation. No prefix like 0x is generated.
Iterators
iterator items(s: mstring): mstring {....raises: [], tags: [].}
- Iterates over each MBCS character of mstring.
iterator mitems(s: var wstring): var WCHAR {....raises: [], tags: [].}
- Iterates over each WCHAR of wstring so that you can modify the yielded value.
iterator mpairs(s: var wstring): tuple[key: int, val: var WCHAR] {....raises: [], tags: [].}
- Iterates over each WCHAR of wstring. Yields (int, var WCHAR) pairs.
Converters
converter winstrConverterBSTRToLPWSTR(x: BSTR): LPWSTR {....raises: [], tags: [].}
- Converts BSTR to LPWSTR automatically.
converter winstrConverterCStringToBSTR(x: cstring): BSTR {....raises: [], tags: [].}
- Converts cstring to BSTR automatically.
converter winstrConverterCStringToLPWSTR(x: cstring): LPWSTR {....raises: [], tags: [].}
- Converts cstring to LPWSTR automatically.
converter winstrConverterCStringToPtrChar(x: cstring): ptr char {....raises: [], tags: [].}
- Converts cstring to ptr char automatically.
converter winstrConverterMStringToLPSTR(x: mstring): LPSTR {....raises: [], tags: [].}
- Converts mstring to LPSTR automatically.
converter winstrConverterMStringToPtrChar(x: mstring): ptr char {....raises: [], tags: [].}
- Converts mstring to ptr char automatically.
converter winstrConverterStringToBSTR(x: string): BSTR {....raises: [], tags: [].}
- Converts string to BSTR automatically.
converter winstrConverterStringToLPWSTR(x: string): LPWSTR {....raises: [], tags: [].}
- Converts string to LPWSTR automatically.
converter winstrConverterStringToPtrChar(x: string): ptr char {....raises: [], tags: [].}
- Converts string to ptr char automatically.
converter winstrConverterWideCStringToLPWSTR(x: WideCString): LPWSTR {. ...raises: [], tags: [].}
- Converts WideCString to LPWSTR automatically.
converter winstrConverterWStringToBSTR(x: wstring): BSTR {....raises: [], tags: [].}
- Converts wstring to BSTR automatically.
converter winstrConverterWStringToLPWSTR(x: wstring): LPWSTR {....raises: [], tags: [].}
- Converts wstring to LPWSTR automatically.
Templates
template `<<<`[A: SomeBuffer | SomeString](a: A; b: SomeString)
- Fill buffer by string, include a null. Please make sure both side have the same character size. If destination don't have the length information (e.g. pointer or UncheckedArray), please make sure the buffer size is large enough.
template `<<`[A: SomeBuffer | SomeString; B: SomeBuffer | SomeString](a: A; b: B)
- Fill operator for SomeBuffer and SomeString. Please make sure both side have the same character size. If destination don't have the length information (e.g. pointer or UncheckedArray), please make sure the buffer size is large enough.
template `>>>`(a: typed; b: typed)
- This is the same as b <<< a.
template `>>`(a: typed; b: typed)
- This is the same as b << a.
template T(x: Natural): untyped
- Generate wstring or mstring buffer depend on conditional symbol: useWinAnsi. Use & to get the buffer address and then pass to Windows API.
template T(x: string): untyped
- Generate wstring or mstring depend on conditional symbol: useWinAnsi.