about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--112read-byte.subx32
-rw-r--r--400.mu1
-rw-r--r--browse_slack/main.mu71
3 files changed, 104 insertions, 0 deletions
diff --git a/112read-byte.subx b/112read-byte.subx
index 93503d8b..5ffd4903 100644
--- a/112read-byte.subx
+++ b/112read-byte.subx
@@ -42,6 +42,38 @@ $read-byte:abort:
     (abort "read-byte: empty stream")
     # never gets here
 
+# Return next byte value in eax, with top 3 bytes cleared.
+# Abort on reaching end of stream.
+peek-byte:  # s: (addr stream byte) -> result/eax: byte
+    # . prologue
+    55/push-ebp
+    89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+    # . save registers
+    51/push-ecx
+    56/push-esi
+    # esi = s
+    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+    # ecx = s->read
+    8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(esi+4) to ecx
+    # if (f->read >= f->write) abort
+    3b/compare                      0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # compare ecx with *esi
+    0f 8d/jump-if->=  $peek-byte:abort/disp32
+    # result = f->data[f->read]
+    31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
+    8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(esi+ecx+12) to AL
+$peek-byte:end:
+    # . restore registers
+    5e/pop-to-esi
+    59/pop-to-ecx
+    # . epilogue
+    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+    5d/pop-to-ebp
+    c3/return
+
+$peek-byte:abort:
+    (abort "peek-byte: empty stream")
+    # never gets here
+
 == data
 
 _test-input-stream:  # (stream byte)
diff --git a/400.mu b/400.mu
index 6640a524..d1143ea8 100644
--- a/400.mu
+++ b/400.mu
@@ -59,6 +59,7 @@ sig space-remaining-in-stream f: (addr stream byte) -> _/eax: int
 sig write-stream f: (addr stream byte), s: (addr stream byte)
 sig write-stream-immutable f: (addr stream byte), s: (addr stream byte)
 sig read-byte s: (addr stream byte) -> _/eax: byte
+sig peek-byte s: (addr stream byte) -> _/eax: byte
 sig append-byte f: (addr stream byte), n: int  # really just a byte, but I want to pass in literal numbers
 #sig to-hex-char in/eax: int -> out/eax: int
 sig append-byte-hex f: (addr stream byte), n: int  # really just a byte, but I want to pass in literal numbers
diff --git a/browse_slack/main.mu b/browse_slack/main.mu
index dadf653c..f4a5abfb 100644
--- a/browse_slack/main.mu
+++ b/browse_slack/main.mu
@@ -86,6 +86,9 @@ fn parse in: (addr stream byte), users: (addr array user), channels: (addr array
     var done?/eax: boolean <- stream-empty? in
     compare done?, 0/false
     break-if-!=
+    set-cursor-position 0/screen, 0 0
+    draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, user-idx, 3/fg 0/bg
+    draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, item-idx, 4/fg 0/bg
     parse-record in, record
     var user?/eax: boolean <- user-record? record
     {
@@ -105,9 +108,49 @@ fn parse in: (addr stream byte), users: (addr array user), channels: (addr array
 }
 
 fn parse-record in: (addr stream byte), out: (addr stream byte) {
+  var paren/eax: byte <- read-byte in
+  compare paren, 0x28/open-paren
+  {
+    break-if-=
+    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-=
+      abort "parse-record: truncated"
+    }
+    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
 }
 
 fn user-record? record: (addr stream byte) -> _/eax: boolean {
+  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
   return 0/false
 }
 
@@ -116,3 +159,31 @@ fn parse-user record: (addr stream byte), users: (addr array user), user-idx: in
 
 fn parse-item record: (addr stream byte), channels: (addr array channel), items: (addr array item), item-idx: int {
 }
+
+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-=
+      abort "slurp-json-string: truncated"
+    }
+    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
+  }
+}