stringbox.cpp
1 #include <iterator>
2 #include <sstream>
3 #include <algorithm>
4 #include <symengine/printers/stringbox.h>
5 
6 // Macro to let string literals be unicode const char in all C++ standards
7 // Otherwise u8"" would be char8_t in C++20
8 #define U8(x) reinterpret_cast<const char *>(u8##x)
9 
10 namespace SymEngine
11 {
12 
13 void StringBox::pad_lines(std::size_t new_width)
14 {
15  auto diff = new_width - width_;
16  auto half = diff / 2;
17  auto odd = diff % 2;
18  for (std::string &line : lines_) {
19  line.insert(0, std::string(half + odd, ' '));
20  if (half > 0) {
21  line.append(std::string(half, ' '));
22  }
23  }
24 }
25 
26 void StringBox::add_below(StringBox &other)
27 {
28  if (other.width_ > width_) {
29  pad_lines(other.width_);
30  width_ = other.width_;
31  } else if (width_ > other.width_) {
32  other.pad_lines(width_);
33  other.width_ = width_;
34  }
35  lines_.insert(lines_.end(), other.lines_.begin(), other.lines_.end());
36 }
37 
38 void StringBox::add_below_unicode_line(StringBox &other)
39 {
40  auto new_width = std::max(width_, other.width_);
41  std::string bar;
42  for (unsigned i = 0; i < new_width; i++) {
43  bar.append(U8("\u2015"));
44  }
45  StringBox barbox(bar, new_width);
46  add_below(barbox);
47  add_below(other);
48 }
49 
50 void StringBox::add_right(StringBox &other)
51 {
52  StringBox *smaller;
53  auto this_size = lines_.size();
54  auto other_size = other.lines_.size();
55  if (other_size > this_size) {
56  smaller = this;
57  } else {
58  smaller = &other;
59  }
60  auto diff
61  = std::max(other_size, this_size) - std::min(other_size, this_size);
62  auto half = diff / 2;
63  auto odd = diff % 2;
64  std::string pad(smaller->width_, ' ');
65  for (unsigned i = 0; i < half; i++) {
66  smaller->lines_.push_back(pad);
67  smaller->lines_.insert(smaller->lines_.begin(), pad);
68  }
69  if (odd == 1) {
70  smaller->lines_.insert(lines_.begin(), pad);
71  }
72  for (unsigned i = 0; i < lines_.size(); i++) {
73  lines_[i].append(other.lines_[i]);
74  }
75  width_ += other.width_;
76 }
77 
78 void StringBox::add_power(StringBox &other)
79 {
80  for (std::string &line : lines_) {
81  line.append(std::string(other.width_, ' '));
82  }
83  for (std::string &line : other.lines_) {
84  lines_.insert(lines_.begin(), std::string(width_, ' ') + line);
85  }
86  width_ += other.width_;
87 }
88 
89 void StringBox::enclose_abs()
90 {
91  for (std::string &line : lines_) {
92  line.insert(0, U8("\u2502"));
93  line.append(U8("\u2502"));
94  }
95  width_ += 2;
96 }
97 
98 void StringBox::enclose_parens()
99 {
100  add_left_parens();
101  add_right_parens();
102 }
103 
104 void StringBox::enclose_sqbrackets()
105 {
106  add_left_sqbracket();
107  add_right_sqbracket();
108 }
109 
110 void StringBox::enclose_curlies()
111 {
112  add_left_curly();
113  add_right_curly();
114 }
115 
116 void StringBox::add_left_parens()
117 {
118  if (lines_.size() == 1) {
119  lines_[0].insert(0, "(");
120  } else {
121  lines_[0].insert(0, U8("\u239B"));
122  lines_.back().insert(0, U8("\u239D"));
123  for (unsigned i = 1; i < lines_.size() - 1; i++) {
124  lines_[i].insert(0, U8("\u239C"));
125  }
126  }
127  width_ += 1;
128 }
129 
130 void StringBox::add_right_parens()
131 {
132  if (lines_.size() == 1) {
133  lines_[0].append(")");
134  } else {
135  lines_[0].append(U8("\u239E"));
136  lines_.back().append(U8("\u23A0"));
137  for (unsigned i = 1; i < lines_.size() - 1; i++) {
138  lines_[i].append(U8("\u239F"));
139  }
140  }
141  width_ += 1;
142 }
143 
144 void StringBox::add_left_sqbracket()
145 {
146  if (lines_.size() == 1) {
147  lines_[0].insert(0, "[");
148  } else {
149  lines_[0].insert(0, U8("\u23A1"));
150  lines_.back().insert(0, U8("\u23A3"));
151  for (unsigned i = 1; i < lines_.size() - 1; i++) {
152  lines_[i].insert(0, U8("\u23A2"));
153  }
154  }
155  width_ += 1;
156 }
157 
158 void StringBox::add_left_curly()
159 {
160  if (lines_.size() == 1) {
161  lines_[0].insert(0, "{");
162  } else if (lines_.size() == 2) {
163  lines_[0].insert(0, U8("\u23A7"));
164  lines_[1].insert(0, U8("\u23A9"));
165  lines_.insert(lines_.begin() + 1,
166  U8("\u23A8") + std::string(width_, ' '));
167  } else {
168  lines_[0].insert(0, U8("\u23A7"));
169  lines_.back().insert(0, U8("\u23A9"));
170  std::size_t mid = lines_.size() / 2;
171  for (std::size_t i = 1; i < lines_.size() - 1; i++) {
172  if (i == mid) {
173  lines_[i].insert(0, U8("\u23A8"));
174  } else {
175  lines_[i].insert(0, U8("\u23AA"));
176  }
177  }
178  }
179  width_ += 1;
180 }
181 
182 void StringBox::add_right_curly()
183 {
184  if (lines_.size() == 1) {
185  lines_[0].append("}");
186  } else if (lines_.size() == 2) {
187  lines_[0].append(U8("\u23AB"));
188  lines_[1].append(U8("\u23AD"));
189  lines_.insert(lines_.begin() + 1,
190  std::string(width_, ' ') + U8("\u23AC"));
191  } else {
192  lines_[0].append(U8("\u23AB"));
193  lines_.back().append(U8("\u23AD"));
194  std::size_t mid = lines_.size() / 2;
195  for (std::size_t i = 1; i < lines_.size() - 1; i++) {
196  if (i == mid) {
197  lines_[i].append(U8("\u23AC"));
198  } else {
199  lines_[i].append(U8("\u23AA"));
200  }
201  }
202  }
203  width_ += 1;
204 }
205 
206 void StringBox::add_right_sqbracket()
207 {
208  if (lines_.size() == 1) {
209  lines_[0].append("]");
210  } else {
211  lines_[0].append(U8("\u23A4"));
212  lines_.back().append(U8("\u23A5"));
213  for (unsigned i = 1; i < lines_.size() - 1; i++) {
214  lines_[i].append(U8("\u23A6"));
215  }
216  }
217  width_ += 1;
218 }
219 
220 void StringBox::enclose_floor()
221 {
222  lines_.back().insert(0, U8("\u230A"));
223  lines_.back().append(U8("\u230B"));
224  for (unsigned i = 0; i < lines_.size() - 1; i++) {
225  lines_[i].insert(0, U8("\u2502"));
226  lines_[i].append(U8("\u2502"));
227  }
228  width_ += 2;
229 }
230 
231 void StringBox::enclose_ceiling()
232 {
233  lines_[0].insert(0, U8("\u2308"));
234  lines_[0].append(U8("\u2309"));
235  for (unsigned i = 1; i < lines_.size(); i++) {
236  lines_[i].insert(0, U8("\u2502"));
237  lines_[i].append(U8("\u2502"));
238  }
239  width_ += 2;
240 }
241 
242 void StringBox::enclose_sqrt()
243 {
244  std::size_t len = lines_.size();
245  std::size_t i = len;
246  for (std::string &line : lines_) {
247  if (i == 1) {
248  line.insert(0, U8("\u2572\u2571") + std::string(len - i, ' '));
249  } else {
250  line.insert(0, std::string(i, ' ') + U8("\u2571")
251  + std::string(len - i, ' '));
252  }
253  i--;
254  }
255  lines_.insert(lines_.begin(),
256  std::string(len + 1, ' ') + std::string(width_, '_'));
257  width_ += len + 1;
258 }
259 
260 std::string StringBox::get_string() const
261 {
263  auto b = begin(lines_), e = end(lines_);
264 
265  if (b != e) {
267  b = prev(e);
268  }
269  if (b != e) {
270  os << *b;
271  }
272 
273  return os.str();
274 }
275 
276 }; // namespace SymEngine
T append(T... args)
T begin(T... args)
T copy(T... args)
T end(T... args)
T insert(T... args)
T max(T... args)
T min(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19
T prev(T... args)
T str(T... args)