This module contains new string types and utilities for dealing with Windows strings. The Windows SDK uses the following types to represent a character or string:
type CHAR = char WCHAR = uint16 LPSTR|LPCSTR = ptr CHAR # however, it should be an ANSI string, not a UTF-8 string LPWSTR|LPCWSTR = ptr WCHAR BSTR = distinct ptr WCHAR # BSTR is not binary compatible with LPWSTR (ptr) array[I, CHAR] # sometimes a string is defined as array[1, CHAR], but not necessarily only one character (ptr) array[I, WCHAR] # sometimes a string is defined as array[1, WCHAR], but not necessarily only one wide character
By default, Nim's string type uses UTF-8 encoding. However, Windows uses wide-character strings (a.k.a. Unicode strings) or multibyte-character strings (a.k.a. ANSI strings). Therefore, this module introduces the following string types.
type string # Nim's built-in string type, UTF-8 encoded by default; can sometimes be an ANSI string. cstring # compatible with the type char* in ANSI C wstring = distinct string # a new string type to store Unicode strings mstring = distinct string # a new string type to store ANSI strings
Some type classes are also defined for convenience when dealing 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 is pseudocode for the 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 UTF-8-encoded strings. # Use `%$` to treat `openArray[SomeChar]` explicitly as a string. 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-encoded strings. # 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 a buffer with a string, including a null terminator. # These operators don't convert the encoding (they copy byte by byte). # Please make sure both sides have the same character size. # If the destination does not have 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 a const string or string literal can be converted to a Unicode string at compile time; # otherwise it is just `+$`. template T(s: string): mstring|wstring # Generate a wstring or mstring depending on the conditional symbol: useWinAnsi. # For example: (this code works under both Unicode and ANSI modes) MessageBox(0, T"hello, world", T"Nim is Powerful 中文測試", 0) template T(n: Natural): mstring|wstring # Generate a wstring or mstring buffer depending on the conditional symbol: useWinAnsi. # Use `&` to get the buffer address and then pass to Windows API. converter winstrConverter(s: SomeString): SomeBuffer # With these converters, passing strings to the Windows API is easier. # The 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 (UTF-8 to Unicode). # A new memory block will be allocated. However, these converters are useful and convenient. # cstring|string => LPWSTR|BSTR
There are also new string functions for dealing with wstring and mstring like the 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 doesn't use the built-in WideCString, but still supports it.
converter winstrConverter(s: WideCString): LPWSTR # WideCString can be sent directly to the Windows API (Unicode only). proc `+$`(s: WideCString): wstring # Converts WideCString to wstring. proc newWideCString(s: wstring): WideCString # Converts wstring to WideCString.
Imports
-
winimbase, windef
Types
mIndex = distinct int
- Using mIndex with substr, [], or []= on an mstring means indexing by MBCS characters, not by bytes.
mstring = distinct string
- New string type to store multibyte character strings (a.k.a. ANSI strings).
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.
SomeChar = byte | char | WCHAR
- Type class matching all char 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 UTF-16 code units for Windows wide strings.
Procs
proc `$`(s: Stringable): string {.inline.}
- Converts any stringable type to string. This operator assumes string|cstring|ptr char|openArray[char] are UTF-8-encoded strings.
proc `$$`(s: Stringable): string {.inline.}
- Converts any stringable type to string. This operator assumes string|cstring|ptr char|openArray[char] are ANSI-encoded strings.
proc `%$`(s: Stringable): string {.inline.}
- Converts any stringable type to string. Always treats openArray[SomeChar] as a string. This operator assumes string|cstring|ptr char|openArray[char] are UTF-8-encoded strings.
proc `&`(s, u: wstring): wstring {.inline, ...raises: [], tags: [], forbids: [].}
- Concatenates s with u.
proc `&`(s: cstring): ptr char {.inline, ...raises: [], tags: [], forbids: [].}
- Gets the address of the first character of a cstring.
proc `&`(s: mstring): ptr char {.inline, ...raises: [], tags: [], forbids: [].}
- Gets the address of the first character of a mstring.
proc `&`(s: string): ptr char {.inline, ...raises: [], tags: [], forbids: [].}
- Gets the address of the first character of a string.
proc `&`(s: wstring): ptr WCHAR {.inline, ...raises: [], tags: [], forbids: [].}
- Gets the address of the first WCHAR of a wstring.
proc `&`(x, y: mstring): mstring {.borrow, ...raises: [], tags: [], forbids: [].}
- Concatenates x with y.
proc `+$`(s: Stringable): wstring {.inline.}
- Converts any stringable type to wstring. This operator assumes string|cstring|ptr char|openArray[char] are UTF-8-encoded strings.
proc `+$$`(s: Stringable): wstring {.inline.}
- Converts any stringable type to wstring. This operator assumes string|cstring|ptr char|openArray[char] are ANSI-encoded strings.
proc `-$`(s: Stringable): mstring {.inline.}
- Converts any stringable type to mstring. This operator assumes string|cstring|ptr char|openArray[char] are UTF-8-encoded strings.
proc `-$$`(s: Stringable): mstring {.inline.}
- Converts any stringable type to mstring. This operator assumes string|cstring|ptr char|openArray[char] are ANSI-encoded strings.
proc `[]`(s: mstring; i: int): char {.inline, ...raises: [], tags: [], forbids: [].}
- Index operator for mstring, counting by bytes.
proc `[]`(s: mstring; i: mIndex): mstring {....raises: [], tags: [], forbids: [].}
- Index operator for mstring, counting by MBCS characters.
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: [], forbids: [].}
- Index assignment operator for mstring, counting by MBCS characters, and only the first MBCS character of u will be used.
proc add(s: var wstring; u: wstring) {....raises: [], tags: [], forbids: [].}
- Appends u to s in place.
proc add(x: var mstring; y: byte) {.inline, ...raises: [], tags: [], forbids: [].}
- Appends y to x in place.
proc add(x: var mstring; y: char) {.borrow, ...raises: [], tags: [], forbids: [].}
- Appends y to x in place.
proc newMString(L: Natural): mstring {....raises: [], tags: [], forbids: [].}
- Returns a new mstring of length L, counting by bytes.
proc newMString(s: string | cstring | wstring): mstring {.inline, ...deprecated: "use `-$` instead".}
- Returns a new mstring.
proc newMStringOfCap(L: Natural): mstring {....raises: [], tags: [], forbids: [].}
- Returns a new mstring of length 0 but with capacity L, counting by bytes.
proc newWideCString(s: wstring): WideCStringObj {.inline, ...raises: [], tags: [], forbids: [].}
- Converts wstring to WideCString.
proc newWString(L: Natural): wstring {....raises: [], tags: [], forbids: [].}
- Returns a new wstring of length L, counted in UTF-16 code units.
proc newWString(s: cstring | string | mstring): wstring {.inline, ...deprecated: "use `+$` instead".}
- Returns a new wstring.
proc newWStringOfCap(L: Natural): wstring {....raises: [], tags: [], forbids: [].}
- Returns a new wstring of length 0 but with capacity L, counting by UTF-16 code units.
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 substr(s: mstring; first = 0): mstring {.borrow, ...raises: [], tags: [], forbids: [].}
- 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: [], forbids: [].}
- 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: [], forbids: [].}
- 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: [], forbids: [].}
- Copies a slice of s into a new mstring and returns it, counting by MBCS characters.
proc toHex(s: cstring): string {.inline, ...raises: [], tags: [], forbids: [].}
- Converts a cstring to its hexadecimal representation. No prefix like 0x is generated.
Iterators
Converters
converter winstrConverterBSTRToLPWSTR(x: BSTR): LPWSTR {....raises: [], tags: [], forbids: [].}
- Borrows the BSTR buffer as LPWSTR for an immediate input call. The callee must not retain, modify, or free it.
converter winstrConverterCStringToBSTR(x: cstring): BSTR {....raises: [], tags: [], forbids: [].}
- Borrows a BSTR-layout-compatible input for an immediate call. The callee must not retain or free it; a later conversion on this thread may reuse it.
converter winstrConverterCStringToLPWSTR(x: cstring): LPWSTR {....raises: [], tags: [], forbids: [].}
- Borrows an LPWSTR for an immediate input call. The callee must not retain, modify, or free it; a later conversion on this thread may reuse it.
converter winstrConverterCStringToPtrChar(x: cstring): ptr char {....raises: [], tags: [], forbids: [].}
- Borrows the cstring buffer as ptr char. Its lifetime is the source lifetime, and the callee must not modify or free it.
converter winstrConverterMStringToLPSTR(x: mstring): LPSTR {....raises: [], tags: [], forbids: [].}
- Borrows an ANSI/MBCS LPSTR for an immediate input call. The callee must not retain, modify, or free it.
converter winstrConverterMStringToPtrChar(x: mstring): ptr char {....raises: [], tags: [], forbids: [].}
- Borrows an ANSI/MBCS ptr char for an immediate input call. The callee must not retain, modify, or free it.
converter winstrConverterStringToBSTR(x: string): BSTR {....raises: [], tags: [], forbids: [].}
- Borrows a BSTR-layout-compatible input for an immediate call. The callee must not retain or free it; a later conversion on this thread may reuse it.
converter winstrConverterStringToLPWSTR(x: string): LPWSTR {....raises: [], tags: [], forbids: [].}
- Borrows an LPWSTR for an immediate input call. The callee must not retain, modify, or free it; a later conversion on this thread may reuse it.
converter winstrConverterStringToPtrChar(x: string): ptr char {....raises: [], tags: [], forbids: [].}
- Borrows a UTF-8 ptr char for an immediate input call. The callee must not retain, modify, or free it.
converter winstrConverterWideCStringToLPWSTR(x: WideCStringObj): LPWSTR {. ...raises: [], tags: [], forbids: [].}
- Borrows the WideCString buffer as LPWSTR; the pointer is valid only while the source remains alive and must not be freed.
converter winstrConverterWStringToBSTR(x: wstring): BSTR {....raises: [], tags: [], forbids: [].}
- Borrows a BSTR-layout-compatible input for an immediate call. The callee must not retain or free it; a later conversion on this thread may reuse it.
converter winstrConverterWStringToLPWSTR(x: wstring): LPWSTR {....raises: [], tags: [], forbids: [].}
- Borrows an LPWSTR for an immediate input call. The callee must not retain, modify, or free it.
Templates
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
- Generates a wstring or mstring buffer depending on the conditional symbol: useWinAnsi. Uses & to get the buffer address and then passes it to the Windows API.
template T(x: string): untyped
- Generates a wstring or mstring depending on the conditional symbol: useWinAnsi.