source: mainline/uspace/lib/cpp/include/__bits/locale/num_put.hpp@ b57a3ee

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b57a3ee was b57a3ee, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: refactored the library layout, everything from the impl directory was moved to the bits directory for the sake of consistency, updated copyright notices and include guards

  • Property mode set to 100644
File size: 13.0 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_BITS_LOCALE_NUM_PUT
30#define LIBCPP_BITS_LOCALE_NUM_PUT
31
32#include <__bits/locale/locale.hpp>
33#include <__bits/locale/numpunct.hpp>
34#include <ios>
35#include <iterator>
36
37namespace std
38{
39 /**
40 * 22.4.2.2, class template num_put:
41 */
42
43 template<class Char, class OutputIterator = ostreambuf_iterator<Char>>
44 class num_put: public locale::facet
45 {
46 public:
47 using char_type = Char;
48 using iter_type = OutputIterator;
49
50 explicit num_put(size_t refs = 0)
51 { /* DUMMY BODY */ }
52
53 iter_type put(iter_type it, ios_base& base, char_type fill, bool v) const
54 {
55 return do_put(it, base, fill, v);
56 }
57
58 iter_type put(iter_type it, ios_base& base, char_type fill, long v) const
59 {
60 return do_put(it, base, fill, v);
61 }
62
63 iter_type put(iter_type it, ios_base& base, char_type fill, long long v) const
64 {
65 return do_put(it, base, fill, v);
66 }
67
68 iter_type put(iter_type it, ios_base& base, char_type fill, unsigned long v) const
69 {
70 return do_put(it, base, fill, v);
71 }
72
73 iter_type put(iter_type it, ios_base& base, char_type fill, unsigned long long v) const
74 {
75 return do_put(it, base, fill, v);
76 }
77
78 iter_type put(iter_type it, ios_base& base, char_type fill, double v) const
79 {
80 return do_put(it, base, fill, v);
81 }
82
83 iter_type put(iter_type it, ios_base& base, char_type fill, long double v) const
84 {
85 return do_put(it, base, fill, v);
86 }
87
88 iter_type put(iter_type it, ios_base& base, char_type fill, const void* v) const
89 {
90 return do_put(it, base, fill, v);
91 }
92
93 ~num_put()
94 { /* DUMMY BODY */ }
95
96 protected:
97 iter_type do_put(iter_type it, ios_base& base, char_type fill, bool v) const
98 {
99 auto loc = base.getloc();
100
101 if ((base.flags() & ios_base::boolalpha) == 0)
102 return do_put(it, base, fill, (long)v);
103 else
104 {
105 auto s = v ? use_facet<numpunct<char_type>>(loc).truename()
106 : use_facet<numpunct<char_type>>(loc).falsename();
107 for (auto c: s)
108 *it++ = c;
109 }
110
111 return it;
112 }
113
114 iter_type do_put(iter_type it, ios_base& base, char_type fill, long v) const
115 {
116 auto basefield = (base.flags() & ios_base::basefield);
117 auto uppercase = (base.flags() & ios_base::uppercase);
118
119 int ret{};
120 if (basefield == ios_base::oct)
121 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%lo", v);
122 else if ((basefield == ios_base::hex) && !uppercase)
123 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%lx", v);
124 else if (basefield == ios_base::hex)
125 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%lX", v);
126 else
127 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%ld", v);
128
129 return put_adjusted_buffer_(it, base, fill, ret);
130 }
131
132 iter_type do_put(iter_type it, ios_base& base, char_type fill, long long v) const
133 {
134 auto basefield = (base.flags() & ios_base::basefield);
135 auto uppercase = (base.flags() & ios_base::uppercase);
136
137 int ret{};
138 if (basefield == ios_base::oct)
139 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%llo", v);
140 else if ((basefield == ios_base::hex) && !uppercase)
141 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%llx", v);
142 else if (basefield == ios_base::hex)
143 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%llX", v);
144 else
145 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%lld", v);
146
147 return put_adjusted_buffer_(it, base, fill, ret);
148 }
149
150 iter_type do_put(iter_type it, ios_base& base, char_type fill, unsigned long v) const
151 {
152 auto basefield = (base.flags() & ios_base::basefield);
153 auto uppercase = (base.flags() & ios_base::uppercase);
154
155 int ret{};
156 if (basefield == ios_base::oct)
157 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%lo", v);
158 else if ((basefield == ios_base::hex) && !uppercase)
159 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%lx", v);
160 else if (basefield == ios_base::hex)
161 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%lX", v);
162 else
163 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%lu", v);
164
165 return put_adjusted_buffer_(it, base, fill, ret);
166 }
167
168 iter_type do_put(iter_type it, ios_base& base, char_type fill, unsigned long long v) const
169 {
170 auto basefield = (base.flags() & ios_base::basefield);
171 auto uppercase = (base.flags() & ios_base::uppercase);
172
173 // TODO: showbase
174 int ret{};
175 if (basefield == ios_base::oct)
176 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%llo", v);
177 else if ((basefield == ios_base::hex) && !uppercase)
178 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%llx", v);
179 else if (basefield == ios_base::hex)
180 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%llX", v);
181 else
182 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%llu", v);
183
184 return put_adjusted_buffer_(it, base, fill, ret);
185 }
186
187 iter_type do_put(iter_type it, ios_base& base, char_type fill, double v) const
188 {
189 auto floatfield = (base.flags() & ios_base::floatfield);
190 auto uppercase = (base.flags() & ios_base::uppercase);
191
192 // TODO: showbase
193 // TODO: precision
194 int ret{};
195 if (floatfield == ios_base::fixed)
196 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%f", v);
197 else if (floatfield == ios_base::scientific && !uppercase)
198 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%e", v);
199 else if (floatfield == ios_base::scientific)
200 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%E", v);
201 else if (floatfield == (ios_base::fixed | ios_base::scientific) && !uppercase)
202 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%a", v);
203 else if (floatfield == (ios_base::fixed | ios_base::scientific))
204 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%A", v);
205 else if (!uppercase)
206 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%g", v);
207 else
208 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%G", v);
209
210 return put_adjusted_buffer_(it, base, fill, ret);
211 }
212
213 iter_type do_put(iter_type it, ios_base& base, char_type fill, long double v) const
214 {
215 /**
216 * Note: Long double is not support at the moment in snprintf.
217 */
218 auto floatfield = (base.flags() & ios_base::floatfield);
219 auto uppercase = (base.flags() & ios_base::uppercase);
220
221 // TODO: showbase
222 // TODO: precision
223 int ret{};
224 if (floatfield == ios_base::fixed)
225 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%Lf", v);
226 else if (floatfield == ios_base::scientific && !uppercase)
227 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%Le", v);
228 else if (floatfield == ios_base::scientific)
229 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%LE", v);
230 else if (floatfield == (ios_base::fixed | ios_base::scientific) && !uppercase)
231 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%La", v);
232 else if (floatfield == (ios_base::fixed | ios_base::scientific))
233 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%LA", v);
234 else if (!uppercase)
235 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%Lg", v);
236 else
237 ret = snprintf(base.buffer_, ios_base::buffer_size_, "%LG", v);
238
239 return put_adjusted_buffer_(it, base, fill, ret);
240 }
241
242 iter_type do_put(iter_type it, ios_base& base, char_type fill, const void* v) const
243 {
244 int ret = snprintf(base.buffer_, ios_base::buffer_size_, "%p", v);
245
246 return put_adjusted_buffer_(it, base, fill, ret);
247 }
248
249 private:
250 iter_type put_adjusted_buffer_(iter_type it, ios_base& base, char_type fill, size_t size) const
251 {
252 auto adjustfield = (base.flags() & ios_base::adjustfield);
253
254 size_t to_fill{};
255 size_t width = static_cast<size_t>(base.width());
256
257 if (base.width() > 0 && size < width)
258 to_fill = width - size;
259
260 if (to_fill > 0)
261 {
262 if (adjustfield == ios_base::left)
263 {
264 it = put_buffer_(it, base, fill, 0, size);
265 for (size_t i = 0; i < to_fill; ++i)
266 *it++ = fill;
267 }
268 else if (adjustfield == ios_base::right)
269 {
270 for (size_t i = 0; i < to_fill; ++i)
271 *it++ = fill;
272 it = put_buffer_(it, base, fill, 0, size);
273 }
274 else if (adjustfield == ios_base::internal)
275 {
276 // TODO: pad after - or 0x/0X
277 }
278 else
279 {
280 for (size_t i = 0; i < to_fill; ++i)
281 *it++ = fill;
282 it = put_buffer_(it, base, fill, 0, size);
283 }
284 }
285 else
286 it = put_buffer_(it, base, fill, 0, size);
287 base.width(0);
288
289 return it;
290 }
291
292 iter_type put_buffer_(iter_type it, ios_base& base, char_type fill, size_t start, size_t size) const
293 {
294 const auto& loc = base.getloc();
295 const auto& ct = use_facet<ctype<char_type>>(loc);
296 const auto& punct = use_facet<numpunct<char_type>>(loc);
297
298 for (size_t i = start; i < size; ++i)
299 {
300 if (base.buffer_[i] == '.')
301 *it++ = punct.decimal_point();
302 else
303 *it++ = ct.widen(base.buffer_[i]);
304 // TODO: Should do grouping & thousands_sep, but that's a low
305 // priority for now.
306 }
307
308 return it;
309 }
310 };
311}
312
313#endif
Note: See TracBrowser for help on using the repository browser.