sudachi/plugin/path_rewrite/join_numeric/numeric_parser/
string_number.rs

1/*
2 * Copyright (c) 2021-2024 Works Applications Co., Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#[derive(Debug)]
18pub struct StringNumber {
19    significand: String,
20    scale: usize,
21    point: i32,
22    pub is_all_zero: bool,
23}
24
25impl StringNumber {
26    pub fn new() -> StringNumber {
27        StringNumber {
28            significand: String::new(),
29            scale: 0,
30            point: -1,
31            is_all_zero: true,
32        }
33    }
34
35    pub fn clear(&mut self) {
36        self.significand.clear();
37        self.scale = 0;
38        self.point = -1;
39        self.is_all_zero = true;
40    }
41
42    pub fn append(&mut self, i: i32) {
43        if i != 0 {
44            self.is_all_zero = false;
45        }
46        self.significand += &i.to_string();
47    }
48
49    pub fn shift_scale(&mut self, i: i32) {
50        if self.is_zero() {
51            self.significand += "1";
52        }
53        self.scale = (self.scale as i32 + i) as usize;
54    }
55
56    pub fn add(&mut self, number: &mut StringNumber) -> bool {
57        if number.is_zero() {
58            return true;
59        }
60
61        if self.is_zero() {
62            self.significand += &number.significand;
63            self.scale = number.scale;
64            self.point = number.point;
65            return true;
66        }
67
68        self.normalize_scale();
69        let length = number.int_length();
70        if self.scale >= length {
71            self.fill_zero(self.scale - length);
72            if number.point >= 0 {
73                self.point = self.significand.len() as i32 + number.point;
74            }
75            self.significand += &number.significand;
76            self.scale = number.scale;
77            return true;
78        }
79
80        false
81    }
82
83    pub fn set_point(&mut self) -> bool {
84        if self.scale == 0 && self.point < 0 {
85            self.point = self.significand.len() as i32;
86            return true;
87        }
88        false
89    }
90
91    fn int_length(&mut self) -> usize {
92        self.normalize_scale();
93        if self.point >= 0 {
94            return self.point as usize;
95        }
96        self.significand.len() + self.scale
97    }
98
99    pub fn is_zero(&self) -> bool {
100        self.significand.is_empty()
101    }
102
103    pub fn to_string(&mut self) -> String {
104        if self.is_zero() {
105            return "0".to_owned();
106        }
107
108        self.normalize_scale();
109        if self.scale > 0 {
110            self.fill_zero(self.scale);
111        } else if self.point >= 0 {
112            self.significand.insert(self.point as usize, '.');
113            if self.point == 0 {
114                self.significand.insert(0, '0');
115            }
116            let n_last_zero = self
117                .significand
118                .chars()
119                .rev()
120                .take_while(|c| *c == '0')
121                .count();
122            self.significand
123                .truncate(self.significand.len() - n_last_zero);
124            if self.significand.ends_with('.') {
125                self.significand.truncate(self.significand.len() - 1);
126            }
127        }
128
129        self.significand.clone()
130    }
131
132    fn normalize_scale(&mut self) {
133        if self.point >= 0 {
134            let n_scale = self.significand.len() as i32 - self.point;
135            if n_scale > self.scale as i32 {
136                self.point += self.scale as i32;
137                self.scale = 0;
138            } else {
139                self.scale -= n_scale as usize;
140                self.point = -1;
141            }
142        }
143    }
144
145    fn fill_zero(&mut self, length: usize) {
146        self.significand += &"0".repeat(length);
147    }
148}