mirror of
https://github.com/jslightham/cpp-utils.git
synced 2026-03-09 18:12:26 +01:00
Initial commit
This commit is contained in:
54
BlockingQueue.h
Normal file
54
BlockingQueue.h
Normal 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
34
Errno.h
Normal 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
55
Event.h
Normal 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
19
Map.h
Normal 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
19
Number.h
Normal 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
14
PairHash.h
Normal 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
3
README.md
Normal 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
20
String.h
Normal 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
23
Variant.h
Normal 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
26
ip.h
Normal 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
|
||||||
Reference in New Issue
Block a user