OpenStructure
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 
16 namespace ost { namespace io {
17 
18 namespace fmt {
19 
20 struct 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 
32 struct 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 
45 struct 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.
74 struct LPaddedFloat {
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 
138 class LineSlice {
139 public:
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  }
182 private:
183  char* data_;
184  size_t len_;
185 };
186 
188 public:
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  }
222 private:
223  FormattedLine& operator=(const FormattedLine& rhs);
224  FormattedLine(const FormattedLine& rhs);
225  char* data_;
226  size_t len_;
227 };
228 
229 inline 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
const char * data() const
Definition: string_ref.hh:52
size_t length() const
Definition: string_ref.hh:55
FormattedLine(size_t width)
char operator[](size_t index) const
LineSlice operator()(int start, int len)
char & operator[](size_t index)
const char * Data() const
LineSlice & operator=(const fmt::LPaddedInt &i)
LineSlice & operator=(const StringRef &str)
LineSlice(char *data, size_t l)
LineSlice & operator=(const fmt::RPadded &str)
LineSlice & operator=(const fmt::LPadded &str)
LineSlice & operator=(const fmt::LPaddedFloat &f)
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 char *s)
LPadded(const String &s)
LPadded(const char *s, size_t l)
RPadded(const String &s)
RPadded(const char *s)
RPadded(const char *s, size_t l)