2021-08-08 04:24:46 +00:00
|
|
|
type channel {
|
|
|
|
name: (handle array byte)
|
|
|
|
posts: (handle array int) # item indices
|
2021-08-13 15:27:50 +00:00
|
|
|
posts-first-free: int
|
2021-08-08 04:24:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type user {
|
|
|
|
id: (handle array byte)
|
|
|
|
name: (handle array byte)
|
|
|
|
real-name: (handle array byte)
|
2021-08-11 05:46:51 +00:00
|
|
|
avatar: (handle image)
|
2021-08-08 04:24:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type item {
|
|
|
|
id: (handle array byte)
|
|
|
|
channel: (handle array byte)
|
|
|
|
by: int # user index
|
|
|
|
text: (handle array byte)
|
|
|
|
parent: int # item index
|
2021-08-10 12:26:10 +00:00
|
|
|
comments: (handle array int)
|
2021-08-13 15:27:50 +00:00
|
|
|
comments-first-free: int
|
2021-08-08 04:24:46 +00:00
|
|
|
}
|
|
|
|
|
2021-08-12 00:17:41 +00:00
|
|
|
type item-list {
|
|
|
|
data: (handle array item)
|
2021-08-13 15:27:50 +00:00
|
|
|
data-first-free: int
|
2021-08-12 00:17:41 +00:00
|
|
|
}
|
|
|
|
|
2021-08-08 04:24:46 +00:00
|
|
|
# globals:
|
|
|
|
# users: (handle array user)
|
|
|
|
# channels: (handle array channel)
|
|
|
|
# items: (handle array item)
|
|
|
|
#
|
|
|
|
# flows:
|
|
|
|
# channel -> posts
|
2021-08-10 12:26:10 +00:00
|
|
|
# user -> posts|comments
|
2021-08-08 04:24:46 +00:00
|
|
|
# post -> comments
|
2021-08-10 12:26:10 +00:00
|
|
|
# comment -> post|comments
|
2021-08-08 04:24:46 +00:00
|
|
|
# keywords -> posts|comments
|
|
|
|
|
2021-08-11 03:52:18 +00:00
|
|
|
# static buffer sizes in this program:
|
|
|
|
# data-size
|
|
|
|
# data-size-in-sectors
|
|
|
|
# num-channels
|
|
|
|
# num-users
|
|
|
|
# num-items
|
2021-08-11 04:05:02 +00:00
|
|
|
# num-comments
|
|
|
|
# message-text-limit
|
|
|
|
# channel-capacity
|
2021-08-11 03:52:18 +00:00
|
|
|
|
2021-08-08 04:24:46 +00:00
|
|
|
fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
|
|
|
|
# load entire disk contents to a single enormous stream
|
|
|
|
var s-h: (handle stream byte) # the stream is too large to put on the stack
|
|
|
|
var s-ah/eax: (addr handle stream byte) <- address s-h
|
2021-08-11 03:52:18 +00:00
|
|
|
populate-stream s-ah, 0x4000000/data-size
|
2021-08-08 04:24:46 +00:00
|
|
|
var _s/eax: (addr stream byte) <- lookup *s-ah
|
|
|
|
var s/ebx: (addr stream byte) <- copy _s
|
2021-08-11 17:29:34 +00:00
|
|
|
var sector-count/eax: int <- copy 0x400 # test_data
|
|
|
|
#? var sector-count/eax: int <- copy 0x20000 # largest size tested; slow
|
2021-08-13 13:25:02 +00:00
|
|
|
set-cursor-position 0/screen, 0x20/x 0/y # aborts clobber the screen starting x=0
|
2021-08-11 17:29:34 +00:00
|
|
|
draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "loading ", 3/fg 0/bg
|
|
|
|
draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, sector-count, 3/fg 0/bg
|
|
|
|
draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " sectors from data disk..", 3/fg 0/bg
|
|
|
|
load-sectors data-disk, 0/lba, sector-count, s
|
2021-08-08 04:24:46 +00:00
|
|
|
draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "done", 3/fg 0/bg
|
|
|
|
# parse global data structures out of the stream
|
|
|
|
var users-h: (handle array user)
|
|
|
|
var users-ah/eax: (addr handle array user) <- address users-h
|
2021-08-11 03:52:18 +00:00
|
|
|
populate users-ah, 0x800/num-users
|
2021-08-08 04:24:46 +00:00
|
|
|
var _users/eax: (addr array user) <- lookup *users-ah
|
|
|
|
var users/edi: (addr array user) <- copy _users
|
|
|
|
var channels-h: (handle array channel)
|
|
|
|
var channels-ah/eax: (addr handle array channel) <- address channels-h
|
2021-08-11 03:52:18 +00:00
|
|
|
populate channels-ah, 0x20/num-channels
|
2021-08-08 04:24:46 +00:00
|
|
|
var _channels/eax: (addr array channel) <- lookup *channels-ah
|
|
|
|
var channels/esi: (addr array channel) <- copy _channels
|
2021-08-12 00:17:41 +00:00
|
|
|
var items-storage: item-list
|
|
|
|
var items/edx: (addr item-list) <- address items-storage
|
|
|
|
var items-data-ah/eax: (addr handle array item) <- get items, data
|
|
|
|
populate items-data-ah, 0x10000/num-items
|
2021-08-08 04:24:46 +00:00
|
|
|
parse s, users, channels, items
|
2022-01-18 04:30:09 +00:00
|
|
|
# event loop
|
2021-08-08 04:24:46 +00:00
|
|
|
var env-storage: environment
|
|
|
|
var env/ebx: (addr environment) <- address env-storage
|
2021-08-12 01:08:08 +00:00
|
|
|
initialize-environment env, items
|
2022-01-18 04:30:09 +00:00
|
|
|
#? # uncomment this for a hacky feature: browse thread for a specific url
|
|
|
|
#? new-thread-tab-from-url env, "https://futureofcoding.slack.com/archives/C5T9GPWFL/p1599719973216100", users, channels, items
|
2021-08-08 04:24:46 +00:00
|
|
|
{
|
2021-08-11 05:17:05 +00:00
|
|
|
render-environment screen, env, users, channels, items
|
2021-08-08 04:24:46 +00:00
|
|
|
{
|
|
|
|
var key/eax: byte <- read-key keyboard
|
|
|
|
compare key, 0
|
|
|
|
loop-if-=
|
2021-08-13 21:19:01 +00:00
|
|
|
update-environment env, key, users, channels, items
|
2021-08-08 04:24:46 +00:00
|
|
|
}
|
|
|
|
loop
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-12 00:17:41 +00:00
|
|
|
fn parse in: (addr stream byte), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
|
|
|
|
var items/esi: (addr item-list) <- copy _items
|
|
|
|
var items-data-ah/eax: (addr handle array item) <- get items, data
|
|
|
|
var _items-data/eax: (addr array item) <- lookup *items-data-ah
|
|
|
|
var items-data/edi: (addr array item) <- copy _items-data
|
2021-08-10 12:26:10 +00:00
|
|
|
# 'in' consists of a long, flat sequence of records surrounded by parens
|
|
|
|
var record-storage: (stream byte 0x18000)
|
|
|
|
var record/ecx: (addr stream byte) <- address record-storage
|
|
|
|
var user-idx/edx: int <- copy 0
|
|
|
|
var item-idx/ebx: int <- copy 0
|
|
|
|
{
|
|
|
|
var done?/eax: boolean <- stream-empty? in
|
|
|
|
compare done?, 0/false
|
|
|
|
break-if-!=
|
2021-08-10 13:29:11 +00:00
|
|
|
var c/eax: byte <- peek-byte in
|
|
|
|
compare c, 0
|
|
|
|
break-if-=
|
2021-08-13 13:25:02 +00:00
|
|
|
set-cursor-position 0/screen, 0x20/x 1/y
|
|
|
|
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "parsed " 3/fg 0/bg
|
2021-08-10 12:52:48 +00:00
|
|
|
draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, user-idx, 3/fg 0/bg
|
2021-08-13 13:25:02 +00:00
|
|
|
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " users, " 3/fg 0/bg
|
|
|
|
draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, item-idx, 3/fg 0/bg
|
|
|
|
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " posts/comments" 3/fg 0/bg
|
2021-08-10 13:17:50 +00:00
|
|
|
clear-stream record
|
2021-08-10 12:26:10 +00:00
|
|
|
parse-record in, record
|
|
|
|
var user?/eax: boolean <- user-record? record
|
|
|
|
{
|
|
|
|
compare user?, 0/false
|
|
|
|
break-if-=
|
|
|
|
parse-user record, users, user-idx
|
|
|
|
user-idx <- increment
|
|
|
|
}
|
|
|
|
{
|
|
|
|
compare user?, 0/false
|
|
|
|
break-if-!=
|
2021-08-12 00:17:41 +00:00
|
|
|
parse-item record, channels, items-data, item-idx
|
2021-08-10 12:26:10 +00:00
|
|
|
item-idx <- increment
|
|
|
|
}
|
|
|
|
loop
|
|
|
|
}
|
2021-08-13 15:27:50 +00:00
|
|
|
var dest/eax: (addr int) <- get items, data-first-free
|
2021-08-12 00:17:41 +00:00
|
|
|
copy-to *dest, item-idx
|
2021-08-10 12:26:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn parse-record in: (addr stream byte), out: (addr stream byte) {
|
2021-08-10 12:52:48 +00:00
|
|
|
var paren/eax: byte <- read-byte in
|
|
|
|
compare paren, 0x28/open-paren
|
|
|
|
{
|
|
|
|
break-if-=
|
2021-08-10 13:29:11 +00:00
|
|
|
set-cursor-position 0/screen, 0x20 0x10
|
|
|
|
var c/eax: int <- copy paren
|
|
|
|
draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen c, 5/fg 0/bg
|
2021-08-10 12:52:48 +00:00
|
|
|
abort "parse-record: ("
|
|
|
|
}
|
|
|
|
var paren-int/eax: int <- copy paren
|
|
|
|
append-byte out, paren-int
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var eof?/eax: boolean <- stream-empty? in
|
|
|
|
compare eof?, 0/false
|
|
|
|
break-if-=
|
2021-08-12 01:36:57 +00:00
|
|
|
abort "parse-record: truncated; increase the sector-count to load from disk"
|
2021-08-10 12:52:48 +00:00
|
|
|
}
|
|
|
|
var c/eax: byte <- read-byte in
|
|
|
|
{
|
|
|
|
var c-int/eax: int <- copy c
|
|
|
|
append-byte out, c-int
|
|
|
|
}
|
|
|
|
compare c, 0x29/close-paren
|
|
|
|
break-if-=
|
|
|
|
compare c, 0x22/double-quote
|
|
|
|
{
|
|
|
|
break-if-!=
|
|
|
|
slurp-json-string in, out
|
|
|
|
}
|
|
|
|
loop
|
|
|
|
}
|
|
|
|
skip-chars-matching-whitespace in
|
2021-08-10 12:26:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn user-record? record: (addr stream byte) -> _/eax: boolean {
|
2021-08-10 12:52:48 +00:00
|
|
|
rewind-stream record
|
|
|
|
var c/eax: byte <- read-byte record # skip paren
|
|
|
|
var c/eax: byte <- read-byte record # skip double quote
|
|
|
|
var c/eax: byte <- read-byte record
|
|
|
|
compare c, 0x55/U
|
|
|
|
{
|
|
|
|
break-if-!=
|
|
|
|
return 1/true
|
|
|
|
}
|
|
|
|
rewind-stream record
|
2021-08-10 12:26:10 +00:00
|
|
|
return 0/false
|
|
|
|
}
|
|
|
|
|
2021-08-10 20:58:14 +00:00
|
|
|
fn parse-user record: (addr stream byte), _users: (addr array user), user-idx: int {
|
|
|
|
var users/esi: (addr array user) <- copy _users
|
|
|
|
var offset/eax: (offset user) <- compute-offset users, user-idx
|
|
|
|
var user/esi: (addr user) <- index users, offset
|
|
|
|
#
|
2021-08-11 05:44:49 +00:00
|
|
|
var s-storage: (stream byte 0x100)
|
2021-08-10 20:58:14 +00:00
|
|
|
var s/ecx: (addr stream byte) <- address s-storage
|
|
|
|
#
|
|
|
|
rewind-stream record
|
|
|
|
var paren/eax: byte <- read-byte record
|
|
|
|
compare paren, 0x28/open-paren
|
|
|
|
{
|
|
|
|
break-if-=
|
|
|
|
abort "parse-user: ("
|
|
|
|
}
|
|
|
|
# user id
|
|
|
|
skip-chars-matching-whitespace record
|
|
|
|
var double-quote/eax: byte <- read-byte record
|
|
|
|
compare double-quote, 0x22/double-quote
|
|
|
|
{
|
|
|
|
break-if-=
|
|
|
|
abort "parse-user: id"
|
|
|
|
}
|
|
|
|
next-json-string record, s
|
|
|
|
var dest/eax: (addr handle array byte) <- get user, id
|
|
|
|
stream-to-array s, dest
|
|
|
|
# user name
|
|
|
|
skip-chars-matching-whitespace record
|
|
|
|
var double-quote/eax: byte <- read-byte record
|
|
|
|
compare double-quote, 0x22/double-quote
|
|
|
|
{
|
|
|
|
break-if-=
|
|
|
|
abort "parse-user: name"
|
|
|
|
}
|
2021-08-11 03:50:16 +00:00
|
|
|
clear-stream s
|
2021-08-10 20:58:14 +00:00
|
|
|
next-json-string record, s
|
|
|
|
var dest/eax: (addr handle array byte) <- get user, name
|
|
|
|
stream-to-array s, dest
|
|
|
|
# real name
|
|
|
|
skip-chars-matching-whitespace record
|
|
|
|
var double-quote/eax: byte <- read-byte record
|
|
|
|
compare double-quote, 0x22/double-quote
|
|
|
|
{
|
|
|
|
break-if-=
|
|
|
|
abort "parse-user: real-name"
|
|
|
|
}
|
2021-08-11 03:50:16 +00:00
|
|
|
clear-stream s
|
2021-08-10 20:58:14 +00:00
|
|
|
next-json-string record, s
|
|
|
|
var dest/eax: (addr handle array byte) <- get user, real-name
|
|
|
|
stream-to-array s, dest
|
|
|
|
# avatar
|
|
|
|
skip-chars-matching-whitespace record
|
|
|
|
var open-bracket/eax: byte <- read-byte record
|
|
|
|
compare open-bracket, 0x5b/open-bracket
|
|
|
|
{
|
|
|
|
break-if-=
|
|
|
|
abort "parse-user: avatar"
|
|
|
|
}
|
|
|
|
skip-chars-matching-whitespace record
|
|
|
|
var c/eax: byte <- peek-byte record
|
|
|
|
{
|
|
|
|
compare c, 0x5d/close-bracket
|
|
|
|
break-if-=
|
2021-08-11 05:46:51 +00:00
|
|
|
var dest-ah/eax: (addr handle image) <- get user, avatar
|
|
|
|
allocate dest-ah
|
|
|
|
var dest/eax: (addr image) <- lookup *dest-ah
|
2021-08-10 20:58:14 +00:00
|
|
|
initialize-image dest, record
|
|
|
|
}
|
2021-08-10 12:26:10 +00:00
|
|
|
}
|
|
|
|
|
2021-08-11 04:05:02 +00:00
|
|
|
fn parse-item record: (addr stream byte), _channels: (addr array channel), _items: (addr array item), item-idx: int {
|
|
|
|
var items/esi: (addr array item) <- copy _items
|
|
|
|
var offset/eax: (offset item) <- compute-offset items, item-idx
|
|
|
|
var item/edi: (addr item) <- index items, offset
|
|
|
|
#
|
|
|
|
var s-storage: (stream byte 0x40)
|
|
|
|
var s/ecx: (addr stream byte) <- address s-storage
|
|
|
|
#
|
2021-08-10 20:58:14 +00:00
|
|
|
rewind-stream record
|
|
|
|
var paren/eax: byte <- read-byte record
|
|
|
|
compare paren, 0x28/open-paren
|
|
|
|
{
|
|
|
|
break-if-=
|
|
|
|
abort "parse-item: ("
|
|
|
|
}
|
2021-08-11 04:05:02 +00:00
|
|
|
# item id
|
|
|
|
skip-chars-matching-whitespace record
|
|
|
|
var double-quote/eax: byte <- read-byte record
|
|
|
|
compare double-quote, 0x22/double-quote
|
|
|
|
{
|
|
|
|
break-if-=
|
|
|
|
abort "parse-item: id"
|
|
|
|
}
|
|
|
|
next-json-string record, s
|
|
|
|
var dest/eax: (addr handle array byte) <- get item, id
|
|
|
|
stream-to-array s, dest
|
|
|
|
# parent index
|
|
|
|
{
|
|
|
|
var word-slice-storage: slice
|
|
|
|
var word-slice/ecx: (addr slice) <- address word-slice-storage
|
|
|
|
next-word record, word-slice
|
|
|
|
var src/eax: int <- parse-decimal-int-from-slice word-slice
|
|
|
|
compare src, -1
|
|
|
|
break-if-=
|
|
|
|
var dest/edx: (addr int) <- get item, parent
|
|
|
|
copy-to *dest, src
|
|
|
|
# cross-link to parent
|
|
|
|
var parent-offset/eax: (offset item) <- compute-offset items, src
|
|
|
|
var parent-item/esi: (addr item) <- index items, parent-offset
|
|
|
|
var parent-comments-ah/ebx: (addr handle array int) <- get parent-item, comments
|
|
|
|
var parent-comments/eax: (addr array int) <- lookup *parent-comments-ah
|
|
|
|
compare parent-comments, 0
|
|
|
|
{
|
|
|
|
break-if-!=
|
|
|
|
populate parent-comments-ah, 0x200/num-comments
|
|
|
|
parent-comments <- lookup *parent-comments-ah
|
|
|
|
}
|
2021-08-13 15:27:50 +00:00
|
|
|
var parent-comments-first-free-addr/edi: (addr int) <- get parent-item, comments-first-free
|
|
|
|
var parent-comments-first-free/edx: int <- copy *parent-comments-first-free-addr
|
|
|
|
var dest/eax: (addr int) <- index parent-comments, parent-comments-first-free
|
2021-08-11 04:05:02 +00:00
|
|
|
var src/ecx: int <- copy item-idx
|
|
|
|
copy-to *dest, src
|
2021-08-13 15:27:50 +00:00
|
|
|
increment *parent-comments-first-free-addr
|
2021-08-11 04:05:02 +00:00
|
|
|
}
|
|
|
|
# channel name
|
|
|
|
skip-chars-matching-whitespace record
|
|
|
|
var double-quote/eax: byte <- read-byte record
|
|
|
|
compare double-quote, 0x22/double-quote
|
|
|
|
{
|
|
|
|
break-if-=
|
|
|
|
abort "parse-item: channel"
|
|
|
|
}
|
|
|
|
clear-stream s
|
|
|
|
next-json-string record, s
|
|
|
|
var dest/eax: (addr handle array byte) <- get item, channel
|
|
|
|
stream-to-array s, dest
|
2021-08-13 20:40:33 +00:00
|
|
|
#? set-cursor-position 0/screen, 0x70 item-idx
|
2021-08-11 04:05:02 +00:00
|
|
|
# cross-link to channels
|
|
|
|
{
|
|
|
|
var channels/esi: (addr array channel) <- copy _channels
|
|
|
|
var channel-index/eax: int <- find-or-insert channels, s
|
2021-08-13 20:40:33 +00:00
|
|
|
#? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, channel-index, 5/fg 0/bg
|
2021-08-11 04:05:02 +00:00
|
|
|
var channel-offset/eax: (offset channel) <- compute-offset channels, channel-index
|
|
|
|
var channel/eax: (addr channel) <- index channels, channel-offset
|
2021-08-13 20:40:33 +00:00
|
|
|
#? {
|
|
|
|
#? var foo/eax: int <- copy channel
|
|
|
|
#? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, foo, 4/fg 0/bg
|
|
|
|
#? }
|
2021-08-11 04:05:02 +00:00
|
|
|
var channel-posts-ah/ecx: (addr handle array int) <- get channel, posts
|
2021-08-13 15:27:50 +00:00
|
|
|
var channel-posts-first-free-addr/edx: (addr int) <- get channel, posts-first-free
|
2021-08-13 20:40:33 +00:00
|
|
|
#? {
|
|
|
|
#? var foo/eax: int <- copy channel-posts-first-free-addr
|
|
|
|
#? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, foo, 4/fg 0/bg
|
|
|
|
#? }
|
2021-08-13 15:27:50 +00:00
|
|
|
var channel-posts-first-free/ebx: int <- copy *channel-posts-first-free-addr
|
2021-08-13 20:40:33 +00:00
|
|
|
#? draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, channel-posts-first-free, 3/fg 0/bg
|
2021-08-11 04:05:02 +00:00
|
|
|
var channel-posts/eax: (addr array int) <- lookup *channel-posts-ah
|
2021-08-13 15:27:50 +00:00
|
|
|
var dest/eax: (addr int) <- index channel-posts, channel-posts-first-free
|
2021-08-13 20:40:33 +00:00
|
|
|
var src/ecx: int <- copy item-idx
|
|
|
|
copy-to *dest, src
|
|
|
|
increment *channel-posts-first-free-addr
|
2021-08-11 04:05:02 +00:00
|
|
|
}
|
|
|
|
# user index
|
|
|
|
{
|
|
|
|
var word-slice-storage: slice
|
|
|
|
var word-slice/ecx: (addr slice) <- address word-slice-storage
|
|
|
|
next-word record, word-slice
|
|
|
|
var src/eax: int <- parse-decimal-int-from-slice word-slice
|
|
|
|
var dest/edx: (addr int) <- get item, by
|
|
|
|
copy-to *dest, src
|
|
|
|
}
|
|
|
|
# text
|
|
|
|
var s-storage: (stream byte 0x4000) # message-text-limit
|
|
|
|
var s/ecx: (addr stream byte) <- address s-storage
|
|
|
|
skip-chars-matching-whitespace record
|
|
|
|
var double-quote/eax: byte <- read-byte record
|
|
|
|
compare double-quote, 0x22/double-quote
|
|
|
|
{
|
|
|
|
break-if-=
|
|
|
|
abort "parse-item: text"
|
|
|
|
}
|
|
|
|
next-json-string record, s
|
|
|
|
var dest/eax: (addr handle array byte) <- get item, text
|
|
|
|
stream-to-array s, dest
|
|
|
|
}
|
|
|
|
|
|
|
|
fn find-or-insert _channels: (addr array channel), name: (addr stream byte) -> _/eax: int {
|
|
|
|
var channels/esi: (addr array channel) <- copy _channels
|
|
|
|
var i/ecx: int <- copy 0
|
|
|
|
var max/edx: int <- length channels
|
|
|
|
{
|
|
|
|
compare i, max
|
|
|
|
break-if->=
|
|
|
|
var offset/eax: (offset channel) <- compute-offset channels, i
|
|
|
|
var curr/ebx: (addr channel) <- index channels, offset
|
|
|
|
var curr-name-ah/edi: (addr handle array byte) <- get curr, name
|
|
|
|
var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
|
|
|
|
{
|
|
|
|
compare curr-name, 0
|
|
|
|
break-if-!=
|
|
|
|
rewind-stream name
|
|
|
|
stream-to-array name, curr-name-ah
|
|
|
|
var posts-ah/eax: (addr handle array int) <- get curr, posts
|
|
|
|
populate posts-ah, 0x8000/channel-capacity
|
|
|
|
return i
|
|
|
|
}
|
|
|
|
var found?/eax: boolean <- stream-data-equal? name, curr-name
|
|
|
|
{
|
|
|
|
compare found?, 0/false
|
|
|
|
break-if-=
|
|
|
|
return i
|
|
|
|
}
|
|
|
|
i <- increment
|
|
|
|
loop
|
|
|
|
}
|
|
|
|
abort "out of channels"
|
|
|
|
return -1
|
2021-08-08 04:24:46 +00:00
|
|
|
}
|
2021-08-10 12:52:48 +00:00
|
|
|
|
2021-08-10 20:58:14 +00:00
|
|
|
# includes trailing double quote
|
2021-08-10 12:52:48 +00:00
|
|
|
fn slurp-json-string in: (addr stream byte), out: (addr stream byte) {
|
|
|
|
# open quote is already slurped
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var eof?/eax: boolean <- stream-empty? in
|
|
|
|
compare eof?, 0/false
|
|
|
|
break-if-=
|
2021-08-11 03:49:50 +00:00
|
|
|
abort "slurp-json-string: truncated"
|
2021-08-10 12:52:48 +00:00
|
|
|
}
|
|
|
|
var c/eax: byte <- read-byte in
|
|
|
|
{
|
|
|
|
var c-int/eax: int <- copy c
|
|
|
|
append-byte out, c-int
|
|
|
|
}
|
|
|
|
compare c, 0x22/double-quote
|
|
|
|
break-if-=
|
|
|
|
compare c, 0x5c/backslash
|
|
|
|
{
|
|
|
|
break-if-!=
|
|
|
|
# read next byte raw
|
|
|
|
c <- read-byte in
|
|
|
|
var c-int/eax: int <- copy c
|
|
|
|
append-byte out, c-int
|
|
|
|
}
|
|
|
|
loop
|
|
|
|
}
|
|
|
|
}
|
2021-08-10 20:58:14 +00:00
|
|
|
|
|
|
|
# drops trailing double quote
|
|
|
|
fn next-json-string in: (addr stream byte), out: (addr stream byte) {
|
|
|
|
# open quote is already read
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var eof?/eax: boolean <- stream-empty? in
|
|
|
|
compare eof?, 0/false
|
|
|
|
break-if-=
|
2021-08-11 03:49:50 +00:00
|
|
|
abort "next-json-string: truncated"
|
2021-08-10 20:58:14 +00:00
|
|
|
}
|
|
|
|
var c/eax: byte <- read-byte in
|
|
|
|
compare c, 0x22/double-quote
|
|
|
|
break-if-=
|
|
|
|
{
|
|
|
|
var c-int/eax: int <- copy c
|
|
|
|
append-byte out, c-int
|
|
|
|
}
|
|
|
|
compare c, 0x5c/backslash
|
|
|
|
{
|
|
|
|
break-if-!=
|
|
|
|
# read next byte raw
|
|
|
|
c <- read-byte in
|
|
|
|
var c-int/eax: int <- copy c
|
|
|
|
append-byte out, c-int
|
|
|
|
}
|
|
|
|
loop
|
|
|
|
}
|
|
|
|
}
|