From: Ian Jackson Date: Thu, 11 Mar 2021 21:24:37 +0000 (+0000) Subject: zcoord: Provide plus_offset method X-Git-Tag: otter-0.4.0~141 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=af5fe9ee53654ed788465c939c8994a176c53162;p=otter.git zcoord: Provide plus_offset method Signed-off-by: Ian Jackson --- diff --git a/base/zcoord.rs b/base/zcoord.rs index a656f984..0f955f6c 100644 --- a/base/zcoord.rs +++ b/base/zcoord.rs @@ -60,6 +60,12 @@ // limb to 0000000000, start again: decrement rightmost nonzero // limb by 1, with borrow, then add two limbs vvvvvvvvvv, and // redo. +// +// Given a base value, and an u32 "offset multiplier", produce a value +// +// The resulting values are all greater than the base, and +// in the same order as the provided offset multipliers. +// The function is deterministic use std::cmp::{max, Ordering}; use std::convert::{TryFrom, TryInto}; @@ -76,6 +82,8 @@ use serde_with::DeserializeFromStr; use serde_with::SerializeDisplay; use thiserror::Error; +use crate::misc::default; + //---------- core definitions ---------- pub type RangeCount = u32; @@ -623,7 +631,7 @@ mod innards { pub(super) struct Header { - pub taillen: u16, + pub taillen: u16, // in characters } #[repr(C)] @@ -711,6 +719,31 @@ mod innards { layout(taillen) } } + + #[throws(Overflow)] + pub fn plus_offset(&self, offset: u32) -> Self { unsafe { + let (old_header, old_tail) = ptrs(self.0.as_ptr()); + let old_taillen = old_header.as_ref().unwrap().taillen; + let new_taillen = old_taillen + .checked_add(TEXT_PER_LIMB as Taillen).ok_or(Overflow)?; + let old_taillen: usize = old_taillen.into(); + let new_limb = lv( + (offset as RawLimbVal) << (BITS_PER_LIMB - 32) | + 1 << (BITS_PER_LIMB - 33) + ); + let mut buf: [u8; TEXT_PER_LIMB] = default(); + buf[0] = b'_'; + new_limb.to_str_buf((&mut buf[1..TEXT_PER_LIMB]).try_into().unwrap()); + ZCoord::alloc_unsafe(new_taillen, |new_tail| { + ptr::copy_nonoverlapping(old_tail, + new_tail, + old_taillen); + + ptr::copy_nonoverlapping(buf.as_ptr(), + new_tail.add(old_taillen), + TEXT_PER_LIMB); + }) + } } } impl Drop for ZCoord { @@ -931,4 +964,15 @@ mod test { let mut it = mkr(None,Some("fvvq000000"),0).unwrap(); it.nxt(None); } + + #[test] + fn plus_offset() { + let z: ZCoord = "3o00000000".parse().unwrap(); + assert_eq!(z.plus_offset(0).unwrap(), + "3o00000000_0000004000".parse().unwrap()); + assert_eq!(z.plus_offset(1).unwrap(), + "3o00000000_000000c000".parse().unwrap()); + assert_eq!(z.plus_offset(0xffffffff).unwrap(), + "3o00000000_vvvvvvs000".parse().unwrap()); + } }