PrettyPrint.hpp
Go to the documentation of this file.
1 // @formatter:off
2 //
3 // Balau core C++ library
4 //
5 // Copyright (C) 2008 Bora Software (contact@borasoftware.com)
6 //
7 // Licensed under the Boost Software License - Version 1.0 - August 17th, 2003.
8 // See the LICENSE file for the full license text.
9 //
10 
16 
17 #ifndef COM_BORA_SOFTWARE__BALAU_UTIL__PRETTY_PRINT
18 #define COM_BORA_SOFTWARE__BALAU_UTIL__PRETTY_PRINT
19 
21 #include <Balau/Util/DateTime.hpp>
22 
23 namespace Balau::Util {
24 
28 struct PrettyPrint final {
36  template <typename T> static std::string fixed(const T & value, const size_t decimalPlaces) {
37  std::ostringstream builder;
38  builder.precision(decimalPlaces);
39  builder << std::fixed << value;
40  return builder.str();
41  }
42 
50  template <typename T> static std::string scientific(const T & value, const size_t decimalPlaces) {
51  std::ostringstream builder;
52  builder.precision(decimalPlaces);
53  builder << std::scientific << value;
54  return builder.str();
55  }
56 
64  template <typename T> static std::string metricPrefix(const T & value, size_t decimalPlaces) {
65  auto prefix = (int) std::floor(std::log10(value) / std::log10(1000.0));
66 
67  if (prefix > 6) {
68  prefix = 6;
69  } else if (prefix < -6) {
70  prefix = -6;
71  }
72 
73  const char * prefixChar = PREFIXES[prefix + 6];
74  const long double multiplier = std::pow(1000.0, (long double) -prefix);
75  return fixed((long double) value * multiplier, decimalPlaces) + prefixChar;
76  }
77 
87  template <typename T> static std::string binaryPrefix(const T & value, const size_t decimalPlaces) {
88  auto prefix = (int) std::floor(std::log10((long double) value) / std::log10((long double) 1024.0));
89 
90  if (prefix > 6) {
91  prefix = 6;
92  } else if (prefix < -6) {
93  prefix = -6;
94  }
95 
96  const char * prefixChar = PREFIXES[prefix + 6];
97  const long double multiplier = std::pow(1024.0, (long double) -prefix);
98  return fixed((long double) value * multiplier, decimalPlaces) + prefixChar;
99  }
100 
104  static std::string byteValue(const size_t bytes, const size_t decimalPlaces = 0) {
105  return binaryPrefix(bytes, decimalPlaces) + "B";
106  }
107 
114  template <typename Rep, typename Period> static
115  std::string duration(std::chrono::duration<Rep, Period> d, const size_t decimalPlaces = 0) {
116  using Days = std::chrono::duration<int, std::ratio<86400>>;
117 
118  long double totalSeconds = (long double) d.count() / (long double) Period::den * (long double) Period::num;
119 
120  std::ostringstream builder;
121 
122  if (totalSeconds < 0.0) {
123  builder << "-";
124  totalSeconds = -totalSeconds;
125  }
126 
127  const long double fraction = totalSeconds - (long double) (unsigned long long) totalSeconds;
128 
129  if (totalSeconds == 0.0) {
130  return "0s";
131  } else if (totalSeconds < 60.0) {
132  builder << metricPrefix(totalSeconds, decimalPlaces) << "s";
133  return builder.str();
134  } else if (totalSeconds < 60.0 * 60.0) { // print minutes::seconds.fraction
135  builder.fill('0');
136  auto minutes = std::chrono::duration_cast<std::chrono::minutes>(d);
137  d -= minutes;
138  auto seconds = std::chrono::duration_cast<std::chrono::seconds>(d);
139  builder << std::setw(2) << minutes.count() << "m"
140  << std::setw(2) << seconds.count();
141  } else if (totalSeconds < 60.0 * 60.0 * 24.0) { // print hours::minutes::seconds.fraction
142  builder.fill('0');
143  auto hours = std::chrono::duration_cast<std::chrono::hours>(d);
144  d -= hours;
145  auto minutes = std::chrono::duration_cast<std::chrono::minutes>(d);
146  d -= minutes;
147  auto seconds = std::chrono::duration_cast<std::chrono::seconds>(d);
148  builder << std::setw(2) << hours.count() << "h"
149  << std::setw(2) << minutes.count() << "m"
150  << std::setw(2) << seconds.count();
151  } else { // print days::hours::minutes::seconds.fraction
152  builder.fill('0');
153  auto days = std::chrono::duration_cast<Days>(d);
154  d -= days;
155  auto hours = std::chrono::duration_cast<std::chrono::hours>(d);
156  d -= hours;
157  auto minutes = std::chrono::duration_cast<std::chrono::minutes>(d);
158  d -= minutes;
159  auto seconds = std::chrono::duration_cast<std::chrono::seconds>(d);
160  builder << std::setw(2) << days.count() << "d"
161  << std::setw(2) << hours.count() << "h"
162  << std::setw(2) << minutes.count() << "m"
163  << std::setw(2) << seconds.count();
164  }
165 
166  if (decimalPlaces != 0 && fraction != 0) {
167  builder << fixed(fraction, decimalPlaces).substr(1);
168  }
169 
170  builder << "s";
171 
172  return builder.str();
173  }
174 
183  template <typename T>
184  static std::string printHexBytes(const T & value, size_t lineLength = 0, size_t groupSize = 0) {
185  return printHexBytes((const char *) & value, sizeof(T), lineLength, groupSize);
186  }
187 
196  static std::string printHexBytes(const char * ptr, size_t byteCount, size_t lineLength = 0, size_t groupSize = 0) {
197  std::ostringstream builder;
198  const size_t groupsPerLine = calculateGroupsPerLine(lineLength, groupSize);
199 
200  if (groupsPerLine == 0) {
201  // Return single line.
202 
203  for (size_t m = 0; m < byteCount; m++) {
204  builder << std::right << std::setw(2) << std::hex << std::setfill('0') << (int) ptr[m];
205  }
206 
207  return builder.str();
208  }
209 
210  size_t index = 0;
211 
212  // groupsPerLine > 0
213 
214  while (index < byteCount) {
215  for (size_t m = 0; m < groupsPerLine - 1; m++) {
216  for (size_t n = 0; n < groupSize; n++) {
217  if (index == byteCount) {
218  return builder.str();
219  }
220 
221  builder << std::right << std::setw(2) << std::hex << std::setfill('0') << (int) ptr[index++];
222  }
223 
224  builder << " ";
225  }
226 
227  for (size_t n = 0; n < groupSize; n++) {
228  if (index == byteCount) {
229  return builder.str();
230  }
231 
232  builder << std::right << std::setw(2) << std::hex << std::setfill('0') << (int) ptr[index++];
233  }
234 
235  builder << "\n";
236  }
237 
238  return builder.str();
239  }
240 
242 
243  PrettyPrint() = delete;
244  PrettyPrint(const PrettyPrint &) = delete;
245  PrettyPrint & operator = (const PrettyPrint &) = delete;
246 
248 
249  private: static size_t calculateGroupsPerLine(size_t lineLength, size_t groupSize) {
250  const size_t groupCharCount = groupSize * 2;
251 
252  if (groupCharCount > lineLength) {
253  return 0;
254  }
255 
256  size_t groupCount = 1;
257 
258  while (true) {
259  const size_t size = groupCharCount * (groupCount + 1) + (groupCount + 1) - 1;
260 
261  if (size > lineLength) {
262  return groupCount;
263  }
264 
265  ++groupCount;
266  }
267  }
268 
269  private: static const char * PREFIXES[];
270 };
271 
272 } // namespace Balau::Util
273 
274 #endif // COM_BORA_SOFTWARE__BALAU_UTIL__PRETTY_PRINT
static std::string printHexBytes(const T &value, size_t lineLength=0, size_t groupSize=0)
Print the value as bytes in hexadecimal.
Definition: PrettyPrint.hpp:184
Utility functions.
static std::string binaryPrefix(const T &value, const size_t decimalPlaces)
Print the value with a binary prefix.
Definition: PrettyPrint.hpp:87
Balau exceptions for containers.
static std::string byteValue(const size_t bytes, const size_t decimalPlaces=0)
Returns a string containing the supplied byte value in terms of B/KB/MB/GB etc.
Definition: PrettyPrint.hpp:104
static std::string metricPrefix(const T &value, size_t decimalPlaces)
Print the value with a metric prefix.
Definition: PrettyPrint.hpp:64
Utilities for printing numeric values in different formats.
Definition: PrettyPrint.hpp:28
static std::string scientific(const T &value, const size_t decimalPlaces)
Print the value in scientific notation.
Definition: PrettyPrint.hpp:50
static std::string duration(std::chrono::duration< Rep, Period > d, const size_t decimalPlaces=0)
Pretty print the duration.
Definition: PrettyPrint.hpp:115
static std::string fixed(const T &value, const size_t decimalPlaces)
Print the value in fixed notation.
Definition: PrettyPrint.hpp:36
static std::string printHexBytes(const char *ptr, size_t byteCount, size_t lineLength=0, size_t groupSize=0)
Print the bytes in hexadecimal.
Definition: PrettyPrint.hpp:196
Date and time utilities.