Skip to main content

tex_engine/engine/utils/
memory.rs

1/*! Memory manangement and string interning. */
2
3use crate::tex::tokens::control_sequences::CSName;
4use crate::tex::tokens::token_lists::TokenList;
5use crate::tex::tokens::Token;
6
7/// Utility struct for managing memory allocation and string interning. In particular, it
8/// provides a [`CSHandler`](crate::tex::tokens::control_sequences::CSHandler) implementation for interning control
9/// sequence names (if applicable).
10#[derive(Clone)]
11pub struct MemoryManager<T: Token> {
12    cs_interner: <T::CS as CSName<T::Char>>::Handler,
13    strings: Vec<String>,
14    bytes: Vec<Vec<u8>>,
15    token_vecs: Vec<Vec<T>>,
16    empty: TokenList<T>,
17}
18impl<T: Token> Default for MemoryManager<T> {
19    fn default() -> Self {
20        MemoryManager {
21            cs_interner: <T::CS as CSName<T::Char>>::Handler::default(),
22            strings: Vec::new(),
23            bytes: Vec::new(),
24            token_vecs: Vec::new(),
25            #[cfg(feature = "multithreaded")]
26            empty: TokenList(shared_vector::AtomicSharedVector::new()),
27            #[cfg(not(feature = "multithreaded"))]
28            empty: TokenList(shared_vector::SharedVector::new()),
29        }
30    }
31}
32impl<T: Token> MemoryManager<T> {
33    /// Provides an empty `Vec<u8>` that can be returned using [`return_bytes`](Self::return_bytes), avoiding
34    /// the need to allocate a new `Vec<u8>` every time.
35    pub fn get_bytes(&mut self) -> Vec<u8> {
36        self.bytes.pop().unwrap_or_default()
37    }
38    /// Returns a `Vec<u8>` to the memory manager, which clears it and keeps it in memory for reuse.
39    pub fn return_bytes(&mut self, mut b: Vec<u8>) {
40        b.clear();
41        self.bytes.push(b)
42    }
43    /// Provides an empty `String` that can be returned using [`return_string`](Self::return_string), avoiding
44    /// the need to allocate a new `String` every time.
45    pub fn get_string(&mut self) -> String {
46        self.strings.pop().unwrap_or_default()
47    }
48    /// Returns a `String` to the memory manager, which clears it and keeps it in memory for reuse.
49    pub fn return_string(&mut self, mut s: String) {
50        s.clear();
51        self.strings.push(s)
52    }
53    /// Provides an empty `Vec<T>` that can be returned using [`return_token_vec`](Self::return_token_vec), avoiding
54    /// the need to allocate a new `Vec<T>` every time.
55    pub fn get_token_vec(&mut self) -> Vec<T> {
56        self.token_vecs.pop().unwrap_or_default()
57    }
58    /// Returns a `Vec<T>` to the memory manager, which clears it and keeps it in memory for reuse.
59    pub fn return_token_vec(&mut self, mut v: Vec<T>) {
60        v.clear();
61        self.token_vecs.push(v)
62    }
63    /// Returns a new memory manager with the given control sequence interner.
64    pub fn new_with_cs_interner(cs_interner: <T::CS as CSName<T::Char>>::Handler) -> Self {
65        MemoryManager {
66            cs_interner,
67            strings: Vec::new(),
68            bytes: Vec::new(),
69            token_vecs: Vec::new(),
70            #[cfg(feature = "multithreaded")]
71            empty: TokenList(shared_vector::AtomicSharedVector::new()),
72            #[cfg(not(feature = "multithreaded"))]
73            empty: TokenList(shared_vector::SharedVector::new()),
74        }
75    }
76    /// Sets the control sequence interner.
77    pub fn set_cs_interner(&mut self, cs_interner: <T::CS as CSName<T::Char>>::Handler) {
78        self.cs_interner = cs_interner;
79    }
80
81    /// Returns the control sequence interner mutably.
82    pub fn cs_interner_mut(&mut self) -> &mut <T::CS as CSName<T::Char>>::Handler {
83        &mut self.cs_interner
84    }
85
86    /// Returns the control sequence interner.
87    pub fn cs_interner(&self) -> &<T::CS as CSName<T::Char>>::Handler {
88        &self.cs_interner
89    }
90
91    /// Returns an empty token list.
92    pub fn empty_list(&self) -> TokenList<T> {
93        self.empty.clone()
94    }
95}