From e6dc1c7a5e413cca33b305738ffbe54c79a6aabe Mon Sep 17 00:00:00 2001
From: "w.klijn" <nonoice@gmail.com>
Date: Tue, 16 Aug 2016 17:11:40 +0200
Subject: [PATCH] Add the new spike_exchange files. Do some small textual
 changes

---
 src/io/exporter.hpp            | 37 +++++++++++++
 src/io/exporter_spike_file.hpp | 99 ++++++++++++++++++++++++++++++++++
 2 files changed, 136 insertions(+)
 create mode 100644 src/io/exporter.hpp
 create mode 100644 src/io/exporter_spike_file.hpp

diff --git a/src/io/exporter.hpp b/src/io/exporter.hpp
new file mode 100644
index 00000000..85f7f212
--- /dev/null
+++ b/src/io/exporter.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <random>
+#include <string>
+
+#include <common_types.hpp>
+#include <spike.hpp>
+
+namespace nest {
+namespace mc {
+namespace io {
+
+// interface for exporters.
+// Exposes one virtual functions:
+//    do_export(vector<type>) receiving a vector of parameters to export
+
+template <typename Time, typename CommunicationPolicy>
+class exporter {
+
+public:
+    using time_type = Time;
+    using spike_type = spike<cell_member_type, time_type>;
+
+    // Performs the export of the data
+    virtual void do_export(const std::vector<spike_type>&) = 0;
+
+    // Returns the status of the exporter
+    virtual bool good() const = 0;
+
+    // Static version of the do_export function for NOP callbacks
+    static void do_nothing(const std::vector<spike_type>&)
+    {}
+};
+
+} //communication
+} // namespace mc
+} // namespace nest
diff --git a/src/io/exporter_spike_file.hpp b/src/io/exporter_spike_file.hpp
new file mode 100644
index 00000000..06f26c64
--- /dev/null
+++ b/src/io/exporter_spike_file.hpp
@@ -0,0 +1,99 @@
+#pragma once
+
+#include <cstring>
+#include <cstdio>
+#include <fstream>
+#include <iomanip>
+#include <memory>
+#include <random>
+#include <stdexcept>
+#include <vector>
+
+#include <common_types.hpp>
+#include <io/exporter.hpp>
+#include <spike.hpp>
+#include <util.hpp>
+
+namespace nest {
+namespace mc {
+namespace io {
+
+template <typename Time, typename CommunicationPolicy>
+class exporter_spike_file : public exporter<Time, CommunicationPolicy>
+{
+public:
+    using time_type = Time;
+    using spike_type = spike<cell_member_type, time_type>;
+    using communication_policy_type = CommunicationPolicy;
+
+    // Constructor
+    // over_write if true will overwrite the specified output file (default = true)
+    // output_path  relative or absolute path
+    // file_name    will be appended with "_x" with x the rank number
+    // file_extention  a seperator will be added automatically
+    exporter_spike_file(const std::string& file_name, const std::string& path,
+        const std::string& file_extention, bool over_write=true)
+    {
+        auto file_path =
+            create_output_file_path(file_name, path, file_extention,
+                communication_policy_.id());
+
+        //test if the file exist and depending on over_write throw or delete
+        if (!over_write && file_exists(file_path))
+        {
+            throw std::runtime_error("Tried opening file for writing but it exists and over_write is false: " +
+                file_path);
+        }
+
+        file_handle_.open(file_path);
+    }
+
+    // Performs the a export of the spikes to file
+    // one id and spike time with 4 decimals after the comma on a
+    // line space separated
+    void do_export(const std::vector<spike_type>& spikes) override
+    {
+        for (auto spike : spikes) {
+            char linebuf[45];
+            auto n = std::snprintf(linebuf, sizeof(linebuf), "%u %.4f\n",
+                unsigned{spike.source.gid}, float{spike.time});
+            file_handle_.write(linebuf, n);
+        }
+    }
+
+    bool good() const override
+    {
+        return file_handle_.good();
+    }
+
+    // Creates an indexed filename
+    static std::string create_output_file_path(const std::string& file_name,
+        const std::string& path, const std::string& file_extention,
+        unsigned index)
+    {
+        // Nest does not produce the indexing for nrank == 0
+        // I have the feeling this disrupts consistent output. Id rather
+        // always put the zero in. it allows a simpler regex when opening
+        // files
+        return path + file_name + "_" +  std::to_string(index) + "." +
+               file_extention;
+    }
+
+private:
+
+    bool file_exists(const std::string& file_path)
+    {
+        std::ifstream fid(file_path);
+        return fid.good();
+    }
+
+    // Handle to opened file handle
+    std::ofstream file_handle_;
+
+    communication_policy_type communication_policy_;
+
+};
+
+} //communication
+} // namespace mc
+} // namespace nest
-- 
GitLab