Initial commit

This commit is contained in:
2026-01-24 16:10:02 -05:00
parent e053f094b3
commit cf4020fa08
10 changed files with 267 additions and 0 deletions

54
BlockingQueue.h Normal file
View File

@@ -0,0 +1,54 @@
//
// A thread safe queue with a maximum capacity with blocking enqueue and dequeue calls.
// enqueue blocks if the queue is full, dequeue blocks if the queue is empty.
//
#ifndef BLOCKINGQUEUE_H
#define BLOCKINGQUEUE_H
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <optional>
#include <queue>
template <typename T> class BlockingQueue {
public:
explicit BlockingQueue(const size_t capacity) : m_capacity(capacity) {
}
// Enqueue with timeout. Returns true on success, false on timeout.
bool enqueue(T &&item, std::chrono::milliseconds max_wait) {
std::unique_lock lock(m_mutex);
if (!m_cond_not_full.wait_for(lock, max_wait,
[this]() { return m_queue.size() < m_capacity; })) {
return false;
}
m_queue.push(std::move(item));
m_cond_not_empty.notify_one();
return true;
}
// Dequeue with timeout. Returns optional<T> (empty on timeout).
std::optional<T> dequeue(std::chrono::milliseconds max_wait) {
std::unique_lock lock(m_mutex);
if (!m_cond_not_empty.wait_for(lock, max_wait, [this]() { return !m_queue.empty(); })) {
return std::nullopt;
}
T item = std::move(m_queue.front());
m_queue.pop();
m_cond_not_full.notify_one();
return item;
}
private:
std::queue<T> m_queue;
size_t m_capacity;
std::mutex m_mutex;
std::condition_variable m_cond_not_empty;
std::condition_variable m_cond_not_full;
};
#endif // BLOCKINGQUEUE_H

34
Errno.h Normal file
View File

@@ -0,0 +1,34 @@
//
// Print a detailed errno
//
#ifndef ERRNO_H
#define ERRNO_H
#include <string>
#define ERRBUF_SIZE 300
#ifdef _WIN32
std::string get_errno() {
std::string errbuf;
errbuf.resize(ERRBUERRBUF_SIZE);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(), 0, errbuf.data(), ERERRBUF_SIZE,
NULL);
return errbuf;
}
#else
#include <errno.h>
#include <string.h>
std::string get_errno() {
std::string err = std::strerror(errno);
return err;
}
#endif
#endif //ERRNO_H

55
Event.h Normal file
View File

@@ -0,0 +1,55 @@
//
// An event/listener system.
//
#ifndef EVENT_H
#define EVENT_H
#include <functional>
#include <unordered_map>
class Event;
class CallbackHandle {
public:
CallbackHandle(Event *evt, int id) : m_evt(evt), m_id(id) {
}
~CallbackHandle();
private:
Event *m_evt;
int m_id;
};
class Event {
public:
using Callback = std::function<void()>;
CallbackHandle addListener(Callback cb) {
int id = m_nextId++;
m_callbacks[id] = std::move(cb);
return CallbackHandle(this, id);
}
void remove(int id) {
m_callbacks.erase(id);
}
void fire() {
for (auto &kv : m_callbacks)
kv.second();
}
private:
friend class CallbackHandle;
std::unordered_map<int, Callback> m_callbacks;
int m_nextId = 0;
};
CallbackHandle::~CallbackHandle() {
if (m_evt)
m_evt->remove(m_id);
}
#endif // EVENT_H

19
Map.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef MAP_UTIL_H
#define MAP_UTIL_H
#include <unordered_map>
#include <vector>
// Get vector of values from an unordered_map
template <typename K, typename V, typename H>
std::vector<V> map_to_values(const std::unordered_map<K, V, H> &map) {
std::vector<V> out;
out.reserve(map.size());
for (auto const &[key, value] : map) {
out.push_back(value);
}
return out;
}
#endif // MAP_UTIL_H

19
Number.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef NUMBER_UTILS_H
#define NUMBER_UTILS_H
#include <iostream>
#include <type_traits>
// Map a value with range, to another range.
template<typename T>
T mapRange(T value, T inMin, T inMax, T outMin, T outMax) {
static_assert(std::is_arithmetic<T>::value, "Template parameter must be a numeric type");
if (inMin == inMax) {
return value;
}
return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
}
#endif //NUMBER_UTILS_H

14
PairHash.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef PAIRHASH_H
#define PAIRHASH_H
#include <unordered_map>
// Custom hash function for std::pair
template <typename T> struct pair_hash {
std::size_t operator()(const std::pair<T, T> &p) const {
return std::hash<T>()(p.first) ^ (std::hash<T>()(p.second) << 1);
}
};
#endif // PAIRHASH_H

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# cpp-utils
This repository contains a collection of C++ helper/utility functions I like to use in a lot of my projects.

20
String.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef STRING_H
#define STRING_H
#include <sstream>
#include <string>
#include <vector>
// Split a string on a delimiter to a vector of strings
inline std::vector<std::string> split(const std::string &str, const char delimiter) {
std::vector<std::string> result;
std::stringstream ss(str);
std::string token;
while (std::getline(ss, token, delimiter)) {
result.push_back(token);
}
return result;
}
#endif //STRING_H

23
Variant.h Normal file
View File

@@ -0,0 +1,23 @@
// Helper to make it easier to use std::visit with std::variant
// For example,
// std::visit(
// overloaded{
// [](int i) { std::cout << "int: " << i << std::endl; },
// [](double d) { std::cout << "double: " << d << std::endl; },
// },
// variant
// );
#ifndef VARIANT_H
#define VARIANT_H
#include <variant> // NOLINT
template <class... Ts> struct overloaded : Ts... {
using Ts::operator()...;
};
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
#endif // VARIANT_H

26
ip.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef IP_UTIL_H
#define IP_UTIL_H
#include <string>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#define CLOSE_SOCKET closesocket
#pragma comment(lib, "ws2_32.lib")
typedef SOCKET socket_t;
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#define CLOSE_SOCKET close
typedef int socket_t;
#endif
bool is_valid_ipv4(const std::string &ip) {
struct in_addr addr;
return inet_pton(AF_INET, ip.c_str(), &addr) == 1;
}
#endif // IP_UTIL_H