OpenStructure
Loading...
Searching...
No Matches
formatted_line.hh
Go to the documentation of this file.
1#ifndef OST_IO_FORMATTED_LINE_HH
2#define OST_IO_FORMATTED_LINE_HH
3
4#ifdef _MSC_VER
5#define snprintf _snprintf
6#endif
7
8#include <cstdio>
9
10#include <ost/string_ref.hh>
11
12/*
13 Author: Marco Biasini
14 */
15
16namespace ost { namespace io {
17
18namespace fmt {
19
20struct LPadded : public StringRef {
21 LPadded(const char* s, size_t l):
22 StringRef(s, l)
23 { }
24
25 explicit LPadded(const String& s): StringRef(s.data(), s.size())
26 { }
27
28 explicit LPadded(const char* s): StringRef(s, strlen(s))
29 { }
30};
31
32struct RPadded : public StringRef {
33 RPadded(const char* s, size_t l):
34 StringRef(s, l)
35 { }
36
37 explicit RPadded(const String& s): StringRef(s.data(), s.size())
38 { }
39
40 explicit RPadded(const char* s): StringRef(s, strlen(s))
41 { }
42};
43
44
45struct LPaddedInt {
46 LPaddedInt(int val) {
47 size_t curr=0;
48 bool minus=val<0;
49 val=std::abs(val);
50 if (minus) {
51 data[curr]='-';
52 ++curr;
53 }
54 do {
55 int m=val%10;
56 data[curr]='0'+m;
57 ++curr;
58 val/=10;
59 } while(val);
60 // swap
61 for (size_t i=0, e=(curr-int(minus))/2; i<e; ++i) {
62 std::swap(data[int(minus)+i], data[curr-i-1]);
63 }
64 data[curr]='\0';
65 len=curr;
66 }
67 char data[20];
68 size_t len;
69};
70
71// BIG FAT WARNING: Before using this class to output floats with lots of
72// digits, make sure you indeed get the result you want. The function has
73// not been tested enough for numerical stability.
75 LPaddedFloat(Real val, int prec)
76 {
77 switch(prec){
78 case 0:
79 len = snprintf(data, sizeof(data), "%.0f", val);
80 break;
81 case 1:
82 len = snprintf(data, sizeof(data), "%.1f", val);
83 break;
84 case 2:
85 len = snprintf(data, sizeof(data), "%.2f", val);
86 break;
87 case 3:
88 len = snprintf(data, sizeof(data), "%.3f", val);
89 break;
90 default:
91 Real rounded_val=round(val*pow(Real(10), prec))*pow(Real(0.1), prec);
92 size_t curr=0;
93 bool minus=rounded_val<0;
94 rounded_val=std::abs(rounded_val);
95 int int_val=int(rounded_val);
96 if (minus) {
97 data[curr]='-';
98 ++curr;
99 }
100 do {
101 int m=int_val%10;
102 data[curr]='0'+m;
103 ++curr;
104 int_val/=10;
105 } while(int_val);
106 // swap
107 for (size_t i=0, e=(curr-int(minus))/2; i<e; ++i) {
108 std::swap(data[int(minus)+i], data[curr-i-1]);
109 }
110 data[curr]='\0';
111 len=curr;
112 if (prec==0) {
113 return;
114 }
115 data[curr]='.';
116 curr++;
117 rounded_val-=int(rounded_val);
118 while(prec>0) {
119 rounded_val*=10;
120 int m=int(rounded_val);
121 rounded_val-=int(rounded_val);
122 data[curr]='0'+m;
123 curr++;
124 --prec;
125 }
126 data[curr]='\0';
127 len=curr;
128 }
129 }
130 char data[20];
131 size_t len;
132};
133
134
135
136}
137
139public:
140 LineSlice(char* data, size_t l): data_(data), len_(l)
141 {
142 }
143
145 {
146 assert(str.length()==len_);
147 memcpy(data_, str.data(), str.size());
148 return *this;
149 }
150
152 {
153 assert(str.size()<=len_);
154 memcpy(data_+len_-str.size(), str.data(), str.size());
155 return *this;
156 }
157
159 {
160 assert(str.size()<=len_);
161 memcpy(data_, str.data(), str.size());
162 return *this;
163 }
164
166 {
167 assert(i.len<=len_);
168 memcpy(data_+len_-i.len, i.data, i.len);
169 return *this;
170 }
171
173 {
174 assert(f.len<=len_);
175 memcpy(data_+len_-f.len, f.data, f.len);
176 return *this;
177 }
178 void Clear()
179 {
180 memset(data_, ' ', len_);
181 }
182private:
183 char* data_;
184 size_t len_;
185};
186
188public:
189 FormattedLine(size_t width):
190 data_(new char[width]), len_(width)
191 {
192 this->Clear();
193 }
194
195 void Clear()
196 {
197 memset(data_, ' ', len_);
198 }
199 ~FormattedLine() { delete[] data_; }
200
201 LineSlice operator()(int start, int len)
202 {
203 assert(start>=0 && start+len<=static_cast<int>(len_));
204 return LineSlice(data_+start, len);
205 }
206
207 const char* Data() const { return data_; }
208
209 size_t GetWidth() const { return len_; }
210
211 char operator[](size_t index) const
212 {
213 assert(index<len_);
214 return data_[index];
215 }
216
217 char& operator[](size_t index)
218 {
219 assert(index<len_);
220 return data_[index];
221 }
222private:
223 FormattedLine& operator=(const FormattedLine& rhs);
224 FormattedLine(const FormattedLine& rhs);
225 char* data_;
226 size_t len_;
227};
228
229inline std::ostream& operator<<(std::ostream& stream, const FormattedLine& line)
230{
231 stream.write(line.Data(), line.GetWidth());
232 stream << std::endl;
233 return stream;
234}
235
236
237}}
238
239#endif
convenient datatype for referencing character data
Definition string_ref.hh:39
size_t size() const
Definition string_ref.hh:54
size_t length() const
Definition string_ref.hh:55
const char * data() const
Definition string_ref.hh:52
const char * Data() const
char operator[](size_t index) const
LineSlice operator()(int start, int len)
char & operator[](size_t index)
LineSlice & operator=(const fmt::RPadded &str)
LineSlice(char *data, size_t l)
LineSlice & operator=(const fmt::LPaddedFloat &f)
LineSlice & operator=(const fmt::LPaddedInt &i)
LineSlice & operator=(const StringRef &str)
LineSlice & operator=(const fmt::LPadded &str)
float Real
Definition base.hh:44
std::string String
Definition base.hh:54
std::ostream & operator<<(std::ostream &stream, const FormattedLine &line)
Definition base.dox:1
LPaddedFloat(Real val, int prec)
LPadded(const String &s)
LPadded(const char *s, size_t l)
RPadded(const String &s)
RPadded(const char *s, size_t l)