summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2013-07-26 19:47:09 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2013-07-26 19:47:09 +0200
commitf706404e6e40043b87ff19e32c8fd11958772e9d (patch)
treeb949a9a1fa58fdb410f1c048e5675c9b11a02c94
parenta615e395f28d313dd9c111abc846960db6cb0738 (diff)
downloadgmrf-f706404e6e40043b87ff19e32c8fd11958772e9d.tar
gmrf-f706404e6e40043b87ff19e32c8fd11958772e9d.zip
More cleanups
-rw-r--r--mmss/CMakeLists.txt1
-rw-r--r--mmss/config.cpp7
-rw-r--r--mmss/gmrf.cpp143
-rw-r--r--mmss/iface.cpp64
-rw-r--r--mmss/log.cpp47
-rw-r--r--mmss/mmss.cpp49
-rw-r--r--mmss/mmss.hpp108
-rw-r--r--mmss/protocol.cpp14
-rw-r--r--mmss/schedule.cpp12
-rw-r--r--mmss/types.hpp5
-rw-r--r--mmss/util.hpp47
11 files changed, 316 insertions, 181 deletions
diff --git a/mmss/CMakeLists.txt b/mmss/CMakeLists.txt
index 047e348..04ac405 100644
--- a/mmss/CMakeLists.txt
+++ b/mmss/CMakeLists.txt
@@ -5,6 +5,7 @@ BISON_TARGET(mmss_config_parse config.y ${CMAKE_CURRENT_BINARY_DIR}/config.yy.cp
add_executable(mmss
config.cpp
+ gmrf.cpp
iface.cpp
log.cpp
mmss.cpp
diff --git a/mmss/config.cpp b/mmss/config.cpp
index 529e9b1..4492ffd 100644
--- a/mmss/config.cpp
+++ b/mmss/config.cpp
@@ -40,13 +40,12 @@ namespace Config {
void add_network(context_t *mmss, config_t *conf, const char *name) {
logf(mmss, LOG_NOTICE, "adding network `%s'", name);
- network_t *net = new network_t;
+ std::shared_ptr<network_t> net = std::make_shared<network_t>();
- net->name = strdup(name);
+ net->name = name;
net->mtu = 1500;
- net->next = conf->networks;
- conf->networks = net;
+ conf->network.push_back(net);
}
}
diff --git a/mmss/gmrf.cpp b/mmss/gmrf.cpp
new file mode 100644
index 0000000..d6eecbc
--- /dev/null
+++ b/mmss/gmrf.cpp
@@ -0,0 +1,143 @@
+/*
+ Copyright (c) 2013, Matthias Schiffer <mschiffer@universe-factory.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "mmss.hpp"
+#include "util.hpp"
+
+#include <cassert>
+
+
+extern "C" {
+
+gmrf_addr_t gmrf_iface_get_addr(gmrf_t *gmrf, gmrf_iface_t *iface) {
+ return iface->address;
+}
+
+const char* gmrf_iface_get_name(gmrf_t *gmrf, gmrf_iface_t *iface) {
+ return iface->name.c_str();
+}
+
+size_t gmrf_iface_get_mtu(gmrf_t *gmrf, gmrf_iface_t *iface) {
+ auto net = iface->net.lock();
+ if (!net)
+ return 0;
+
+ return net->mtu;
+}
+
+bool gmrf_iface_send(gmrf_t *gmrf, gmrf_iface_t *iface, const void *data, size_t len, const gmrf_addr_t *dest) {
+ auto src_iface = iface->iface.lock();
+ assert(src_iface);
+
+ auto net = src_iface->net.lock();
+ if (!net)
+ return false;
+
+ for (auto dest_iface : net->interfaces) {
+ if (gmrf_addr_equal(&dest_iface->address, dest)) {
+ MMSS::enqueue(gmrf->mmss, src_iface, dest_iface, data, len);
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool gmrf_iface_send_bc(gmrf_t *gmrf, gmrf_iface_t *iface, const void *data, size_t len) {
+ auto src_iface = iface->iface.lock();
+ assert(src_iface);
+
+ auto net = src_iface->net.lock();
+ if (!net)
+ return false;
+
+ for (auto dest_iface : net->interfaces) {
+ if (dest_iface != src_iface)
+ MMSS::enqueue(gmrf->mmss, src_iface, dest_iface, data, len);
+ }
+
+ return true;
+}
+
+void gmrf_schedule(gmrf_t *gmrf, gmrf_scheduled_func f, void *arg, unsigned delay) {
+ auto node = gmrf->node.lock();
+ assert(node);
+
+ std::shared_ptr<MMSS::scheduled_t> scheduled = std::make_shared<MMSS::scheduled_t>();
+
+ scheduled->node = node;
+ scheduled->f = f;
+ scheduled->arg = arg;
+
+ gmrf->mmss->scheduled_queue.put(scheduled, gmrf->mmss->now+delay);
+}
+
+gmrf_time_t gmrf_now(gmrf_t *gmrf) {
+ return gmrf->mmss->now;
+}
+
+void gmrf_random_bytes(gmrf_t *gmrf, void *buffer, size_t len) {
+ uint8_t *data = reinterpret_cast<uint8_t*>(buffer);
+
+ size_t i;
+ for (i = 0; i < len; i++)
+ data[i] = rand_r(&gmrf->rand_seed);
+}
+
+static inline const char* get_log_prefix(int log_level) {
+ switch(log_level) {
+ case LOG_CRIT:
+ return "Fatal: ";
+ case LOG_ERR:
+ return "Error: ";
+ case LOG_WARNING:
+ return "Warning: ";
+ case LOG_NOTICE:
+ return "Info: ";
+ case LOG_INFO:
+ return "Verbose: ";
+ case LOG_DEBUG:
+ return "DEBUG: ";
+ default:
+ return "";
+ }
+}
+
+void gmrf_logf(gmrf_t *gmrf, int priority, const char *format, ...) {
+ char buf[1024];
+ size_t pos = 0;
+
+ pos += MMSS::snprintf_safe(buf, sizeof(buf), "%s: %s", gmrf->name.c_str(), get_log_prefix(priority));
+
+ va_list ap;
+ va_start(ap, format);
+ vsnprintf(buf+pos, sizeof(buf)-pos, format, ap);
+ va_end(ap);
+
+ MMSS::logf(gmrf->mmss, priority, "%s", buf);
+}
+
+}
diff --git a/mmss/iface.cpp b/mmss/iface.cpp
index e25eccd..602daa2 100644
--- a/mmss/iface.cpp
+++ b/mmss/iface.cpp
@@ -32,29 +32,34 @@
namespace MMSS {
void dispatch(std::shared_ptr<packet_t> packet) {
- packet->dest->node->proto->handle_packet(packet->dest->node, packet->dest->node->ctx, packet->dest,
- &packet->source->address, packet->data.get(), packet->len);
+ auto source = packet->source.lock();
+ auto dest = packet->dest.lock();
+ if (!source || !dest)
+ return;
+
+ auto node = dest->node.lock();
+ if (!node)
+ return;
+
+ node->proto->handle_packet(node.get(), node->ctx, dest.get(), &source->address, packet->data.get(), packet->len);
}
-void add_iface(gmrf_t *node, network_t *net, const char *name, const gmrf_addr_t *address) {
- gmrf_iface_t *iface = new gmrf_iface_t;
+void add_iface(std::shared_ptr<node_t> node, std::shared_ptr<network_t> net, const std::string &name, const gmrf_addr_t *address) {
+ std::shared_ptr<iface_t> iface = iface_t::create();
- iface->name = strdup(name);
+ iface->name = name;
iface->address = *address;
iface->node = node;
iface->net = net;
- iface->node_next = node->interfaces;
- node->interfaces = iface;
+ node->interfaces.push_back(iface);
+ net->interfaces.push_back(iface);
- iface->network_next = net->interfaces;
- net->interfaces = iface;
-
- node->proto->add_iface(node, node->ctx, iface);
+ node->proto->add_iface(node.get(), node->ctx, iface.get());
}
-static void enqueue(context_t *mmss, gmrf_iface_t *source, gmrf_iface_t *dest, const void *data, size_t len) {
+void enqueue(context_t *mmss, std::shared_ptr<iface_t> source, std::shared_ptr<iface_t> dest, const void *data, size_t len) {
std::shared_ptr<packet_t> packet = std::make_shared<packet_t>();
packet->sent = mmss->now;
@@ -69,38 +74,3 @@ static void enqueue(context_t *mmss, gmrf_iface_t *source, gmrf_iface_t *dest, c
}
}
-
-
-gmrf_addr_t gmrf_iface_get_addr(gmrf_t *gmrf, gmrf_iface_t *iface) {
- return iface->address;
-}
-
-const char* gmrf_iface_get_name(gmrf_t *gmrf, gmrf_iface_t *iface) {
- return iface->name;
-}
-
-size_t gmrf_iface_get_mtu(gmrf_t *gmrf, gmrf_iface_t *iface) {
- return iface->net->mtu;
-}
-
-bool gmrf_iface_send(gmrf_t *gmrf, gmrf_iface_t *iface, const void *data, size_t len, const gmrf_addr_t *dest) {
- gmrf_iface_t *dest_iface;
- for (dest_iface = iface->net->interfaces; dest_iface; dest_iface = dest_iface->network_next) {
- if (gmrf_addr_equal(&dest_iface->address, dest)) {
- MMSS::enqueue(gmrf->mmss, iface, dest_iface, data, len);
- break;
- }
- }
-
- return true;
-}
-
-bool gmrf_iface_send_bc(gmrf_t *gmrf, gmrf_iface_t *iface, const void *data, size_t len) {
- gmrf_iface_t *dest_iface;
- for (dest_iface = iface->net->interfaces; dest_iface; dest_iface = dest_iface->network_next) {
- if (dest_iface != iface)
- enqueue(gmrf->mmss, iface, dest_iface, data, len);
- }
-
- return true;
-}
diff --git a/mmss/log.cpp b/mmss/log.cpp
index 029b1d6..b66cf6f 100644
--- a/mmss/log.cpp
+++ b/mmss/log.cpp
@@ -25,41 +25,10 @@
#include "mmss.hpp"
-
-#include <cstdarg>
-#include <cstdio>
-
+#include "util.hpp"
namespace MMSS {
-static inline int snprintf_safe(char *buffer, size_t size, const char *format, ...) {
- std::va_list ap;
- va_start(ap, format);
- int ret = std::vsnprintf(buffer, size, format, ap);
- va_end(ap);
-
- return ret < 0 ? 0 : ret > size ? size : ret;
-}
-
-static inline const char* get_log_prefix(int log_level) {
- switch(log_level) {
- case LOG_CRIT:
- return "Fatal: ";
- case LOG_ERR:
- return "Error: ";
- case LOG_WARNING:
- return "Warning: ";
- case LOG_NOTICE:
- return "Info: ";
- case LOG_INFO:
- return "Verbose: ";
- case LOG_DEBUG:
- return "DEBUG: ";
- default:
- return "";
- }
-}
-
void logf(context_t *mmss, int priority, const char *format, ...) {
char buf[1024];
size_t pos = 0;
@@ -75,17 +44,3 @@ void logf(context_t *mmss, int priority, const char *format, ...) {
}
}
-
-void gmrf_logf(gmrf_t *gmrf, int priority, const char *format, ...) {
- char buf[1024];
- size_t pos = 0;
-
- pos += MMSS::snprintf_safe(buf, sizeof(buf), "%s: %s", gmrf->name, MMSS::get_log_prefix(priority));
-
- va_list ap;
- va_start(ap, format);
- vsnprintf(buf+pos, sizeof(buf)-pos, format, ap);
- va_end(ap);
-
- MMSS::logf(gmrf->mmss, priority, "%s", buf);
-}
diff --git a/mmss/mmss.cpp b/mmss/mmss.cpp
index cb50329..1d918e4 100644
--- a/mmss/mmss.cpp
+++ b/mmss/mmss.cpp
@@ -30,25 +30,11 @@
#include <cstdio>
-gmrf_time_t gmrf_now(gmrf_t *gmrf) {
- return gmrf->mmss->now;
-}
-
-void gmrf_random_bytes(gmrf_t *gmrf, void *buffer, size_t len) {
- uint8_t *data = reinterpret_cast<uint8_t*>(buffer);
-
- size_t i;
- for (i = 0; i < len; i++)
- data[i] = rand_r(&gmrf->rand_seed);
-}
-
namespace MMSS {
-static void init_nodes(gmrf_t *nodes) {
- gmrf_t *node;
- for (node = nodes; node; node = node->next) {
- node->ctx = node->proto->init(node);
- }
+static void init_nodes(std::list<std::shared_ptr<node_t>> &nodes) {
+ for (auto node : nodes)
+ node->ctx = node->proto->init(node.get());
}
@@ -85,22 +71,29 @@ void main(int argc, char *argv[]) {
read_config(&mmss, &conf, "babel_test.mmss");
- network_t net0 = { .mtu = 1500 }, net1 = { .mtu = 1500 };
- gmrf_t node1 = { .name = strdup("node1"), .mmss = &mmss, .rand_seed = 1, .proto = proto };
- gmrf_t node2 = { .name = strdup("node2"), .mmss = &mmss, .rand_seed = 2, .proto = proto };
- gmrf_t node3 = { .name = strdup("node3"), .mmss = &mmss, .rand_seed = 3, .proto = proto };
+ std::shared_ptr<network_t> net0 = std::make_shared<network_t>();
+ std::shared_ptr<network_t> net1 = std::make_shared<network_t>();
+
+ *net0 = (network_t){ .mtu = 1500 };
+ *net1 = (network_t){ .mtu = 1500 };
+
+ std::shared_ptr<node_t> node1 = node_t::create(&mmss, "node1", 1, proto);
+ std::shared_ptr<node_t> node2 = node_t::create(&mmss, "node2", 2, proto);
+ std::shared_ptr<node_t> node3 = node_t::create(&mmss, "node3", 3, proto);
+
+ std::list<std::shared_ptr<node_t>> nodes;
- node2.next = &node1;
- node3.next = &node2;
- gmrf_t *nodes = &node3;
+ nodes.push_back(node1);
+ nodes.push_back(node2);
+ nodes.push_back(node3);
init_nodes(nodes);
gmrf_addr_t addr1 = {{1}}, addr2 = {{2}}, addr3 = {{3}}, addr4 = {{4}};
- add_iface(&node1, &net0, "mmss0", &addr1);
- add_iface(&node2, &net0, "mmss0", &addr2);
- add_iface(&node2, &net1, "mmss1", &addr3);
- add_iface(&node3, &net1, "mmss1", &addr4);
+ add_iface(node1, net0, "mmss0", &addr1);
+ add_iface(node2, net0, "mmss0", &addr2);
+ add_iface(node2, net1, "mmss1", &addr3);
+ add_iface(node3, net1, "mmss1", &addr4);
while (true) {
int timeout = get_queue_timeout(&mmss);
diff --git a/mmss/mmss.hpp b/mmss/mmss.hpp
index 78c93be..4045c40 100644
--- a/mmss/mmss.hpp
+++ b/mmss/mmss.hpp
@@ -29,9 +29,67 @@
#include "queue.hpp"
+#include <list>
#include <memory>
+struct gmrf {
+private:
+ gmrf(MMSS::context_t *mmss0, const std::string &name0, unsigned rand_seed0, const MMSS::protocol_t *proto0) :
+ mmss(mmss0), name(name0), rand_seed(rand_seed0), proto(proto0) {}
+ gmrf(gmrf const&) = delete;
+ gmrf& operator=(gmrf const&) = delete;
+
+public:
+ static std::shared_ptr<MMSS::node_t> create(MMSS::context_t *mmss, const std::string &name, unsigned rand_seed, const MMSS::protocol_t *proto) {
+ MMSS::node_t *node = new MMSS::node_t(mmss, name, rand_seed, proto);
+
+ std::shared_ptr<MMSS::node_t> ptr(node);
+ node->node = ptr;
+
+ return ptr;
+ }
+
+ std::weak_ptr<MMSS::node_t> node;
+
+ MMSS::context_t *mmss;
+
+ std::string name;
+
+ gmrf_context_t *ctx;
+ std::list<std::shared_ptr<MMSS::iface_t>> interfaces;
+
+ unsigned rand_seed;
+
+ const MMSS::protocol_t *proto;
+};
+
+struct gmrf_iface {
+private:
+ gmrf_iface() {}
+ gmrf_iface(gmrf_iface const&) = delete;
+ gmrf_iface& operator=(gmrf_iface const&) = delete;
+
+public:
+ static std::shared_ptr<MMSS::iface_t> create() {
+ MMSS::iface_t *iface = new MMSS::iface_t;
+
+ std::shared_ptr<MMSS::iface_t> ptr(iface);
+ iface->iface = ptr;
+
+ return ptr;
+ }
+
+ std::weak_ptr<MMSS::iface_t> iface;
+
+ std::string name;
+ gmrf_addr_t address;
+
+ std::weak_ptr<MMSS::node_t> node;
+ std::weak_ptr<MMSS::network_t> net;
+};
+
+
namespace MMSS {
class context_t {
@@ -45,17 +103,15 @@ public:
class config_t {
public:
- network_t *networks;
- gmrf_t *nodes;
+ std::list<std::shared_ptr<network_t>> network;
+ std::list<std::shared_ptr<node_t>> nodes;
};
class network_t {
public:
- network_t *next;
+ std::string name;
- char *name;
-
- gmrf_iface_t *interfaces;
+ std::list<std::shared_ptr<iface_t>> interfaces;
size_t mtu;
};
@@ -63,8 +119,8 @@ class packet_t {
public:
uint64_t sent;
- gmrf_iface_t *source;
- gmrf_iface_t *dest;
+ std::weak_ptr<iface_t> source;
+ std::weak_ptr<iface_t> dest;
size_t len;
std::unique_ptr<uint8_t> data;
@@ -72,7 +128,7 @@ public:
class scheduled_t {
public:
- gmrf_t *node;
+ std::shared_ptr<node_t> node;
gmrf_scheduled_func f;
void *arg;
};
@@ -80,20 +136,15 @@ public:
const protocol_t* load_protocol(const char *module);
-namespace Config {
-
-void add_network(context_t *mmss, config_t *conf, const char *name);
-
-}
-
bool read_config(context_t *mmss, config_t *conf, const char *filename);
-void add_iface(gmrf_t *node, network_t *net, const char *name, const gmrf_addr_t *address);
+void add_iface(std::shared_ptr<node_t> node, std::shared_ptr<network_t> net, const std::string &name, const gmrf_addr_t *address);
uint64_t now(const context_t *mmss);
void dispatch(std::shared_ptr<packet_t> packet);
void run_scheduled(std::shared_ptr<scheduled_t> scheduled);
+void enqueue(context_t *mmss, std::shared_ptr<iface_t> source, std::shared_ptr<iface_t> dest, const void *data, size_t len);
void logf(context_t *mmss, int priority, const char *format, ...);
@@ -111,31 +162,14 @@ static inline size_t alignto(size_t l, size_t a) {
return ((l+a-1)/a)*a;
}
-}
-
-struct gmrf {
- gmrf_t *next;
-
- char *name;
- MMSS::context_t *mmss;
- gmrf_context_t *ctx;
- gmrf_iface_t *interfaces;
-
- unsigned rand_seed;
+namespace Config {
- const MMSS::protocol_t *proto;
-};
+void add_network(context_t *mmss, config_t *conf, const char *name);
-struct gmrf_iface {
- gmrf_iface_t *node_next;
- gmrf_iface_t *network_next;
+}
- char *name;
- gmrf_addr_t address;
+}
- gmrf_t *node;
- MMSS::network_t *net;
-};
#endif /* _GMRF_MMSS_MMSS_HPP_ */
diff --git a/mmss/protocol.cpp b/mmss/protocol.cpp
index f08d13e..3bbfeb1 100644
--- a/mmss/protocol.cpp
+++ b/mmss/protocol.cpp
@@ -33,21 +33,21 @@
namespace MMSS {
const protocol_t* load_protocol(const char *module) {
- void *handle = dlopen(module, RTLD_NOW);
+ void *handle = ::dlopen(module, RTLD_NOW);
if (!handle) {
- fprintf(stderr, "unable to load protocol from `%s': %s\n", module, dlerror());
+ std::fprintf(stderr, "unable to load protocol from `%s': %s\n", module, dlerror());
return NULL;
}
- dlerror();
- const protocol_t *proto = reinterpret_cast<const protocol_t*>(dlsym(handle, "mmss_protocol_info"));
+ ::dlerror();
+ const protocol_t *proto = reinterpret_cast<const protocol_t*>(::dlsym(handle, "mmss_protocol_info"));
if (!proto) {
- fprintf(stderr, "unable to load protocol from `%s': %s\n", module, dlerror());
- dlclose(handle);
+ std::fprintf(stderr, "unable to load protocol from `%s': %s\n", module, dlerror());
+ ::dlclose(handle);
return NULL;
}
- fprintf(stderr, "loaded protocol `%s' version %s\n", proto->get_name(), proto->get_version());
+ std::fprintf(stderr, "loaded protocol `%s' version %s\n", proto->get_name(), proto->get_version());
return proto;
}
diff --git a/mmss/schedule.cpp b/mmss/schedule.cpp
index 88de519..7e6247e 100644
--- a/mmss/schedule.cpp
+++ b/mmss/schedule.cpp
@@ -30,17 +30,7 @@
namespace MMSS {
void run_scheduled(std::shared_ptr<scheduled_t> scheduled) {
- scheduled->f(scheduled->node, scheduled->node->ctx, scheduled->arg);
+ scheduled->f(scheduled->node.get(), scheduled->node->ctx, scheduled->arg);
}
}
-
-void gmrf_schedule(gmrf_t *gmrf, gmrf_scheduled_func f, void *arg, unsigned delay) {
- std::shared_ptr<MMSS::scheduled_t> scheduled = std::make_shared<MMSS::scheduled_t>();
-
- scheduled->node = gmrf;
- scheduled->f = f;
- scheduled->arg = arg;
-
- gmrf->mmss->scheduled_queue.put(scheduled, gmrf->mmss->now+delay);
-}
diff --git a/mmss/types.hpp b/mmss/types.hpp
index e8a63cc..3daa486 100644
--- a/mmss/types.hpp
+++ b/mmss/types.hpp
@@ -33,8 +33,8 @@
extern "C" {
-#include <gmrf/gmrf.h>
#include <mmss/protocol.h>
+#include <gmrf/gmrf.h>
}
@@ -48,6 +48,9 @@ class scheduled_t;
typedef ::mmss_protocol_t protocol_t;
+typedef ::gmrf_t node_t;
+typedef ::gmrf_iface_t iface_t;
+
}
#endif /* _GMRF_MMSS_TYPES_HPP_ */
diff --git a/mmss/util.hpp b/mmss/util.hpp
new file mode 100644
index 0000000..147a9aa
--- /dev/null
+++ b/mmss/util.hpp
@@ -0,0 +1,47 @@
+/*
+ Copyright (c) 2013, Matthias Schiffer <mschiffer@universe-factory.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _GMRF_MMSS_UTIL_HPP_
+#define _GMRF_MMSS_UTIL_HPP_
+
+#include <cstdarg>
+#include <cstdio>
+
+
+namespace MMSS {
+
+static inline int snprintf_safe(char *buffer, size_t size, const char *format, ...) {
+ std::va_list ap;
+ va_start(ap, format);
+ int ret = std::vsnprintf(buffer, size, format, ap);
+ va_end(ap);
+
+ return ret < 0 ? 0 : ret > size ? size : ret;
+}
+
+}
+
+#endif /* _GMRF_MMSS_UTIL_HPP_ */