let mut functor_writer = Heap::functor_writer(functor);
functor_writer(&mut heap).unwrap();
- assert_eq!(heap.cell_len(), 8);
+ assert_eq!(heap.cell_len(), 10);
assert_eq!(heap[0], atom_as_cell!(atom!("second"), 1));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2)));
heap.slice_to_str(heap_index!(2), "a stuttered".len()),
"a stuttered"
);
- assert_eq!(heap[4], pstr_loc_as_cell!(heap_index!(5)));
+ assert_eq!(heap[4], list_loc_as_cell!(5));
+ assert_eq!(heap[5], char_as_cell!('\u{0}'));
+ assert_eq!(heap[6], pstr_loc_as_cell!(heap_index!(7)));
assert_eq!(
- heap.slice_to_str(heap_index!(5), " string".len()),
+ heap.slice_to_str(heap_index!(7), " string".len()),
" string"
);
- assert_eq!(heap[7], empty_list_as_cell!());
+ assert_eq!(heap[9], empty_list_as_cell!());
}
#[test]
}
pub(crate) fn push_pstr(&mut self, mut src: &str) -> Option<HeapCellValue> {
- let orig_h = self.cell_len();
-
- if src.is_empty() {
- return if orig_h == self.heap_cell_len {
- // src is empty and always was. nothing allocated
- // in this case, so nothing to point to in heap.
- None
- } else {
- self.push_cell(heap_loc_as_cell!(orig_h));
- Some(heap_loc_as_cell!(orig_h))
- };
- }
+ let anchor = self.cell_len();
+ let mut ret = None;
loop {
- let null_char_idx = src.find('\u{0}').unwrap_or(src.len());
- let cells_written = self.push_pstr_segment(&src[0..null_char_idx]);
-
- if cells_written == 0 {
- return None;
- } else if null_char_idx + 1 < src.len() {
- let tail_idx = self.cell_len();
- self.push_cell(pstr_loc_as_cell!(heap_index!(tail_idx + 1)));
+ // Eat the first null chars
+ while let Some('\u{0}') = src.chars().next() {
+ match ret {
+ Some(_) => {
+ debug_assert_ne!(anchor, self.cell_len());
+ self.push_cell(list_loc_as_cell!(self.cell_len() + 1));
+ }
+ None => {
+ debug_assert_eq!(anchor, self.cell_len());
+ ret = Some(list_loc_as_cell!(self.cell_len()));
+ }
+ }
+
+ self.push_cell(char_as_cell!('\u{0}'));
+
+ src = &src[1..];
+ }
+
+ if src.is_empty() {
+ return ret;
+ }
+
+ debug_assert!(!src.is_empty());
+
+ if let Some(null_char_idx) = src.find('\u{0}') {
+ debug_assert_ne!(null_char_idx, 0);
+
+ match ret {
+ Some(_) => {
+ debug_assert_ne!(anchor, self.cell_len());
+ self.push_cell(pstr_loc_as_cell!(heap_index!(self.cell_len() + 1)));
+ }
+ None => {
+ debug_assert_eq!(anchor, self.cell_len());
+ ret = Some(pstr_loc_as_cell!(heap_index!(self.cell_len())));
+ }
+ }
+
+ self.push_pstr_segment(&src[0..null_char_idx]);
+
+ // Put the \x0\
+ self.push_cell(list_loc_as_cell!(self.cell_len() + 1));
+ self.push_cell(char_as_cell!('\u{0}'));
+
src = &src[null_char_idx + 1..];
+ if src.is_empty() {
+ return ret;
+ }
} else {
- return Some(pstr_loc_as_cell!(heap_index!(orig_h)));
+ match ret {
+ Some(_) => {
+ debug_assert_ne!(anchor, self.cell_len());
+ self.push_cell(pstr_loc_as_cell!(heap_index!(self.cell_len() + 1)));
+ }
+ None => {
+ debug_assert_eq!(anchor, self.cell_len());
+ ret = Some(pstr_loc_as_cell!(heap_index!(self.cell_len())));
+ }
+ }
+
+ self.push_pstr_segment(&src);
+
+ return ret;
}
}
}
pub fn allocate_pstr(&mut self, src: &str) -> Result<Option<PStrWriteInfo>, usize> {
let size_in_heap = Self::compute_pstr_size(src);
+
let pstr_loc = heap_index!(self.cell_len());
Ok(if size_in_heap > 0 {