hicc_std/
std_string.rs

1use crate::*;
2use std::cmp::min;
3use std::cmp::{Ordering, PartialEq, PartialOrd};
4use std::convert::From;
5use std::ffi::CStr;
6use std::slice;
7
8hicc::cpp! {
9    #include <string>
10}
11
12hicc::import_class! {
13    #[cpp(class = "template<class CharT, class Traits, class Allocator> std::basic_string<CharT, Traits, Allocator>")]
14    pub class basic_string<CharT> {
15        pub const npos: usize = usize::MAX;
16        /// ```
17        /// use std::ffi::CStr;
18        /// use hicc_std::string;
19        /// let s = string::from(c"abc");
20        /// let cstr = unsafe { CStr::from_ptr(s.c_str()) };
21        /// assert_eq!(cstr, c"abc");
22        /// ```
23        #[cpp(method = "const CharT* c_str() const")]
24        pub fn c_str(&self) -> *const CharT;
25
26        /// ```
27        /// use hicc_std::string;
28        /// let s = string::new();
29        /// assert!(s.is_empty());
30        /// ```
31        #[cpp(method = "bool empty() const")]
32        pub fn is_empty(&self) -> bool;
33
34        /// ```
35        /// use hicc_std::string;
36        /// let s = string::new();
37        /// assert_eq!(s.size(), 0);
38        /// ```
39        #[cpp(method = "size_t size() const")]
40        pub fn size(&self) -> usize;
41
42        /// ```
43        /// use hicc_std::string;
44        /// let s = string::new();
45        /// println!("s.max_size = {}", s.max_size());
46        /// ```
47        #[cpp(method = "size_t max_size() const")]
48        pub fn max_size(&self) -> usize;
49
50        /// ```
51        /// use hicc_std::string;
52        /// let s = string::new();
53        /// println!("s.capacity = {}", s.capacity());
54        /// ```
55        #[cpp(method = "size_t capacity() const")]
56        pub fn capacity(&self) -> usize;
57
58        /// ```
59        /// use hicc_std::string;
60        /// let mut s = string::from(c"a");
61        /// s.resize(3, b'c' as i8);
62        /// assert_eq!(s.as_cstr(), c"acc");
63        /// ```
64        #[cpp(method = "void resize(size_t, CharT) ")]
65        pub fn resize(&mut self, n: usize, c: CharT);
66
67        /// ```
68        /// use hicc_std::string;
69        /// let mut s = string::from(c"abc");
70        /// s.reserve(100);
71        /// println!("s.capacity = {}", s.capacity());
72        /// ```
73        #[cpp(method = "void reserve(size_t)")]
74        pub fn reserve(&mut self, n: usize);
75
76        /// ```
77        /// use hicc_std::string;
78        /// let mut s = string::from(c"abc");
79        /// s.clear();
80        /// assert!(s.is_empty());
81        /// ```
82        #[cpp(method = "void clear()")]
83        pub fn clear(&mut self);
84
85        /// ```
86        /// use hicc_std::string;
87        /// let mut s = string::from(c"abc");
88        /// s.reserve(100);
89        /// println!("before shrink_to_fit: capacity = {}", s.capacity());
90        /// s.assign(10, b'c' as i8);
91        /// s.shrink_to_fit();
92        /// println!("after shrink_to_fit: capacity = {}", s.capacity());
93        /// ```
94        #[cpp(method = "void shrink_to_fit()")]
95        pub fn shrink_to_fit(&mut self);
96
97        /// 如果pos超出范围,会返回空字符串.
98        /// ```
99        /// use hicc_std::string;
100        /// let mut s = string::from(c"abc");
101        /// let substr = s.substr(1, 2);
102        /// assert_eq!(substr.as_cstr(), c"bc");
103        /// ```
104        pub fn substr(&self, mut pos: usize, len: usize) -> Self {
105            if pos > self.size() {
106                pos = self.size();
107            }
108            self._substr(pos, len)
109        }
110        #[cpp(method = "Self substr(size_t, size_t) const")]
111        fn _substr(&self, pos: usize, len: usize) -> Self;
112
113        /// ```
114        /// use hicc_std::string;
115        /// let s1 = string::from(c"abc");
116        /// let s2 = string::from(c"abd");
117        /// assert!(s1 < s2);
118        /// assert!(s1 != s2);
119        /// ```
120        #[cpp(method = "int compare(const Self&) const")]
121        pub fn compare(&self, other: &Self) -> i32;
122
123        /// ```
124        /// use hicc_std::string;
125        /// let s1 = string::from(c"abcdef");
126        /// let s2 = string::from(c"bcd");
127        /// assert_eq!(s1.find_str(&s2, 0), 1);
128        /// ```
129        #[cpp(method = "size_t find(const Self&, size_t) const")]
130        pub fn find_str(&self, target: &Self, pos: usize) -> usize;
131
132        /// ```
133        /// use hicc_std::string;
134        /// let s = string::from(c"abcdef");
135        /// assert_eq!(s.find(b'c' as i8, 1), 2);
136        /// ```
137        #[cpp(method = "size_t find(CharT, size_t) const")]
138        pub fn find(&self, c: CharT, pos: usize) -> usize;
139
140        /// ```
141        /// use hicc_std::string;
142        /// let s1 = string::from(c"abcdef");
143        /// let s2 = string::from(c"bcd");
144        /// assert_eq!(s1.rfind_str(&s2, string::npos), 1);
145        /// ```
146        #[cpp(method = "size_t rfind(const Self&, size_t) const")]
147        pub fn rfind_str(&self, target: &Self, pos: usize) -> usize;
148
149        /// ```
150        /// use hicc_std::string;
151        /// let s = string::from(c"abcdef");
152        /// assert_eq!(s.rfind(b'c' as i8, string::npos), 2);
153        /// ```
154        #[cpp(method = "size_t rfind(CharT, size_t) const")]
155        pub fn rfind(&self, c: CharT, pos: usize) -> usize;
156
157        /// ```
158        /// use hicc_std::string;
159        /// let s1 = string::from(c"abcdef");
160        /// let s2 = string::from(c"dfb");
161        /// assert_eq!(s1.find_first_of(&s2, 0), 1);
162        /// ```
163        #[cpp(method = "size_t find_first_of(const Self&, size_t) const")]
164        pub fn find_first_of(&self, target: &Self, pos: usize) -> usize;
165
166        /// ```
167        /// use hicc_std::string;
168        /// let s = string::from(c"abcabc");
169        /// assert_eq!(s.find_first(b'c' as i8, 0), 2);
170        /// ```
171        #[cpp(method = "size_t find_first_of(CharT, size_t) const")]
172        pub fn find_first(&self, c: CharT, pos: usize) -> usize;
173
174        /// ```
175        /// use hicc_std::string;
176        /// let s1 = string::from(c"abcdef");
177        /// let s2 = string::from(c"dfb");
178        /// assert_eq!(s1.find_last_of(&s2, string::npos), 5);
179        /// ```
180        #[cpp(method = "size_t find_last_of(const Self&, size_t) const")]
181        pub fn find_last_of(&self, target: &Self, pos: usize) -> usize;
182
183        /// ```
184        /// use hicc_std::string;
185        /// let s = string::from(c"abcabc");
186        /// assert_eq!(s.find_last(b'c' as i8, string::npos), 5);
187        /// ```
188        #[cpp(method = "size_t find_last_of(CharT, size_t) const")]
189        pub fn find_last(&self, c: CharT, pos: usize) -> usize;
190
191        /// ```
192        /// use hicc_std::string;
193        /// let s1 = string::from(c"abcdef");
194        /// let s2 = string::from(c"abc");
195        /// assert_eq!(s1.find_first_not_of(&s2, 0), 3);
196        /// ```
197        #[cpp(method = "size_t find_first_not_of(const Self&, size_t) const")]
198        pub fn find_first_not_of(&self, target: &Self, pos: usize) -> usize;
199
200        /// ```
201        /// use hicc_std::string;
202        /// let s = string::from(c"abcabc");
203        /// assert_eq!(s.find_first_not(b'a' as i8, 0), 1);
204        /// ```
205        #[cpp(method = "size_t find_first_not_of(CharT, size_t) const")]
206        pub fn find_first_not(&self, c: CharT, pos: usize) -> usize;
207
208        /// ```
209        /// use hicc_std::string;
210        /// let s1 = string::from(c"abcdef");
211        /// let s2 = string::from(c"def");
212        /// assert_eq!(s1.find_last_not_of(&s2, string::npos), 2);
213        /// ```
214        #[cpp(method = "size_t find_last_not_of(const Self&, size_t) const")]
215        pub fn find_last_not_of(&self, target: &Self, pos: usize) -> usize;
216
217        /// ```
218        /// use hicc_std::string;
219        /// let s = string::from(c"abcabc");
220        /// assert_eq!(s.find_last_not(b'c' as i8, string::npos), 4);
221        /// ```
222        #[cpp(method = "size_t find_last_not_of(CharT, size_t) const")]
223        pub fn find_last_not(&self, c: CharT, pos: usize) -> usize;
224
225        /// 如果subpos超出范围则不做任何改变.
226        /// ```
227        /// use hicc_std::string;
228        /// let mut s1 = string::from(c"abc");
229        /// let s2 = string::from(c"def");
230        /// s1.append_str(&s2, 0, 2);
231        /// assert_eq!(s1.as_cstr(), c"abcde");
232        /// ```
233        pub fn append_str(&mut self, s: &Self, subpos: usize, sublen: usize) {
234            if subpos < s.size() {
235                self._append_str(s, subpos, sublen);
236            }
237        }
238        #[cpp(method = "Self& append(const Self&, size_t, size_t)")]
239        fn _append_str(&mut self, s: &Self, subpos: usize, sublen: usize);
240
241        /// ```
242        /// use hicc_std::string;
243        /// let mut s = string::from(c"abc");
244        /// s.append(1, b'd' as i8);
245        /// assert_eq!(s.as_cstr(), c"abcd");
246        /// ```
247        #[cpp(method = "Self& append(size_t, CharT)")]
248        pub fn append(&mut self, n: usize, c: CharT);
249
250        /// 如果subpos超出范围不做任何改变, 如果pos超出范围则追加到最后.
251        /// ```
252        /// use hicc_std::string;
253        /// let mut s1 = string::from(c"abc");
254        /// let mut s2 = string::from(c"def");
255        /// s1.insert_str(0, &s2, 0, string::npos);
256        /// assert_eq!(s1.as_cstr(), c"defabc");
257        /// s1.insert_str(100, &s2, 0, string::npos);
258        /// assert_eq!(s1.as_cstr(), c"defabcdef");
259        /// ```
260        pub fn insert_str(&mut self, pos: usize, s: &Self, subpos: usize, sublen: usize) {
261            if subpos < s.size() {
262                self._insert_str(min(pos, self.size()), s, subpos, sublen);
263            }
264        }
265        #[cpp(method = "Self& insert(size_t, const Self&, size_t, size_t)")]
266        fn _insert_str(&mut self, pos: usize, s: &Self, subpos: usize, sublen: usize);
267
268        /// 如果pos超出范围则追加到最后.
269        /// ```
270        /// use hicc_std::string;
271        /// let mut s = string::from(c"abc");
272        /// s.insert(0, 3, b'd' as i8);
273        /// assert_eq!(s.as_cstr(), c"dddabc");
274        /// s.insert(110, 3, b'd' as i8);
275        /// assert_eq!(s.as_cstr(), c"dddabcddd");
276        /// ```
277        pub fn insert(&mut self, pos: usize, n: usize, c: CharT::InputType) {
278            self._insert(min(pos, self.size()), n, c);
279        }
280        #[cpp(method = "Self& insert(size_t, size_t, CharT)")]
281        fn _insert(&mut self, pos: usize, n: usize, c: CharT);
282
283        /// 如果pos或者subpos超出范围则不做任何改变.
284        /// ```
285        /// use hicc_std::string;
286        /// let mut s1 = string::from(c"abc");
287        /// let mut s2 = string::from(c"de");
288        /// s1.replace_str(0, string::npos, &s2, 0, string::npos);
289        /// assert_eq!(s1.as_cstr(), c"de");
290        /// ```
291        pub fn replace_str(&mut self, pos: usize, len: usize, s: &Self, subpos: usize, sublen: usize) {
292            if pos < self.size() && subpos < s.size() {
293                self._replace_str(pos, len, s, subpos, sublen);
294            }
295        }
296        #[cpp(method = "Self& replace(size_t, size_t, const Self&, size_t, size_t)")]
297        fn _replace_str(&mut self, pos: usize, len: usize, s: &Self, subpos: usize, sublen: usize);
298
299        /// 如果pos超出范围则不做任何改变.
300        /// ```
301        /// use hicc_std::string;
302        /// let mut s = string::from(c"abc");
303        /// s.replace(0, string::npos, 1, b'd' as i8);
304        /// assert_eq!(s.as_cstr(), c"d");
305        /// ```
306        pub fn replace(&mut self, pos: usize, len: usize, n: usize, c: CharT::InputType) {
307            if pos < self.size() {
308                self._replace(pos, len, n, c);
309            }
310        }
311        #[cpp(method = "Self& replace(size_t, size_t, size_t, CharT)")]
312        fn _replace(&mut self, pos: usize, len: usize, n: usize, c: CharT);
313
314        /// 如果subpos超出范围则不做任何改变.
315        /// ```
316        /// use hicc_std::string;
317        /// let mut s1 = string::from(c"abc");
318        /// let mut s2 = string::from(c"de");
319        /// s1.assign_str(&s2, 0, string::npos);
320        /// assert_eq!(s1.as_cstr(), c"de");
321        /// ```
322        pub fn assign_str(&mut self, s: &Self, subpos: usize, sublen: usize) {
323            if subpos < s.size() {
324                self._assign_str(s, subpos, sublen);
325            }
326        }
327        #[cpp(method = "Self& assign(const Self&, size_t, size_t)")]
328        fn _assign_str(&mut self, s: &Self, subpos: usize, sublen: usize);
329
330        /// ```
331        /// use hicc_std::string;
332        /// let mut s = string::from(c"abc");
333        /// s.assign(1, b'd' as i8);
334        /// assert_eq!(s.as_cstr(), c"d");
335        /// ```
336        #[cpp(method = "Self& assign(size_t, CharT)")]
337        pub fn assign(&mut self, n: usize, c: CharT);
338
339        /// 如果pos超出范围则不做任何改变.
340        /// ```
341        /// use hicc_std::string;
342        /// let mut s = string::from(c"abc");
343        /// s.erase(1, 1);
344        /// assert_eq!(s.as_cstr(), c"ac");
345        /// ```
346        pub fn erase(&mut self, pos: usize, len: usize) {
347            if pos < self.size() {
348                self._erase(pos, len);
349            }
350        }
351        #[cpp(method = "Self& erase(size_t, size_t)")]
352        fn _erase(&mut self, pos: usize, len: usize);
353
354
355        /// ```
356        /// use hicc_std::string;
357        /// let mut s = string::from(c"abc");
358        /// s.push_back(b'd' as i8);
359        /// assert_eq!(s.as_cstr(), c"abcd");
360        /// ```
361        #[cpp(method = "void push_back(CharT)")]
362        pub fn push_back(&mut self, c: CharT);
363
364        /// 如果为空则不做任何改变.
365        /// ```
366        /// use hicc_std::string;
367        /// let mut s = string::from(c"abc");
368        /// s.pop_back();
369        /// assert_eq!(s.as_cstr(), c"ab");
370        /// ```
371        pub fn pop_back(&mut self) {
372            if !self.is_empty() {
373                self._pop_back();
374            }
375        }
376        #[cpp(method = "void pop_back()")]
377        fn _pop_back(&mut self);
378
379        /// ```
380        /// use hicc_std::string;
381        /// let mut s1 = string::from(c"abc");
382        /// let mut s2 = string::from(c"de");
383        /// s1.swap(&mut s2);
384        /// assert_eq!(s1.as_cstr(), c"de");
385        /// assert_eq!(s2.as_cstr(), c"abc");
386        /// ```
387        #[cpp(method = "void swap(Self&)")]
388        pub fn swap(&mut self, other: &mut Self);
389
390        /// ```
391        /// use hicc_std::string;
392        /// let s = string::from(c"abc");
393        /// assert_eq!(s.get(0), Some(&(b'a' as i8)));
394        /// assert_eq!(s.get(3), None);
395        /// ```
396        pub fn get(&self, pos: usize) -> Option<CharT::OutputRef<'_>> {
397            if pos < self.size() {
398                return Some(self._get(pos));
399            }
400            None
401        }
402        #[cpp(method = "const CharT& at(size_t) const")]
403        fn _get(&self, pos: usize) -> &CharT;
404
405
406        /// ```
407        /// use hicc_std::string;
408        /// let mut s = string::from(c"abc");
409        /// assert!(s.get_mut(0).is_some());
410        /// assert_eq!(*s.get_mut(0).unwrap(), b'a' as i8);
411        /// assert_eq!(s.get(3), None);
412        /// ```
413        pub fn get_mut(&mut self, pos: usize) -> Option<CharT::OutputRefMut<'_>> {
414            if pos < self.size() {
415                return Some(self._get_mut(pos));
416            }
417            None
418        }
419        #[cpp(method = "CharT& at(size_t)")]
420        fn _get_mut(&mut self, pos: usize) -> &mut CharT;
421    }
422
423    /// 对应`std::string`
424    #[allow(non_camel_case_types)]
425    pub type string = basic_string<hicc::Pod<i8>>;
426    /// 对应`std::u16string`
427    #[allow(non_camel_case_types)]
428    pub type u16string = basic_string<hicc::Pod<i16>>;
429    /// 对应`std::u32string`
430    #[allow(non_camel_case_types)]
431    pub type u32string = basic_string<hicc::Pod<i32>>;
432}
433
434unsafe impl<CharT: hicc::AbiType + Sync> Send for basic_string<CharT> {}
435unsafe impl<CharT: hicc::AbiType + Sync> Sync for basic_string<CharT> {}
436
437impl<T: Sized + 'static> basic_string<hicc::Pod<T>> {
438    /// ```
439    /// use hicc_std::string;
440    /// let mut s = string::with_cstr(c"bcd");
441    /// assert_eq!(s.as_slice(), &[b'b' as i8, b'c' as i8, b'd' as i8]);
442    /// ```
443    pub fn as_slice(&self) -> &[T] {
444        let cstr = self.c_str();
445        let size = self.size();
446        unsafe { slice::from_raw_parts(cstr, size) }
447    }
448
449    /// ```
450    /// use hicc_std::string;
451    /// let mut s = string::with_cstr(c"abc");
452    /// s.as_slice_mut().iter_mut().for_each(|mut c| { *c += 1; });
453    /// assert_eq!(s.as_slice(), &[b'b' as i8, b'c' as i8, b'd' as i8]);
454    /// ```
455    pub fn as_slice_mut(&mut self) -> &mut [T] {
456        let cstr = self.c_str();
457        let size = self.size();
458        unsafe { slice::from_raw_parts_mut(cstr.cast_mut(), size) }
459    }
460}
461
462impl<T: hicc::AbiType> PartialEq for basic_string<T> {
463    fn eq(&self, other: &Self) -> bool {
464        self.compare(other) == 0
465    }
466}
467
468impl<T: hicc::AbiType> PartialOrd for basic_string<T> {
469    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
470        match self.compare(other) {
471            0 => Some(Ordering::Equal),
472            1.. => Some(Ordering::Greater),
473            _ => Some(Ordering::Less),
474        }
475    }
476}
477
478impl string {
479    pub fn new() -> Self {
480        string_new()
481    }
482
483    pub fn with_cstr(s: &CStr) -> Self {
484        unsafe { string_with_cstr(s.as_ptr()) }
485    }
486
487    pub fn with_buf(b: &[u8]) -> Self {
488        unsafe { string_with_buf(b.as_ptr(), b.len()) }
489    }
490
491    pub fn as_cstr(&self) -> &CStr {
492        unsafe { CStr::from_ptr(self.c_str()) }
493    }
494}
495
496impl From<&CStr> for string {
497    fn from(s: &CStr) -> Self {
498        unsafe { string_with_cstr(s.as_ptr()) }
499    }
500}
501
502impl Default for string {
503    fn default() -> Self {
504        Self::new()
505    }
506}
507
508impl u16string {
509    pub fn new() -> Self {
510        u16string_new()
511    }
512
513    pub fn with_buf(b: &[u16]) -> Self {
514        unsafe { u16string_with_buf(b.as_ptr(), b.len()) }
515    }
516}
517
518impl Default for u16string {
519    fn default() -> Self {
520        Self::new()
521    }
522}
523
524impl u32string {
525    pub fn new() -> Self {
526        u32string_new()
527    }
528
529    pub fn with_buf(b: &[u32]) -> Self {
530        unsafe { u32string_with_buf(b.as_ptr(), b.len()) }
531    }
532}
533
534impl Default for u32string {
535    fn default() -> Self {
536        Self::new()
537    }
538}