aboutsummaryrefslogtreecommitdiff
path: root/apps/sample-timestamp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'apps/sample-timestamp.cpp')
-rw-r--r--apps/sample-timestamp.cpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/apps/sample-timestamp.cpp b/apps/sample-timestamp.cpp
new file mode 100644
index 0000000..3a0b3e0
--- /dev/null
+++ b/apps/sample-timestamp.cpp
@@ -0,0 +1,156 @@
+#include "SoilMoistureIo.h"
+#include "apps.h"
+#include <fstream>
+#include <sys/stat.h>
+
+namespace trygvis {
+namespace apps {
+
+using namespace std;
+using namespace trygvis::apps;
+using namespace trygvis::soil_moisture;
+namespace po = boost::program_options;
+
+class TimestampFixingSampleOutputStream : public SampleOutputStream {
+
+public:
+ TimestampFixingSampleOutputStream(string timestamp_name, string now_name, time_t start_time, shared_ptr<SampleOutputStream> output) :
+ timestamp_name_(timestamp_name), now_name_(now_name), start_time_(start_time), output_(output) {
+ }
+
+ virtual void write(Sample sample) override {
+ long relative_time = sample.lexical_at<long>(now_name_);
+
+ string new_value = std::to_string(start_time_ + relative_time);
+ sample.set(timestamp_name_, new_value);
+
+ output_->write(sample);
+ };
+
+private:
+ string now_name_, timestamp_name_;
+ time_t start_time_;
+ shared_ptr<SampleOutputStream> output_;
+};
+
+class sample_timestamp : public app {
+
+private:
+ string input_file, timestamp_name, now_name;
+
+public:
+ sample_timestamp() : input_file("") {
+ }
+
+ void add_options(po::options_description_easy_init &options) override {
+ options
+ ("help", "produce this help message")
+ ("input", po::value<string>(&input_file)->required())
+ ("now-name", po::value<string>(&now_name)->default_value("now"))
+ ("timestamp-name", po::value<string>(&timestamp_name)->default_value("timestamp"));
+ }
+
+ int main(app_execution &execution) override {
+ ifstream input(input_file, std::ifstream::in | std::ifstream::binary);
+
+ if (input.fail()) {
+ cerr << "Could not open file: " << input_file << endl;
+ return EXIT_FAILURE;
+ }
+
+ const int buffer_size = 100;
+
+ input.seekg(-buffer_size, ios_base::end);
+
+ struct stat buf;
+
+ if (stat(input_file.c_str(), &buf)) {
+ cerr << "stat failed" << endl;
+ return EXIT_FAILURE;
+ }
+
+ auto sample_buffer = make_shared<VectorSampleOutputStream>();
+ unique_ptr<SampleStreamParser> parser = open_sample_input_stream(sample_buffer);
+ while (!input.eof()) {
+ char buffer[buffer_size];
+ input.read(buffer, buffer_size);
+
+ if (input.bad()) {
+ cerr << "Error reading input" << endl;
+ return EXIT_FAILURE;
+ }
+
+ size_t count = (size_t) input.gcount();
+
+ mutable_buffers_1 b = boost::asio::buffer(buffer, count);
+ parser->process(b);
+ }
+
+ if (sample_buffer->samples.empty()) {
+ cerr << "Could not find any samples" << endl;
+ return EXIT_FAILURE;
+ }
+
+ time_t end_time = buf.st_mtim.tv_sec;
+
+ Sample sample = *--sample_buffer->samples.end();
+
+ string s;
+ try {
+ s = sample.at(now_name);
+ } catch (out_of_range &e) {
+ cerr << "Missing key '" + now_name + "'." << endl;
+ return EXIT_FAILURE;
+ }
+
+ long now;
+ try {
+ now = boost::lexical_cast<long>(s);
+ } catch (const boost::bad_lexical_cast &e) {
+ cerr << "Bad integer value '" + s + "'." << endl;
+ return EXIT_FAILURE;
+ }
+
+ time_t start_time = end_time - now;
+ cerr << "end_time " << end_time << endl;
+ cerr << "now " << now << endl;
+ cerr << "start_time " << start_time << endl;
+
+ // Restart the reading of the input file and add the adjusted timestamp
+ input.clear(ios::eofbit);
+ input.seekg(0);
+ if(input.fail()) {
+ cerr << "Coult not seek input file" << endl;
+ return EXIT_FAILURE;
+ }
+
+ auto output_stream = open_sample_output_stream(parser->type(), unique_ptr<ostream>(&cout));
+ auto p = make_shared<TimestampFixingSampleOutputStream>("timestamp", now_name, start_time, move(output_stream));
+ parser = open_sample_input_stream(p, parser->type());
+
+ int recordCount = 0;
+
+ while (!input.eof()) {
+ char buffer[buffer_size];
+
+ size_t gcount = (size_t)input.readsome(buffer, buffer_size);
+
+ recordCount++;
+
+ mutable_buffers_1 b = boost::asio::buffer(buffer, gcount);
+ parser->process(b);
+ }
+
+ return EXIT_SUCCESS;
+ }
+};
+
+}
+}
+
+using namespace trygvis::apps;
+
+int main(int argc, char *argv[]) {
+ sample_timestamp app;
+ return launch_app(argc, argv, app);
+}