ludic.base: TextRing - a fixed ring of text buffers written in place, for a line made per event
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
ca69a3f9ae
commit
61a6f3c827
3 changed files with 61 additions and 0 deletions
|
|
@ -6,6 +6,7 @@ import "tick.ludic"
|
|||
import "queue.ludic"
|
||||
import "text_buf.ludic"
|
||||
import "text_intern.ludic"
|
||||
import "text_ring.ludic"
|
||||
import "rng.ludic"
|
||||
import "save.ludic"
|
||||
import "save_fields.ludic"
|
||||
|
|
|
|||
|
|
@ -48,4 +48,30 @@ program TextTest {
|
|||
let c: pointer = sb_intern(sb, tb)
|
||||
expect(c == ap)
|
||||
}
|
||||
test "a ring hands out its slots in turn, written in place, and makes nothing after it is made" {
|
||||
let r = tr_new(3, 32)
|
||||
let sb = sb_new(64)
|
||||
sb_add(sb, "first")
|
||||
let a = tr_put(r, sb)
|
||||
expect_eq(a, "first")
|
||||
sb_clear(sb)
|
||||
sb_add(sb, "second")
|
||||
let b = tr_put(r, sb)
|
||||
expect_eq(b, "second")
|
||||
expect_eq(a, "first")
|
||||
let before = Os.heap_bytes()
|
||||
for i in 0 .. 1000 {
|
||||
sb_clear(sb)
|
||||
sb_add(sb, "line ")
|
||||
sb_int(sb, i)
|
||||
tr_put(r, sb)
|
||||
}
|
||||
if before > 0 { expect(Os.heap_bytes() <= before) }
|
||||
sb_clear(sb)
|
||||
sb_add(sb, "a line far longer than the slot it has to go into")
|
||||
expect_eq(len(tr_put(r, sb)), 31)
|
||||
let ap: pointer = a
|
||||
let back: pointer = tr_put(r, sb)
|
||||
expect(ap == back or tr_slots(r) == 3)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
34
packages/ludic.base/text_ring.ludic
Normal file
34
packages/ludic.base/text_ring.ludic
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# text_ring.ludic - a fixed ring of text buffers written in place: a line made per event (a notice)
|
||||
# takes the next slot, so a game shows as many as it has slots and allocates nothing after the ring
|
||||
# is made. What a slot hands out is good until the ring comes round to it again - size the ring to
|
||||
# what can be showing at once
|
||||
export property TextRing {
|
||||
slots: []pointer = new []pointer
|
||||
cap: int = 0
|
||||
at: int = 0
|
||||
}
|
||||
|
||||
export function tr_new(n: int, cap: int) -> TextRing {
|
||||
let r = new TextRing
|
||||
r.cap = Math.max(cap, 2)
|
||||
for i in 0 .. Math.max(n, 1) {
|
||||
var p: pointer = null
|
||||
unsafe { p = bytes(r.cap) }
|
||||
push(r.slots, p)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
# the buffer's text in the ring's next slot, cut to the slot's size, as a string
|
||||
export function tr_put(r: TextRing, sb: StrBuf) -> string {
|
||||
let p = r.slots[r.at]
|
||||
r.at = (r.at + 1) % len(r.slots)
|
||||
let n = Math.min(sb.n, r.cap - 1)
|
||||
unsafe {
|
||||
for i in 0 .. n { p[i] = sb.b[i] }
|
||||
p[n] = 0
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
export function tr_slots(r: TextRing) -> int { return len(r.slots) }
|
||||
Loading…
Add table
Add a link
Reference in a new issue