Skip to content

Commit 0c397a4

Browse files
authored
Merge pull request #18 from SimonCahill/feat/fix-time-and-byte-values
Fixed time and data sent values; they are now human readable.
2 parents f4f5841 + e553e54 commit 0c397a4

File tree

5 files changed

+281
-175
lines changed

5 files changed

+281
-175
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
cmake_minimum_required(VERSION 3.10)
22

3-
project(endlessh-report VERSION 1.1.2 LANGUAGES CXX DESCRIPTION "A simple report generator for endlessh tarpits.")
3+
project(endlessh-report VERSION 1.2.0 LANGUAGES CXX DESCRIPTION "A simple report generator for endlessh tarpits.")
4+
set(PROJECT_LONG_NAME "Endlessh Report Generator")
45
set(CMAKE_CXX_STANDARD 17)
56
set(CMAKE_CXX_STANDARD_REQUIRED True)
67

include/extensions.hpp

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/**
2+
* @file extensions.hpp
3+
* @author Simon Cahill (simon@simonc.eu)
4+
* @brief Contains useful extension methods that aren't provided by C++ out of the box.
5+
* @version 0.1
6+
* @date 2022-10-15
7+
*
8+
* @copyright Copyright (c) 2022 Simon Cahill
9+
*/
10+
11+
#ifndef ENDLESSH_REPORT_INCLUDE_EXTENSIONS_HPP
12+
#define ENDLESSH_REPORT_INCLUDE_EXTENSIONS_HPP
13+
14+
// stl
15+
#include <chrono>
16+
#include <cmath>
17+
#include <functional>
18+
#include <string>
19+
#include <vector>
20+
21+
// libc
22+
#include <regex.h>
23+
24+
// date
25+
#include <date/date.h>
26+
27+
// fmt
28+
#include <fmt/format.h>
29+
30+
using std::chrono::seconds;
31+
using std::chrono::system_clock;
32+
using std::function;
33+
using std::string;
34+
using std::vector;
35+
36+
/**
37+
* @brief Splits a given string by the passed delimiters in to a vector.
38+
*
39+
* @param str string& The string to split.
40+
* @param delimiters string& A string containing the delimiters to split by (chars).
41+
* @param tokens vector<string>& A vector that will contain the elements.
42+
*
43+
* @return true If tokens were found.
44+
* @return false Otherwise.
45+
*/
46+
inline bool splitString(const string& str, const string& delimiters, vector<string> &tokens) {
47+
// Skip delimiters at beginning.
48+
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
49+
// Find first "non-delimiter".
50+
string::size_type pos = str.find_first_of(delimiters, lastPos);
51+
52+
while (string::npos != pos || string::npos != lastPos) {
53+
// Found a token, add it to the vector.
54+
tokens.push_back(str.substr(lastPos, pos - lastPos));
55+
// Skip delimiters.
56+
lastPos = string::npos == pos ? string::npos : pos + 1;
57+
// Find next "non-delimiter"
58+
pos = str.find_first_of(delimiters, lastPos);
59+
}
60+
61+
return tokens.size() > 0;
62+
}
63+
64+
/**
65+
* @brief Matches a string against a regular expression.
66+
*
67+
* @param haystack The string to compare
68+
* @param needle The expression to compare against
69+
*
70+
* @return true If the string matches the expression
71+
* @return false Otherwise
72+
*/
73+
inline bool regexMatch(const char* haystack, const char* needle) {
74+
int nRet;
75+
regex_t sRegEx;
76+
77+
if (regcomp(&sRegEx, needle, REG_EXTENDED | REG_NOSUB) != 0) {
78+
return false;
79+
}
80+
81+
nRet = regexec(&sRegEx, haystack, (size_t) 0, NULL, 0);
82+
regfree(&sRegEx);
83+
84+
if (nRet != 0) {
85+
return false;
86+
}
87+
88+
return true;
89+
}
90+
91+
/**
92+
* @brief Rounds a given double to the desired amount of decimal places.
93+
*
94+
* @param x The double to round
95+
* @param decimalPlaces The decimal places the double should be rounded to
96+
*
97+
* @return double The resulting double.
98+
*/
99+
inline double roundNumber(const double x, const uint32_t decimalPlaces) {
100+
const double multiplificationFaktor = std::pow(10.0, decimalPlaces);
101+
return std::ceil(x * multiplificationFaktor) / multiplificationFaktor;
102+
}
103+
104+
/**
105+
* @brief Gets the current timestamp as an ISO timestamp, accurate to the nearest second.
106+
*
107+
* @return string A string containing the current timestamp in ISO format.
108+
*/
109+
inline string getCurrentIsoTimestamp() {
110+
auto timeNow = system_clock::now();
111+
return date::format("%FT%TZ", date::floor<seconds>(timeNow));
112+
}
113+
114+
/**
115+
* @brief Converts a number of bytes to a human-readable format, such as KiB, MiB, GiB, ...
116+
*
117+
* @param bytes The bytes to convert.
118+
*
119+
* @return string The human-readable string.
120+
*/
121+
inline string getHumanReadableBytes(const size_t bytes) {
122+
const static size_t ONE_KIB = 1024;
123+
const static size_t ONE_MIB = ONE_KIB * ONE_KIB;
124+
const static size_t ONE_GIB = ONE_MIB * ONE_MIB;
125+
126+
if (bytes > ONE_GIB) { return fmt::format("{0:.2f}GiB", static_cast<double>(bytes / ONE_GIB)); }
127+
if (bytes > ONE_MIB) { return fmt::format("{0:.2f}MiB", static_cast<double>(bytes / ONE_MIB)); }
128+
if (bytes > ONE_KIB) { return fmt::format("{0:.2f}KiB", static_cast<double>(bytes / ONE_KIB)); }
129+
130+
// We're likely less than a KiB
131+
return fmt::format("{0:d}B", bytes);
132+
}
133+
134+
/**
135+
* @brief Converts n seconds into a human-readable form. E.g. 300s would become 5 minutes
136+
*
137+
* @param seconds The amount of seconds to convert.
138+
*
139+
* @return string The human-readable string
140+
*/
141+
inline string getHumanReadableTime(const double seconds) {
142+
if (seconds < 60) { return fmt::format("{0:.0f}s", floor(seconds)); }
143+
144+
string result{};
145+
time_t secondsAsTime = static_cast<time_t>(seconds);
146+
struct tm timeStruct = {0};
147+
gmtime_r(&secondsAsTime, &timeStruct);
148+
149+
if (timeStruct.tm_yday > 0) {
150+
result += fmt::format("{0:d}d ", timeStruct.tm_yday);
151+
} if (timeStruct.tm_hour > 0) {
152+
result += fmt::format("{0:d}h ", timeStruct.tm_hour);
153+
} if (timeStruct.tm_min > 0) {
154+
result += fmt::format("{0:d}m ", timeStruct.tm_min);
155+
} if (timeStruct.tm_sec > 0) {
156+
result += fmt::format("{0:d}s", timeStruct.tm_sec);
157+
}
158+
159+
return result;
160+
}
161+
162+
/**
163+
* @brief Gets a string containing whitespace to centre text
164+
*
165+
* @param totalWidth The total width of the area where the string should be centred
166+
* @param strLength The length of the string to be centre-printed
167+
*
168+
* @return string The spacer string
169+
*/
170+
inline string getSpacerString(const uint32_t totalWidth, const uint32_t strLength) {
171+
return string(totalWidth / 2 - strLength / 2, ' ');
172+
}
173+
174+
/**
175+
* @brief Trims the beginning of a given string.
176+
*
177+
* @param nonTrimmed The non-trimmed string.
178+
* @param trimChar The character to trim off the string. (default: space)
179+
*
180+
* @return The trimmed string.
181+
*/
182+
inline string trimStart(string nonTrimmed, const string& trimChar) {
183+
//nonTrimmed.erase(nonTrimmed.begin(), find_if(nonTrimmed.begin(), nonTrimmed.end(), not1(ptr_fun<int32_t, int32_t>(isspace))));
184+
185+
function<bool(char)> shouldTrimChar = [=](char c) -> bool { return trimChar.size() == 0 ? isspace(c) : trimChar.find(c) != string::npos; };
186+
187+
nonTrimmed.erase(nonTrimmed.begin(), find_if(nonTrimmed.begin(), nonTrimmed.end(), not1(shouldTrimChar)));
188+
189+
return nonTrimmed;
190+
}
191+
192+
/**
193+
* @brief Trims the end of a given string.
194+
* @param nonTrimmed The non-trimmed string.
195+
* @param trimChar The character to trim off the string. (default: space)
196+
*
197+
* @return The trimmed string.
198+
*/
199+
inline string trimEnd(string nonTrimmed, const string& trimChar) {
200+
// nonTrimmed.erase(find_if(nonTrimmed.rbegin(), nonTrimmed.rend(), not1(ptr_fun<int32_t, int32_t>(isspace))).base(), nonTrimmed.end());
201+
202+
function<bool(char)> shouldTrimChar = [=](char c) -> bool { return trimChar.size() == 0 ? isspace(c) : trimChar.find(c) != string::npos; };
203+
nonTrimmed.erase(find_if(nonTrimmed.rbegin(), nonTrimmed.rend(), not1(shouldTrimChar)).base(), nonTrimmed.end());
204+
205+
return nonTrimmed;
206+
}
207+
208+
/**
209+
* @brief Trims both the beginning and the end of a given string.
210+
*
211+
* @param nonTrimmed The non-trimmed string.
212+
* @param trimChar The character to trim off the string. (default: space)
213+
*
214+
* @return The trimmed string.
215+
*/
216+
inline string trim(const string& nonTrimmed, const string& trimChar) { return trimStart(trimEnd(nonTrimmed, trimChar), trimChar); }
217+
218+
219+
#endif // ENDLESSH_REPORT_INCLUDE_EXTENSIONS_HPP

include/options.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#ifndef ENDLESSH_REPORT_INCLUDE_OPTIONS_HPP
1212
#define ENDLESSH_REPORT_INCLUDE_OPTIONS_HPP
1313

14-
#include "options.hpp"
14+
#include "version.hpp"
1515

1616
// stl
1717
#include <string>

include/version.hpp.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ constexpr string_view getProjectName() { return R"(@PROJECT_NAME@)"; }
2121

2222
constexpr string_view getProjectDescription() { return R"(@PROJECT_DESCRIPTION@)"; }
2323

24+
constexpr string_view getLongProjectName() { return R"(@PROJECT_LONG_NAME@)"; }
25+
2426
#endif // ENDLESSH_REPORT_INCLUDE_VERSION_HPP

0 commit comments

Comments
 (0)