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