#pragma once
#include <string>
#include <cstring>
#include <sstream>
#include <cstdint>
#undef major
#undef minor
struct Version {
Version() : major(0), minor(0), sub(0) {}
Version(const std::string &str) {
if (!ParseVersionString(str)) {
major = -1;
minor = -1;
sub = -1;
}
}
int major;
int minor;
int sub;
bool IsValid() const {
return sub >= 0 && minor >= 0 && major >= 0;
}
bool operator == (const Version &other) const {
return major == other.major && minor == other.minor && sub == other.sub;
}
bool operator != (const Version &other) const {
return !(*this == other);
}
bool operator <(const Version &other) const {
if (major < other.major) return true;
if (major > other.major) return false;
if (minor < other.minor) return true;
if (minor > other.minor) return false;
if (sub < other.sub) return true;
if (sub > other.sub) return false;
return false;
}
bool operator >=(const Version &other) const {
return !(*this < other);
}
std::string ToString() const;
int ToInteger() const;
private:
bool ParseVersionString(std::string str);
};
bool ParseMacAddress(const std::string &str, uint8_t macAddr[6]);
bool TryParse(const std::string &str, bool *const output);
bool TryParse(const std::string &str, uint32_t *const output);
bool TryParse(const std::string &str, uint64_t *const output);
template <typename N>
static bool TryParse(const std::string &str, N *const output) {
std::istringstream iss(str);
N tmp = 0;
if (iss >> tmp) {
*output = tmp;
return true;
} else
return false;
}
void NiceSizeFormat(uint64_t size, char *out, size_t bufSize);
std::string NiceSizeFormat(uint64_t size);
std::string NiceTimeFormat(int seconds);
class StringWriter {
public:
StringWriter(char *buffer, size_t bufSize) : start_(buffer), p_(buffer), bufSize_(bufSize) {
buffer[0] = '\0';
}
template<size_t sz>
explicit StringWriter(char (&buffer)[sz]) : start_(buffer), p_(buffer), bufSize_(sz) {
buffer[0] = '\0';
}
StringWriter(const StringWriter &) = delete;
std::string_view as_view() const {
return std::string_view(start_, p_ - start_);
}
size_t size() const {
return p_ - start_;
}
template<size_t T>
StringWriter &C(const char(&text)[T]) {
const size_t remainder = bufSize_ - (p_ - start_);
if (remainder <= T)
return *this;
memcpy(p_, text, T);
p_ += T - 1;
return *this;
}
StringWriter &B(bool b) {
return W(b ? "true" : "false");
}
StringWriter &W(std::string_view text) {
const size_t remainder = bufSize_ - (p_ - start_);
if (remainder <= text.length())
return *this;
memcpy(p_, text.data(), text.length());
p_ += text.length();
*p_ = '\0';
return *this;
}
StringWriter &F(const char *format, ...);
StringWriter &endl() {
const size_t remainder = bufSize_ - (p_ - start_);
if (remainder <= 2)
return *this;
return C("\n");
}
void Rewind(size_t offset) {
p_ -= offset;
}
private:
char *start_;
char *p_;
size_t bufSize_;
};