-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathOsString.milone
163 lines (132 loc) · 5.01 KB
/
OsString.milone
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Provides OsString for interop with OS API.
open Std.Block
open Std.Ptr
open Std.Region
open Std.Vector
// For memcpy.
__nativeDecl "#include <string.h>"
// See also milone.h and milone_platform.c
// #milone_os_string
/// `TCHAR` on Windows. `char` on Linux.
type OsChar = __nativeType<OsChar>
/// `LPCTSTR` on Windows. `char const *` on Linux.
type OsStringPtr = InPtr<OsChar>
/// String of OS-dependent encoding.
///
/// This holds the same invariants as String.
///
/// ## Length of String
///
/// Length means the number of code units.
/// On Windows where the native encoding is UTF-16 (Unicode),
/// length is half of the number of bytes.
///
/// String isn't guaranteed to be NUL-terminated
/// and length doesn't count terminating NUL.
type OsString = __nativeType<``struct MiloneOsString``>
let private toPtrLenPair (s: OsString) : OsStringPtr * int =
__nativeExpr ("{0}.ptr", s), __nativeExpr ("{0}.len", s)
/// Unsafely creates a clone of OS-encode string.
/// Result is NUL-terminated.
///
/// SAFETY:
///
/// - Input span must be readable.
/// - These contents must be valid as the OS-native encoding.
let private unsafeCloneOfRawParts (ptr: OsStringPtr) (len: int) : OsStringPtr =
assert (len = 0 || ptr <> Ptr.nullPtr)
if len <> 0 then
let destPtr: OutPtr<OsChar> = Region.alloc (len + 1)
__nativeStmt ("memcpy({0}, {1}, {2});", destPtr, ptr, unativeint len * unativeint sizeof<OsChar>)
Ptr.cast destPtr
else
__nativeExpr """((OsChar const *)L"")"""
let private uintCompare (l: uint) r = compare l r
module OsChar =
/// U+0000
let nul: OsChar = __nativeExpr "(OsChar)0"
let ofByte (n: byte) : OsChar = __nativeExpr ("(OsChar){0}", n)
/// Casts an OsChar to byte.
///
/// This function is lossy on Windows where OsChar isn't byte-sized.
let toByte (n: OsChar) : byte = __nativeExpr ("(uint8_t){0}", n)
let ofUInt16 (n: uint16) : OsChar = __nativeExpr ("(OsChar){0}", n)
let toUInt16 (n: OsChar) : uint16 = __nativeExpr ("(uint16_t){0}", n)
let ofUInt (n: uint) : OsChar = __nativeExpr ("(OsChar){0}", n)
let toUInt (n: OsChar) : uint = __nativeExpr ("(uint32_t){0}", n)
let ofChar (c: char) : OsChar = __nativeExpr ("(OsChar)(uint8_t){0}", c)
/// Converts an OsChar value to char if it's an ASCII character.
/// Returns NUL ('\x00') if not.
let asChar (c: OsChar) : char =
if toUInt c <= 255u then
char (toByte c)
else
'\x00'
let isAscii (c: OsChar) : bool = toUInt c <= 255u
let equals (l: OsChar) (r: OsChar) : bool =
__nativeExpr ("({0} == {1})", l, r)
let compare (l: OsChar) (r: OsChar) : int =
uintCompare (toUInt l) (toUInt r)
module OsString =
/// Gets an empty OsString.
let empty () : OsString =
__nativeExpr """(struct MiloneOsString){.ptr = (OsChar const *)L"", .len = 0}"""
/// Creates an OS-encode string by converting from a UTF-8 string.
let ofString (s: string) : OsString =
__nativeExpr ("milone_os_string_of({0})", s)
/// Creates a UTF-8 string by converting from an OS-encode string.
let toString (s: OsString) : string =
__nativeExpr ("milone_os_string_to({0})", s)
/// Gets "length" of a string.
let length (s: OsString) : int =
let _, len = toPtrLenPair s
len
/// Exposes code units of an OsString as a block.
///
/// PERF: Contents aren't copied.
let asBlock (s: OsString) : Block<OsChar> =
let ptr, len = toPtrLenPair s
BlockExt.unsafeCreate ptr len
/// Gets a "character" at the specified position.
/// Index must be within the bounds.
let item (index: int) (s: OsString) : OsChar =
let ptr, len = toPtrLenPair s
assert (uint index < uint len)
Ptr.read (ptr: InPtr<OsChar>).[index]
module OsStringExt =
/// Exposes a pointer of buffer.
let asPtr (s: OsString) : OsStringPtr =
let ptr, _ = toPtrLenPair s
ptr
/// Unsafely creates an OsString
/// of a pointer and a length without copying.
///
/// SAFETY:
///
/// - Input must satisfy invariants of OsString.
/// - The result is valid as long as the given pointer is valid.
let unsafeCreate (ptr: OsStringPtr) (len: int) : OsString =
assert (ptr <> Ptr.nullPtr)
assert (len >= 0)
__nativeExpr ("(struct MiloneOsString){.ptr = {0}, .len = {1}}", ptr, len)
/// Unsafely creates an OsString
/// of a NUL-terminated pointer without copying.
/// Length is counted.
///
/// SAFETY:
///
/// - Input must satisfy invariants of OsString.
/// - The result is valid as long as the given pointer is valid.
let unsafeOfNative (ptr: OsStringPtr) : OsString =
__nativeExpr ("milone_os_string_borrow({0})", ptr)
/// Unsafely creates an OsString by copying contents from a pointer.
let unsafeOfRawParts (ptr: OsStringPtr) (len: int) : OsString =
unsafeCreate (unsafeCloneOfRawParts ptr len) len
/// Unsafely creates an OsString
/// of a block of OsChar.
///
/// SAFETY: Contents of block must be valid in the encoding
/// but that's unchecked.
let unsafeOfBlockUnchecked (block: Block<OsChar>) : OsString =
let ptr, len = BlockExt.unsafeToRawParts block
unsafeCreate ptr len