]> git.sesse.net Git - casparcg/commitdiff
* Implemented cpu_info(), system_product_name() and os_description() for Linux.
authorHelge Norberg <helge.norberg@svt.se>
Wed, 4 Nov 2015 20:15:27 +0000 (21:15 +0100)
committerHelge Norberg <helge.norberg@svt.se>
Wed, 4 Nov 2015 20:15:27 +0000 (21:15 +0100)
common/os/linux/system_info.cpp

index f1da76a7051111c030d6a701d21d1bda39c4827b..4b05d86e91ef89109d9bbfaef5e80a2daa085121 100644 (file)
 
 #include "../system_info.h"
 
+#include "../../memory.h"
+
+#include <boost/algorithm/string/trim.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/range/algorithm/count.hpp>
+#include <boost/iostreams/filter/grep.hpp>
+#include <boost/iostreams/filter/line.hpp>
+#include <boost/iostreams/filter/aggregate.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/pipeline.hpp>
+#include <boost/iostreams/compose.hpp>
+#include <boost/iostreams/device/file.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <functional>
+
 namespace caspar {
-       
+
+namespace detail {
+
+       class functor_line_filter : public boost::iostreams::wline_filter
+       {
+               std::function<std::wstring (const std::wstring& line)> func_;
+       public:
+               template<typename Func>
+               functor_line_filter(const Func& func)
+               : func_(func)
+               {
+               }
+
+               std::wstring do_filter(const std::wstring& in) override
+               {
+                       return func_(in);
+               }
+       };
+
+       class truncate_duplicates : public boost::iostreams::wline_filter
+       {
+               std::set<std::wstring> seen_;
+       public:
+               std::wstring do_filter(const std::wstring& in) override
+               {
+                       auto previously_not_seen = seen_.insert(in).second;
+
+                       if (previously_not_seen)
+                               return in;
+                       else
+                               return L"";
+               }
+       };
+
+} // namespace detail
+
+std::wstring consume(std::shared_ptr<std::wistream>&& in)
+{
+       return std::wstring(std::istreambuf_iterator<wchar_t>(*in), std::istreambuf_iterator<wchar_t>());
+}
+
+template<typename Filter>
+std::shared_ptr<boost::iostreams::filtering_wistream> operator|(std::shared_ptr<std::wistream> in, const Filter& filter)
+{
+       spl::shared_ptr<boost::iostreams::filtering_wistream> filtered;
+       filtered->push(filter);
+       filtered->push(*in);
+
+       return std::shared_ptr<boost::iostreams::filtering_wistream>(
+               filtered.get(),
+               [in, filtered](boost::iostreams::filtering_wistream* p) {});
+}
+
+// Commands
+
+std::shared_ptr<std::wifstream> cat(const std::string& file)
+{
+       return std::make_shared<std::wifstream>(file);
+}
+
+boost::iostreams::wgrep_filter grep(const std::wstring& pattern)
+{
+       return boost::iostreams::wgrep_filter(boost::wregex(pattern));
+}
+
+detail::functor_line_filter cut(const std::wstring& delimiter, int column)
+{
+       return detail::functor_line_filter([=](const std::wstring& line)
+       {
+               std::vector<std::wstring> result;
+               boost::algorithm::split(result, line, boost::is_any_of(delimiter), boost::algorithm::token_compress_on);
+               return result.at(column);
+       });
+}
+
+detail::functor_line_filter trim()
+{
+       return detail::functor_line_filter([](const std::wstring& line) { return boost::trim_copy(line); });
+}
+
+struct wc : boost::iostreams::aggregate_filter<wchar_t>
+{
+       void do_filter(const std::vector<wchar_t>& src, std::vector<wchar_t>& dest) override
+       {
+               auto line_count = boost::range::count(src, L'\n') + 4;
+               auto out = boost::lexical_cast<std::wstring>(line_count);
+               dest.insert(dest.begin(), out.begin(), out.end());
+               dest.push_back('\n');
+       }
+};
+
+struct remove_empty_lines : boost::iostreams::aggregate_filter<wchar_t>
+{
+       void do_filter(const std::vector<wchar_t>& src, std::vector<wchar_t>& dest) override
+       {
+               bool last_was_newline = false;
+
+               for (auto iter = src.begin(), end = src.end(); iter != end; ++iter)
+               {
+                       auto current    = *iter;
+                       auto is_newline = current == '\n';
+
+                       if (is_newline && (last_was_newline || iter == src.begin()))
+                               continue;
+
+                       dest.push_back(current);
+                       last_was_newline = is_newline;
+               }
+
+               if (!dest.empty() && dest.back() == '\n')
+                       dest.pop_back();
+       }
+};
+
+boost::iostreams::composite<remove_empty_lines, detail::truncate_duplicates> uniq()
+{
+       return boost::iostreams::compose(remove_empty_lines(), detail::truncate_duplicates());
+}
+
 std::wstring cpu_info()
 {
-       // TODO: implement
-       return L"Unknown CPU";
+       try
+       {
+               auto num_physical_threads       = consume(cat("/proc/cpuinfo") | grep(L"model name") | wc() | remove_empty_lines());
+               auto processor_names            = consume(cat("/proc/cpuinfo") | grep(L"model name") | cut(L":", 1) | trim() | uniq());
+
+               return processor_names + L" Physical threads: " + num_physical_threads;
+       }
+       catch (...)
+       {
+               return L"Unknown CPU";
+       }
 }
 
 std::wstring system_product_name()
 {
-       // TODO: implement
-       return L"Unknown System";
+       try
+       {
+               return consume(cat("/sys/devices/virtual/dmi/id/product_name") | remove_empty_lines());
+       }
+       catch (...)
+       {
+               return L"Unknown System";
+       }
 }
 
 std::wstring os_description()
 {
-       // TODO: implement
-       return L"Unknown OS";
+       try
+       {
+               return consume(cat("/etc/issue.net") | remove_empty_lines());
+       }
+       catch (...)
+       {
+               return L"Unknown OS";
+       }
 }
 
 }
+