nomen-lang 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOMEN_AGENTS.md +235 -0
- package/core/System/Ansi.nm +150 -0
- package/core/System/Array.nm +358 -0
- package/core/System/BigInt.nm +887 -0
- package/core/System/Buffer.nm +526 -0
- package/core/System/Channel.nm +198 -0
- package/core/System/ClassBuffer.nm +229 -0
- package/core/System/Console.nm +211 -0
- package/core/System/Controls/Button.nm +138 -0
- package/core/System/Controls/CheckBox.nm +158 -0
- package/core/System/Controls/Container.nm +1562 -0
- package/core/System/Controls/Control.nm +28 -0
- package/core/System/Controls/Geometry.nm +101 -0
- package/core/System/Controls/Layout.nm +228 -0
- package/core/System/Controls/LayoutParams.nm +50 -0
- package/core/System/Controls/Text.nm +129 -0
- package/core/System/Controls/TextBox.nm +157 -0
- package/core/System/Controls/Window.nm +280 -0
- package/core/System/Disposable.nm +8 -0
- package/core/System/Enumerable.nm +10 -0
- package/core/System/Equatable.nm +10 -0
- package/core/System/Graph.nm +68 -0
- package/core/System/Hashable.nm +13 -0
- package/core/System/Init.nm +21 -0
- package/core/System/LinkedList.nm +64 -0
- package/core/System/List.nm +44 -0
- package/core/System/Map.nm +153 -0
- package/core/System/Math.nm +54 -0
- package/core/System/Mutex.nm +78 -0
- package/core/System/Nursery.nm +27 -0
- package/core/System/Sendable.nm +9 -0
- package/core/System/Set.nm +97 -0
- package/core/System/Stream/Directory.nm +176 -0
- package/core/System/Stream/File.nm +432 -0
- package/core/System/Stream/Http.nm +453 -0
- package/core/System/String.nm +154 -0
- package/core/System/StringBuilder.nm +249 -0
- package/core/System/Stringable.nm +8 -0
- package/core/System/Task.nm +263 -0
- package/core/System/Test.nm +241 -0
- package/core/System/Text/Json.nm +377 -0
- package/core/System/Text/JsonTree.nm +187 -0
- package/core/System/Text/Regex.nm +655 -0
- package/core/System/Time.nm +112 -0
- package/core/System/Tree.nm +70 -0
- package/core/System/Viewable.nm +27 -0
- package/core/System/bool.nm +66 -0
- package/core/System/char.nm +42 -0
- package/core/System/float.nm +43 -0
- package/core/System/int.nm +54 -0
- package/core/System/int64.nm +42 -0
- package/core/System/int8.nm +42 -0
- package/core/System/uint.nm +42 -0
- package/core/System/uint64.nm +42 -0
- package/core/System/uint8.nm +42 -0
- package/core/docs/System/Ansi.md +40 -0
- package/core/docs/System/Array.md +16 -0
- package/core/docs/System/BigInt.md +30 -0
- package/core/docs/System/Buffer.md +31 -0
- package/core/docs/System/Channel.md +10 -0
- package/core/docs/System/ClassBuffer.md +15 -0
- package/core/docs/System/Console.md +13 -0
- package/core/docs/System/Controls/Button.md +12 -0
- package/core/docs/System/Controls/CheckBox.md +15 -0
- package/core/docs/System/Controls/Container.md +82 -0
- package/core/docs/System/Controls/Control.md +5 -0
- package/core/docs/System/Controls/Geometry.md +26 -0
- package/core/docs/System/Controls/Layout.md +37 -0
- package/core/docs/System/Controls/LayoutParams.md +13 -0
- package/core/docs/System/Controls/Text.md +12 -0
- package/core/docs/System/Controls/TextBox.md +13 -0
- package/core/docs/System/Controls/Window.md +20 -0
- package/core/docs/System/Disposable.md +5 -0
- package/core/docs/System/Enumerable.md +5 -0
- package/core/docs/System/Graph.md +17 -0
- package/core/docs/System/Init.md +9 -0
- package/core/docs/System/LinkedList.md +16 -0
- package/core/docs/System/List.md +13 -0
- package/core/docs/System/Map.md +14 -0
- package/core/docs/System/Math.md +11 -0
- package/core/docs/System/Mutex.md +10 -0
- package/core/docs/System/Nursery.md +5 -0
- package/core/docs/System/Sendable.md +5 -0
- package/core/docs/System/Set.md +14 -0
- package/core/docs/System/Stream/Directory.md +12 -0
- package/core/docs/System/Stream/File.md +21 -0
- package/core/docs/System/String.md +14 -0
- package/core/docs/System/StringBuilder.md +12 -0
- package/core/docs/System/Stringable.md +5 -0
- package/core/docs/System/Task.md +15 -0
- package/core/docs/System/Text/Json.md +12 -0
- package/core/docs/System/Text/JsonTree.md +21 -0
- package/core/docs/System/Text/Regex.md +12 -0
- package/core/docs/System/Time.md +11 -0
- package/core/docs/System/Tree.md +18 -0
- package/core/docs/System/Viewable.md +5 -0
- package/core/docs/System/bool.md +9 -0
- package/core/docs/System/char.md +9 -0
- package/core/docs/System/float.md +9 -0
- package/core/docs/System/int.md +10 -0
- package/core/docs/System/int64.md +9 -0
- package/core/docs/System/int8.md +9 -0
- package/core/docs/System/uint.md +9 -0
- package/core/docs/System/uint64.md +9 -0
- package/core/docs/System/uint8.md +9 -0
- package/core/package.jsonc +4 -0
- package/dist/index.mjs +417 -5490
- package/package.json +33 -30
- package/src/args.ts +171 -0
- package/src/index.ts +53 -104
- package/src/init.ts +128 -0
- package/src/test.ts +6 -2
- package/test/fixtures/build/calc.test +0 -0
- package/test/fixtures/build/calc.test.c +0 -969
- package/test/fixtures/build/main.h +0 -170
- package/test/fixtures/calc.test.nm +0 -32
- package/tsconfig.json +0 -21
- package/vite.config.ts +0 -7
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal blocking HTTP/1.1 client.
|
|
3
|
+
*
|
|
4
|
+
* Plain `http://` only — no TLS (an `https://` URL cannot be served; use a
|
|
5
|
+
* TLS proxy or wait for a TLS-capable transport). Construct an instance,
|
|
6
|
+
* call `get`/`post` (which block until the full response is received), then
|
|
7
|
+
* read the `status` field for the response's status code. `status` is 0 when
|
|
8
|
+
* DNS resolution or the connection fails.
|
|
9
|
+
*
|
|
10
|
+
* URLs may carry an explicit port (`http://host:8080/path`); the default is
|
|
11
|
+
* 80 and the default path is `/`. `post` sends `body` with a
|
|
12
|
+
* `Content-Type: application/x-www-form-urlencoded` header and a matching
|
|
13
|
+
* `Content-Length`; only the response body (after the blank header/body
|
|
14
|
+
* separator line) is returned.
|
|
15
|
+
*
|
|
16
|
+
* var Http h = Http()
|
|
17
|
+
* var string body = h.get("http://example.com/")
|
|
18
|
+
* var int code = h.status
|
|
19
|
+
* var string r = h.post("http://example.com/submit", "hello=world")
|
|
20
|
+
**/
|
|
21
|
+
pub struct Http {
|
|
22
|
+
// HTTP status code from the most recent request (e.g. 200). 0 if DNS or
|
|
23
|
+
// the connection failed.
|
|
24
|
+
pub var int status = 0
|
|
25
|
+
|
|
26
|
+
// Shared socket round-trip used by get/post. `method` is the request
|
|
27
|
+
// method string ("GET" / "POST"); a leading 'P' selects POST semantics
|
|
28
|
+
// (sends `body` and the Content-* headers). Sets self->status and returns
|
|
29
|
+
// the response body (empty string on failure).
|
|
30
|
+
func exchange = (ref self, string method, string url, string body, out string) {
|
|
31
|
+
```
|
|
32
|
+
#arch: c
|
|
33
|
+
#scope: file
|
|
34
|
+
#include <sys/socket.h>
|
|
35
|
+
#include <netdb.h>
|
|
36
|
+
#include <unistd.h>
|
|
37
|
+
#include <string.h>
|
|
38
|
+
#include <stdlib.h>
|
|
39
|
+
```
|
|
40
|
+
```
|
|
41
|
+
#arch: c
|
|
42
|
+
const char *scheme = strstr(url, "://");
|
|
43
|
+
const char *hp = scheme ? scheme + 3 : url;
|
|
44
|
+
const char *colon = strchr(hp, ':');
|
|
45
|
+
const char *slash = strchr(hp, '/');
|
|
46
|
+
char host[256];
|
|
47
|
+
int port = 80;
|
|
48
|
+
const char *path = "/";
|
|
49
|
+
|
|
50
|
+
if (colon && (!slash || colon < slash)) {
|
|
51
|
+
int hlen = (int)(colon - hp);
|
|
52
|
+
if (hlen > 255) hlen = 255;
|
|
53
|
+
memcpy(host, hp, hlen);
|
|
54
|
+
host[hlen] = 0;
|
|
55
|
+
port = atoi(colon + 1);
|
|
56
|
+
} else {
|
|
57
|
+
const char *end = slash ? slash : hp + strlen(hp);
|
|
58
|
+
int hlen = (int)(end - hp);
|
|
59
|
+
if (hlen > 255) hlen = 255;
|
|
60
|
+
memcpy(host, hp, hlen);
|
|
61
|
+
host[hlen] = 0;
|
|
62
|
+
}
|
|
63
|
+
if (slash) path = slash;
|
|
64
|
+
|
|
65
|
+
struct addrinfo hints, *res;
|
|
66
|
+
memset(&hints, 0, sizeof(hints));
|
|
67
|
+
hints.ai_family = AF_INET;
|
|
68
|
+
hints.ai_socktype = SOCK_STREAM;
|
|
69
|
+
char portstr[16];
|
|
70
|
+
snprintf(portstr, sizeof(portstr), "%d", port);
|
|
71
|
+
if (getaddrinfo(host, portstr, &hints, &res) != 0) {
|
|
72
|
+
self->status = 0;
|
|
73
|
+
return strdup("");
|
|
74
|
+
}
|
|
75
|
+
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
76
|
+
if (sock < 0) {
|
|
77
|
+
freeaddrinfo(res);
|
|
78
|
+
self->status = 0;
|
|
79
|
+
return strdup("");
|
|
80
|
+
}
|
|
81
|
+
if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
|
|
82
|
+
freeaddrinfo(res);
|
|
83
|
+
close(sock);
|
|
84
|
+
self->status = 0;
|
|
85
|
+
return strdup("");
|
|
86
|
+
}
|
|
87
|
+
freeaddrinfo(res);
|
|
88
|
+
|
|
89
|
+
char req[1600];
|
|
90
|
+
int off = snprintf(req, sizeof(req),
|
|
91
|
+
"%s %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n",
|
|
92
|
+
method, path, host);
|
|
93
|
+
if (method[0] == 'P') {
|
|
94
|
+
int blen = (int)strlen(body);
|
|
95
|
+
off += snprintf(req + off, sizeof(req) - off,
|
|
96
|
+
"Content-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n",
|
|
97
|
+
blen);
|
|
98
|
+
send(sock, req, off, 0);
|
|
99
|
+
send(sock, body, blen, 0);
|
|
100
|
+
} else {
|
|
101
|
+
off += snprintf(req + off, sizeof(req) - off, "\r\n");
|
|
102
|
+
send(sock, req, off, 0);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
int cap = 4096, len = 0;
|
|
106
|
+
char *buf = (char*)malloc(cap);
|
|
107
|
+
int n;
|
|
108
|
+
while ((n = recv(sock, buf + len, cap - len - 1, 0)) > 0) {
|
|
109
|
+
len += n;
|
|
110
|
+
if (len + 1 >= cap) {
|
|
111
|
+
cap *= 2;
|
|
112
|
+
buf = (char*)realloc(buf, cap);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
buf[len] = 0;
|
|
116
|
+
close(sock);
|
|
117
|
+
|
|
118
|
+
int code = 0;
|
|
119
|
+
if (len >= 12 && strncmp(buf, "HTTP/", 5) == 0) {
|
|
120
|
+
code = atoi(buf + 9);
|
|
121
|
+
}
|
|
122
|
+
self->status = code;
|
|
123
|
+
|
|
124
|
+
char *body_start = strstr(buf, "\r\n\r\n");
|
|
125
|
+
if (body_start) {
|
|
126
|
+
char *result = strdup(body_start + 4);
|
|
127
|
+
free(buf);
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
return buf;
|
|
131
|
+
```
|
|
132
|
+
```
|
|
133
|
+
#arch: aarch64
|
|
134
|
+
// x0=self(->x19), x1=method, x2=url, x3=body
|
|
135
|
+
// macOS arm64 passes variadic args on the caller stack at [sp+0..], so
|
|
136
|
+
// [sp+0..47] is reserved scratch for snprintf variadic args and the
|
|
137
|
+
// addrinfo hints live above it. Stack frame (2048 bytes):
|
|
138
|
+
// #0 variadic scratch (snprintf args)
|
|
139
|
+
// #48 hints (struct addrinfo, 48 bytes)
|
|
140
|
+
// #96 res* #104 sock fd
|
|
141
|
+
// #112 port #120 hp (host start)
|
|
142
|
+
// #128 method #136 url
|
|
143
|
+
// #144 body #152 path
|
|
144
|
+
// #160 colon/blen/buf #168 slash/cap
|
|
145
|
+
// #176 hostlen/req_off #184 portstr (16)
|
|
146
|
+
// #208 host buffer (256) #464 request buffer (1584)
|
|
147
|
+
sub sp, sp, #2048
|
|
148
|
+
str x1, [sp, #128]
|
|
149
|
+
str x2, [sp, #136]
|
|
150
|
+
str x3, [sp, #144]
|
|
151
|
+
mov x0, #80
|
|
152
|
+
str x0, [sp, #112]
|
|
153
|
+
adr x0, .Lhttp_slash
|
|
154
|
+
str x0, [sp, #152]
|
|
155
|
+
|
|
156
|
+
// hp = (strstr(url, "://") ?: url) + 3 when scheme present
|
|
157
|
+
ldr x0, [sp, #136]
|
|
158
|
+
adr x1, .Lhttp_scheme
|
|
159
|
+
bl _strstr
|
|
160
|
+
cbz x0, .Lhttp_sethp
|
|
161
|
+
add x0, x0, #3
|
|
162
|
+
.Lhttp_sethp:
|
|
163
|
+
str x0, [sp, #120]
|
|
164
|
+
|
|
165
|
+
// colon = strchr(hp, ':'); slash = strchr(hp, '/')
|
|
166
|
+
ldr x0, [sp, #120]
|
|
167
|
+
mov x1, #0x3A
|
|
168
|
+
bl _strchr
|
|
169
|
+
str x0, [sp, #160]
|
|
170
|
+
ldr x0, [sp, #120]
|
|
171
|
+
mov x1, #0x2F
|
|
172
|
+
bl _strchr
|
|
173
|
+
str x0, [sp, #168]
|
|
174
|
+
|
|
175
|
+
// if (colon && (!slash || colon < slash)) -> port branch
|
|
176
|
+
ldr x0, [sp, #160]
|
|
177
|
+
cbz x0, .Lhttp_np
|
|
178
|
+
ldr x1, [sp, #168]
|
|
179
|
+
cbz x1, .Lhttp_port
|
|
180
|
+
cmp x0, x1
|
|
181
|
+
b.lo .Lhttp_port
|
|
182
|
+
.Lhttp_np:
|
|
183
|
+
// hostlen = slash ? (slash - hp) : strlen(hp); path = slash
|
|
184
|
+
ldr x0, [sp, #168]
|
|
185
|
+
cbz x0, .Lhttp_np_strlen
|
|
186
|
+
ldr x1, [sp, #120]
|
|
187
|
+
sub x0, x0, x1
|
|
188
|
+
str x0, [sp, #176]
|
|
189
|
+
ldr x0, [sp, #168]
|
|
190
|
+
str x0, [sp, #152]
|
|
191
|
+
b .Lhttp_cph
|
|
192
|
+
.Lhttp_np_strlen:
|
|
193
|
+
ldr x0, [sp, #120]
|
|
194
|
+
bl _strlen
|
|
195
|
+
str x0, [sp, #176]
|
|
196
|
+
b .Lhttp_cph
|
|
197
|
+
.Lhttp_port:
|
|
198
|
+
// hostlen = colon - hp; port = atoi(colon + 1)
|
|
199
|
+
ldr x0, [sp, #120]
|
|
200
|
+
ldr x1, [sp, #160]
|
|
201
|
+
sub x0, x1, x0
|
|
202
|
+
str x0, [sp, #176]
|
|
203
|
+
ldr x0, [sp, #160]
|
|
204
|
+
add x0, x0, #1
|
|
205
|
+
bl _atoi
|
|
206
|
+
str x0, [sp, #112]
|
|
207
|
+
ldr x0, [sp, #168]
|
|
208
|
+
cbz x0, .Lhttp_cph
|
|
209
|
+
str x0, [sp, #152]
|
|
210
|
+
|
|
211
|
+
// hostlen = min(hostlen, 255); memcpy(hostbuf, hp, hostlen); hostbuf[hostlen]=0
|
|
212
|
+
.Lhttp_cph:
|
|
213
|
+
ldr x0, [sp, #176]
|
|
214
|
+
mov x9, #255
|
|
215
|
+
cmp x0, x9
|
|
216
|
+
csel x0, x0, x9, ls
|
|
217
|
+
str x0, [sp, #176]
|
|
218
|
+
add x0, sp, #208
|
|
219
|
+
ldr x1, [sp, #120]
|
|
220
|
+
ldr x2, [sp, #176]
|
|
221
|
+
bl _memcpy
|
|
222
|
+
add x0, sp, #208
|
|
223
|
+
ldr x1, [sp, #176]
|
|
224
|
+
strb wzr, [x0, x1]
|
|
225
|
+
|
|
226
|
+
// memset(&hints, 0, 48); hints.ai_family=AF_INET(2); hints.ai_socktype=SOCK_STREAM(1)
|
|
227
|
+
add x0, sp, #48
|
|
228
|
+
mov x1, xzr
|
|
229
|
+
mov x2, #48
|
|
230
|
+
bl _memset
|
|
231
|
+
mov w0, #2
|
|
232
|
+
str w0, [sp, #52]
|
|
233
|
+
mov w0, #1
|
|
234
|
+
str w0, [sp, #56]
|
|
235
|
+
// snprintf(portstr, 16, "%ld", port) — variadic arg on stack at [sp+0]
|
|
236
|
+
ldr x9, [sp, #112]
|
|
237
|
+
str x9, [sp, #0]
|
|
238
|
+
add x0, sp, #184
|
|
239
|
+
mov x1, #16
|
|
240
|
+
adr x2, .Lhttp_fmt_ld
|
|
241
|
+
bl _snprintf
|
|
242
|
+
// getaddrinfo(host, portstr, &hints, &res)
|
|
243
|
+
add x0, sp, #208
|
|
244
|
+
add x1, sp, #184
|
|
245
|
+
add x2, sp, #48
|
|
246
|
+
add x3, sp, #96
|
|
247
|
+
bl _getaddrinfo
|
|
248
|
+
cbnz w0, .Lhttp_fail
|
|
249
|
+
|
|
250
|
+
// sock = socket(AF_INET, SOCK_STREAM, 0)
|
|
251
|
+
mov x0, #2
|
|
252
|
+
mov x1, #1
|
|
253
|
+
mov x2, xzr
|
|
254
|
+
bl _socket
|
|
255
|
+
cmp w0, #0
|
|
256
|
+
b.ge .Lhttp_sockok
|
|
257
|
+
ldr x0, [sp, #96]
|
|
258
|
+
bl _freeaddrinfo
|
|
259
|
+
b .Lhttp_fail
|
|
260
|
+
.Lhttp_sockok:
|
|
261
|
+
str w0, [sp, #104]
|
|
262
|
+
// connect(sock, res->ai_addr (off 32), res->ai_addrlen (off 16))
|
|
263
|
+
ldr x9, [sp, #96]
|
|
264
|
+
ldr x1, [x9, #32]
|
|
265
|
+
ldr w2, [x9, #16]
|
|
266
|
+
ldr w0, [sp, #104]
|
|
267
|
+
bl _connect
|
|
268
|
+
cmp w0, #0
|
|
269
|
+
b.ge .Lhttp_connected
|
|
270
|
+
ldr x0, [sp, #96]
|
|
271
|
+
bl _freeaddrinfo
|
|
272
|
+
ldr w0, [sp, #104]
|
|
273
|
+
bl _close
|
|
274
|
+
b .Lhttp_fail
|
|
275
|
+
.Lhttp_connected:
|
|
276
|
+
ldr x0, [sp, #96]
|
|
277
|
+
bl _freeaddrinfo
|
|
278
|
+
|
|
279
|
+
// off = snprintf(req, 1584, common_fmt, method, path, host)
|
|
280
|
+
// variadic args on stack: method@[0], path@[8], host@[16]
|
|
281
|
+
ldr x9, [sp, #128]
|
|
282
|
+
str x9, [sp, #0]
|
|
283
|
+
ldr x9, [sp, #152]
|
|
284
|
+
str x9, [sp, #8]
|
|
285
|
+
add x9, sp, #208
|
|
286
|
+
str x9, [sp, #16]
|
|
287
|
+
add x0, sp, #464
|
|
288
|
+
mov x1, #1584
|
|
289
|
+
adr x2, .Lhttp_reqcommon
|
|
290
|
+
bl _snprintf
|
|
291
|
+
sxtw x0, w0
|
|
292
|
+
str x0, [sp, #176]
|
|
293
|
+
|
|
294
|
+
// if method[0] == 'P' (0x50) -> POST
|
|
295
|
+
ldr x0, [sp, #128]
|
|
296
|
+
ldrb w0, [x0]
|
|
297
|
+
cmp w0, #0x50
|
|
298
|
+
b.ne .Lhttp_getsend
|
|
299
|
+
|
|
300
|
+
// POST: blen = strlen(body); append Content-Length; send headers; send body
|
|
301
|
+
ldr x0, [sp, #144]
|
|
302
|
+
bl _strlen
|
|
303
|
+
str x0, [sp, #160]
|
|
304
|
+
// snprintf(req+off, 1584-off, reqpost, blen) — blen on stack at [sp+0]
|
|
305
|
+
ldr x9, [sp, #160]
|
|
306
|
+
str x9, [sp, #0]
|
|
307
|
+
add x0, sp, #464
|
|
308
|
+
ldr x1, [sp, #176]
|
|
309
|
+
add x0, x0, x1
|
|
310
|
+
mov x1, #1584
|
|
311
|
+
ldr x2, [sp, #176]
|
|
312
|
+
sub x1, x1, x2
|
|
313
|
+
adr x2, .Lhttp_reqpost
|
|
314
|
+
bl _snprintf
|
|
315
|
+
sxtw x0, w0
|
|
316
|
+
ldr x1, [sp, #176]
|
|
317
|
+
add x1, x1, x0
|
|
318
|
+
str x1, [sp, #176]
|
|
319
|
+
ldr w0, [sp, #104]
|
|
320
|
+
add x1, sp, #464
|
|
321
|
+
ldr x2, [sp, #176]
|
|
322
|
+
mov x3, xzr
|
|
323
|
+
bl _send
|
|
324
|
+
ldr x0, [sp, #144]
|
|
325
|
+
bl _strlen
|
|
326
|
+
mov x2, x0
|
|
327
|
+
ldr w0, [sp, #104]
|
|
328
|
+
ldr x1, [sp, #144]
|
|
329
|
+
mov x3, xzr
|
|
330
|
+
bl _send
|
|
331
|
+
b .Lhttp_recv
|
|
332
|
+
|
|
333
|
+
.Lhttp_getsend:
|
|
334
|
+
// GET: append trailing "\r\n" (no variadic) and send
|
|
335
|
+
add x0, sp, #464
|
|
336
|
+
ldr x1, [sp, #176]
|
|
337
|
+
add x0, x0, x1
|
|
338
|
+
mov x1, #1584
|
|
339
|
+
ldr x2, [sp, #176]
|
|
340
|
+
sub x1, x1, x2
|
|
341
|
+
adr x2, .Lhttp_crlf
|
|
342
|
+
bl _snprintf
|
|
343
|
+
sxtw x0, w0
|
|
344
|
+
ldr x1, [sp, #176]
|
|
345
|
+
add x1, x1, x0
|
|
346
|
+
str x1, [sp, #176]
|
|
347
|
+
ldr w0, [sp, #104]
|
|
348
|
+
add x1, sp, #464
|
|
349
|
+
ldr x2, [sp, #176]
|
|
350
|
+
mov x3, xzr
|
|
351
|
+
bl _send
|
|
352
|
+
|
|
353
|
+
// recv loop: buf = malloc(4096); grow as needed
|
|
354
|
+
.Lhttp_recv:
|
|
355
|
+
mov x0, #4096
|
|
356
|
+
bl _malloc
|
|
357
|
+
str x0, [sp, #160]
|
|
358
|
+
mov x0, #4096
|
|
359
|
+
str x0, [sp, #168]
|
|
360
|
+
str xzr, [sp, #96]
|
|
361
|
+
.Lhttp_recvloop:
|
|
362
|
+
ldr w0, [sp, #104]
|
|
363
|
+
ldr x1, [sp, #160]
|
|
364
|
+
ldr x2, [sp, #96]
|
|
365
|
+
add x1, x1, x2
|
|
366
|
+
ldr x2, [sp, #168]
|
|
367
|
+
ldr x3, [sp, #96]
|
|
368
|
+
sub x2, x2, x3
|
|
369
|
+
sub x2, x2, #1
|
|
370
|
+
mov x3, xzr
|
|
371
|
+
bl _recv
|
|
372
|
+
cmp x0, #0
|
|
373
|
+
ble .Lhttp_recvdone
|
|
374
|
+
ldr x1, [sp, #96]
|
|
375
|
+
add x1, x1, x0
|
|
376
|
+
str x1, [sp, #96]
|
|
377
|
+
add x2, x1, #1
|
|
378
|
+
ldr x3, [sp, #168]
|
|
379
|
+
cmp x2, x3
|
|
380
|
+
blt .Lhttp_recvloop
|
|
381
|
+
ldr x0, [sp, #168]
|
|
382
|
+
lsl x0, x0, #1
|
|
383
|
+
str x0, [sp, #168]
|
|
384
|
+
mov x1, x0
|
|
385
|
+
ldr x0, [sp, #160]
|
|
386
|
+
bl _realloc
|
|
387
|
+
str x0, [sp, #160]
|
|
388
|
+
b .Lhttp_recvloop
|
|
389
|
+
|
|
390
|
+
.Lhttp_recvdone:
|
|
391
|
+
// buf[len] = 0; close(sock)
|
|
392
|
+
ldr x0, [sp, #160]
|
|
393
|
+
ldr x1, [sp, #96]
|
|
394
|
+
strb wzr, [x0, x1]
|
|
395
|
+
ldr w0, [sp, #104]
|
|
396
|
+
bl _close
|
|
397
|
+
// self->status = atoi(buf + 9)
|
|
398
|
+
ldr x0, [sp, #160]
|
|
399
|
+
add x0, x0, #9
|
|
400
|
+
bl _atoi
|
|
401
|
+
sxtw x0, w0
|
|
402
|
+
str x0, [x19, #8]
|
|
403
|
+
// body_start = strstr(buf, "\r\n\r\n")
|
|
404
|
+
ldr x0, [sp, #160]
|
|
405
|
+
adr x1, .Lhttp_hdrsep
|
|
406
|
+
bl _strstr
|
|
407
|
+
cbz x0, .Lhttp_retbuf
|
|
408
|
+
// result = strdup(body_start + 4); free(buf); return result
|
|
409
|
+
add x0, x0, #4
|
|
410
|
+
bl _strdup
|
|
411
|
+
str x0, [sp, #112]
|
|
412
|
+
ldr x0, [sp, #160]
|
|
413
|
+
bl _free
|
|
414
|
+
ldr x0, [sp, #112]
|
|
415
|
+
add sp, sp, #2048
|
|
416
|
+
b .return_Http_exchange
|
|
417
|
+
.Lhttp_retbuf:
|
|
418
|
+
ldr x0, [sp, #160]
|
|
419
|
+
add sp, sp, #2048
|
|
420
|
+
b .return_Http_exchange
|
|
421
|
+
.Lhttp_fail:
|
|
422
|
+
str xzr, [x19, #8]
|
|
423
|
+
adr x0, .Lhttp_empty
|
|
424
|
+
bl _strdup
|
|
425
|
+
add sp, sp, #2048
|
|
426
|
+
b .return_Http_exchange
|
|
427
|
+
|
|
428
|
+
.Lhttp_scheme: .asciz "://"
|
|
429
|
+
.Lhttp_slash: .asciz "/"
|
|
430
|
+
.Lhttp_fmt_ld: .asciz "%ld"
|
|
431
|
+
.Lhttp_crlf: .asciz "\r\n"
|
|
432
|
+
.Lhttp_hdrsep: .asciz "\r\n\r\n"
|
|
433
|
+
.Lhttp_empty: .asciz ""
|
|
434
|
+
.Lhttp_reqcommon: .asciz "%s %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n"
|
|
435
|
+
.Lhttp_reqpost: .asciz "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: %ld\r\n\r\n"
|
|
436
|
+
.p2align 2
|
|
437
|
+
```
|
|
438
|
+
return ""
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Issue a blocking GET request to `url`. Returns the response body and
|
|
442
|
+
// sets `self.status` to the response's status code (0 on failure).
|
|
443
|
+
pub func get = (ref self, string url, out string) {
|
|
444
|
+
return self.exchange("GET", url, "")
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Issue a blocking POST request to `url` with `body` as the payload.
|
|
448
|
+
// Returns the response body and sets `self.status` to the response's
|
|
449
|
+
// status code (0 on failure).
|
|
450
|
+
pub func post = (ref self, string url, string body, out string) {
|
|
451
|
+
return self.exchange("POST", url, body)
|
|
452
|
+
}
|
|
453
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A UTF-8 text string — a heap-owned, length-tracked sequence of bytes
|
|
3
|
+
**/
|
|
4
|
+
pub struct string: Stringable {
|
|
5
|
+
pub func to_string = (self, out string) {
|
|
6
|
+
```
|
|
7
|
+
#arch: c
|
|
8
|
+
return strdup(self);
|
|
9
|
+
```
|
|
10
|
+
```
|
|
11
|
+
#arch: aarch64
|
|
12
|
+
mov x0, x19
|
|
13
|
+
```
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
pub func at = (self, int index: index >= 0 && index < self.length, out char) {
|
|
17
|
+
```
|
|
18
|
+
#arch: c
|
|
19
|
+
return self[index];
|
|
20
|
+
```
|
|
21
|
+
```
|
|
22
|
+
#arch: aarch64
|
|
23
|
+
// x19 = self (pointer), x1 = index
|
|
24
|
+
ldrb w0, [x19, x1]
|
|
25
|
+
```
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// A non-owning slice [start, end) into self's buffer. Returns a `view
|
|
29
|
+
// string` (ptr, len) that borrows from self: it may not outlive self's
|
|
30
|
+
// scope and is invalidated if self is reassigned. Use .to_string() to
|
|
31
|
+
// materialize an owned copy.
|
|
32
|
+
pub func slice = (
|
|
33
|
+
self,
|
|
34
|
+
int start: start >= 0 && start <= self.length,
|
|
35
|
+
int end: end >= start && end <= self.length,
|
|
36
|
+
out view string
|
|
37
|
+
) {
|
|
38
|
+
```
|
|
39
|
+
#arch: c
|
|
40
|
+
nomen_view _r;
|
|
41
|
+
_r.ptr = (void*)(self + start);
|
|
42
|
+
_r.len = (long)(end - start);
|
|
43
|
+
return _r;
|
|
44
|
+
```
|
|
45
|
+
```
|
|
46
|
+
#arch: aarch64
|
|
47
|
+
// view string is (ptr, len), returned in the x0/x1 register pair.
|
|
48
|
+
// x19 = self (char*), x1 = start, x2 = end (retained through prologue).
|
|
49
|
+
add x0, x19, x1 // ptr = self + start
|
|
50
|
+
sub x1, x2, x1 // len = end - start
|
|
51
|
+
```
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
pub func set = (ref self, int index: index >= 0 && index < self.length, char value) {
|
|
55
|
+
```
|
|
56
|
+
#arch: c
|
|
57
|
+
(*self)[index] = value;
|
|
58
|
+
```
|
|
59
|
+
```
|
|
60
|
+
#arch: aarch64
|
|
61
|
+
// x19 = self (pointer), x1 = index, w2 = value
|
|
62
|
+
strb w2, [x19, x1]
|
|
63
|
+
```
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
pub func #op_eq = (self, string other, out bool) {
|
|
67
|
+
```
|
|
68
|
+
#arch: c
|
|
69
|
+
return strcmp(self, other) == 0;
|
|
70
|
+
```
|
|
71
|
+
```
|
|
72
|
+
#arch: aarch64
|
|
73
|
+
// x0 = self, x1 = other on entry
|
|
74
|
+
bl _strcmp
|
|
75
|
+
cmp x0, #0
|
|
76
|
+
cset x0, eq
|
|
77
|
+
```
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
pub func #op_add = (self, string other, out string) {
|
|
81
|
+
```
|
|
82
|
+
#arch: c
|
|
83
|
+
int left_len = strlen(self);
|
|
84
|
+
int right_len = strlen(other);
|
|
85
|
+
char* result = malloc(left_len + right_len + 1);
|
|
86
|
+
strcpy(result, self);
|
|
87
|
+
strcat(result, other);
|
|
88
|
+
return result;
|
|
89
|
+
```
|
|
90
|
+
```
|
|
91
|
+
#arch: aarch64
|
|
92
|
+
stp x20, x21, [sp, #-16]!
|
|
93
|
+
mov x20, x1
|
|
94
|
+
bl _strlen
|
|
95
|
+
mov x21, x0
|
|
96
|
+
mov x0, x20
|
|
97
|
+
bl _strlen
|
|
98
|
+
add x0, x21, x0
|
|
99
|
+
add x0, x0, #1
|
|
100
|
+
bl _malloc
|
|
101
|
+
mov x21, x0
|
|
102
|
+
mov x1, x19
|
|
103
|
+
bl _strcpy
|
|
104
|
+
mov x0, x21
|
|
105
|
+
mov x1, x20
|
|
106
|
+
bl _strcat
|
|
107
|
+
mov x0, x21
|
|
108
|
+
ldp x20, x21, [sp], #16
|
|
109
|
+
```
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
pub func #op_mul = (self, int count, out string) {
|
|
113
|
+
```
|
|
114
|
+
#arch: c
|
|
115
|
+
size_t str_len = strlen(self);
|
|
116
|
+
size_t total = str_len * (size_t)count + 1;
|
|
117
|
+
char* buf = malloc(total);
|
|
118
|
+
char* p = buf;
|
|
119
|
+
for (int i = 0; i < count; i++) {
|
|
120
|
+
memcpy(p, self, str_len);
|
|
121
|
+
p += str_len;
|
|
122
|
+
}
|
|
123
|
+
*p = 0;
|
|
124
|
+
return buf;
|
|
125
|
+
```
|
|
126
|
+
```
|
|
127
|
+
#arch: aarch64
|
|
128
|
+
stp x20, x21, [sp, #-16]!
|
|
129
|
+
stp x22, xzr, [sp, #-16]!
|
|
130
|
+
mov x20, x1
|
|
131
|
+
bl _strlen
|
|
132
|
+
mov x21, x0
|
|
133
|
+
mul x0, x0, x20
|
|
134
|
+
add x0, x0, #1
|
|
135
|
+
bl _malloc
|
|
136
|
+
str x0, [x29, #8]
|
|
137
|
+
mov x22, x0
|
|
138
|
+
.Lmul_loop:
|
|
139
|
+
cbz x20, .Lmul_done
|
|
140
|
+
mov x0, x22
|
|
141
|
+
mov x1, x19
|
|
142
|
+
mov x2, x21
|
|
143
|
+
bl _memcpy
|
|
144
|
+
add x22, x22, x21
|
|
145
|
+
sub x20, x20, #1
|
|
146
|
+
b .Lmul_loop
|
|
147
|
+
.Lmul_done:
|
|
148
|
+
strb wzr, [x22]
|
|
149
|
+
ldr x0, [x29, #8]
|
|
150
|
+
ldp x22, xzr, [sp], #16
|
|
151
|
+
ldp x20, x21, [sp], #16
|
|
152
|
+
```
|
|
153
|
+
}
|
|
154
|
+
}
|