From 2fd8b67424ddf5da39852376a54aa72e6ef5ab2b Mon Sep 17 00:00:00 2001 From: krieiter Date: Mon, 18 Mar 2013 16:27:13 +0900 Subject: [PATCH 01/80] Update README.rst I'm not actually sure whether it's typo or not. Feel free to reject this change. --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index f379f93..8ee618d 100644 --- a/README.rst +++ b/README.rst @@ -27,7 +27,7 @@ Example output:: ^ ^ ^ ^ ^ ^ ^ | | | | | | | - 1 2 3 4 5 6 G + 1 2 3 4 5 6 7 1. Currently used memory. 2. Available memory. From ec28a5615b66e3df6eb1b235c601f91a4fe01b97 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Thu, 4 Apr 2013 19:50:16 -0400 Subject: [PATCH 02/80] Add CMake error on OSX. It is not currently supported. --- CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cfa4780..bc0d70d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,11 @@ if(NOT CMAKE_BUILD_TYPE) FORCE) endif(NOT CMAKE_BUILD_TYPE) +if(APPLE) + message(SEND_ERROR "OSX is currently not supported. Patches are welcome.") +endif() + add_executable(tmux-mem-cpu-load tmux-mem-cpu-load.cpp) install(TARGETS tmux-mem-cpu-load - RUNTIME - DESTINATION bin + RUNTIME DESTINATION bin ) From b00f53193b27f52efb4edfc34774b4191d597743 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Thu, 4 Apr 2013 19:52:38 -0400 Subject: [PATCH 03/80] Add note in README that OSX is not supported. --- README.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 8ee618d..8bf29f3 100644 --- a/README.rst +++ b/README.rst @@ -45,10 +45,13 @@ Installation Dependencies ------------ +Currently only tested on Linux. Mac OSX is known not to work. Patches or +hardware are welcome. + Building ~~~~~~~~ -* >= cmake_ -2.6 +* >= CMake_ -2.6 * C++ compiler (e.g. gcc/g++) @@ -104,5 +107,5 @@ Matt McCormick (thewtex) .. _tmux: http://tmux.sourceforge.net/ -.. _cmake: http://www.cmake.org +.. _CMake: http://www.cmake.org .. _`project homepage`: http://github.com/thewtex/tmux-mem-cpu-load From 86bdac97f82f6cf720eb28d2af527e15e0116eae Mon Sep 17 00:00:00 2001 From: Justin Crawford Date: Mon, 15 Apr 2013 11:33:28 -0700 Subject: [PATCH 04/80] Don't use namespace std. It makes things too confusing. --- CMakeLists.txt | 4 ---- tmux-mem-cpu-load.cpp | 50 +++++++++++++++++++++---------------------- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc0d70d..ea96196 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,10 +11,6 @@ if(NOT CMAKE_BUILD_TYPE) FORCE) endif(NOT CMAKE_BUILD_TYPE) -if(APPLE) - message(SEND_ERROR "OSX is currently not supported. Patches are welcome.") -endif() - add_executable(tmux-mem-cpu-load tmux-mem-cpu-load.cpp) install(TARGETS tmux-mem-cpu-load RUNTIME DESTINATION bin diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 94ffcb5..30c090f 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -18,13 +18,11 @@ #include #include #include -using namespace std; - #include // sleep float cpu_percentage( unsigned int cpu_usage_delay ) { - string stat_line; + std::string stat_line; size_t line_start_pos; size_t line_end_pos; unsigned long long current_user; @@ -39,10 +37,10 @@ float cpu_percentage( unsigned int cpu_usage_delay ) unsigned long long diff_system; unsigned long long diff_nice; unsigned long long diff_idle; - istringstream iss; + std::istringstream iss; - ifstream stat_file("/proc/stat"); - getline(stat_file, stat_line); + std::ifstream stat_file("/proc/stat"); + std::getline(stat_file, stat_line); stat_file.close(); // skip "cpu" @@ -59,7 +57,7 @@ float cpu_percentage( unsigned int cpu_usage_delay ) usleep( cpu_usage_delay ); stat_file.open("/proc/stat"); - getline(stat_file, stat_line); + std::getline(stat_file, stat_line); stat_file.close(); // skip "cpu" @@ -81,16 +79,16 @@ float cpu_percentage( unsigned int cpu_usage_delay ) return static_cast(diff_user + diff_system + diff_nice)/static_cast(diff_user + diff_system + diff_nice + diff_idle)*100.0; } -string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines ) +std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines ) { - string meter( graph_lines + 2, ' ' ); + std::string meter( graph_lines + 2, ' ' ); meter[0] = '['; meter[meter.length() - 1] = ']'; int meter_count = 0; float percentage; - ostringstream oss; + std::ostringstream oss; oss.precision( 1 ); - oss.setf( ios::fixed | ios::right ); + oss.setf( std::ios::fixed | std::ios::right ); percentage = cpu_percentage( cpu_usage_delay ); float meter_step = 99.9 / graph_lines; @@ -109,19 +107,19 @@ string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines ) return oss.str(); } -string mem_string() +std::string mem_string() { unsigned int total_mem; unsigned int used_mem; unsigned int unused_mem; size_t line_start_pos; size_t line_end_pos; - istringstream iss; - ostringstream oss; - string mem_line; + std::istringstream iss; + std::ostringstream oss; + std::string mem_line; - ifstream meminfo_file( "/proc/meminfo" ); - getline( meminfo_file, mem_line ); + std::ifstream meminfo_file( "/proc/meminfo" ); + std::getline( meminfo_file, mem_line ); line_start_pos = mem_line.find_first_of( ':' ); line_start_pos++; line_end_pos = mem_line.find_first_of( 'k' ); @@ -132,7 +130,7 @@ string mem_string() for( unsigned int i = 0; i < 3; i++ ) { - getline( meminfo_file, mem_line ); + std::getline( meminfo_file, mem_line ); line_start_pos = mem_line.find_first_of( ':' ); line_start_pos++; line_end_pos = mem_line.find_first_of( 'k' ); @@ -147,11 +145,11 @@ string mem_string() return oss.str(); } -string load_string() +std::string load_string() { - ifstream loadavg_file( "/proc/loadavg" ); - string load_line; - getline( loadavg_file, load_line ); + std::ifstream loadavg_file( "/proc/loadavg" ); + std::string load_line; + std::getline( loadavg_file, load_line ); loadavg_file.close(); return load_line.substr( 0, 14 ); @@ -163,8 +161,8 @@ int main(int argc, char** argv) unsigned int graph_lines = 10; try { - istringstream iss; - iss.exceptions ( ifstream::failbit | ifstream::badbit ); + std::istringstream iss; + iss.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); if( argc > 1 ) { iss.str( argv[1] ); @@ -179,9 +177,9 @@ int main(int argc, char** argv) iss >> graph_lines; } } - catch(const exception &e) + catch(const std::exception &e) { - cerr << "Usage: " << argv[0] << " [tmux_status-interval(seconds)] [graph lines]" << endl; + std::cerr << "Usage: " << argv[0] << " [tmux_status-interval(seconds)] [graph lines]" << std::endl; return 1; } From c14c56c7efd53989dac3528c94c31ebf8bbe7488 Mon Sep 17 00:00:00 2001 From: Justin Crawford Date: Mon, 15 Apr 2013 11:35:38 -0700 Subject: [PATCH 05/80] Fix the formatting to use tabs instead of spaces, easier to read this way. --- tmux-mem-cpu-load.cpp | 257 +++++++++++++++++++++--------------------- 1 file changed, 129 insertions(+), 128 deletions(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 30c090f..acac931 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -22,169 +22,170 @@ float cpu_percentage( unsigned int cpu_usage_delay ) { - std::string stat_line; - size_t line_start_pos; - size_t line_end_pos; - unsigned long long current_user; - unsigned long long current_system; - unsigned long long current_nice; - unsigned long long current_idle; - unsigned long long next_user; - unsigned long long next_system; - unsigned long long next_nice; - unsigned long long next_idle; - unsigned long long diff_user; - unsigned long long diff_system; - unsigned long long diff_nice; - unsigned long long diff_idle; - std::istringstream iss; + std::string stat_line; + size_t line_start_pos; + size_t line_end_pos; + unsigned long long current_user; + unsigned long long current_system; + unsigned long long current_nice; + unsigned long long current_idle; + unsigned long long next_user; + unsigned long long next_system; + unsigned long long next_nice; + unsigned long long next_idle; + unsigned long long diff_user; + unsigned long long diff_system; + unsigned long long diff_nice; + unsigned long long diff_idle; + std::istringstream iss; - std::ifstream stat_file("/proc/stat"); - std::getline(stat_file, stat_line); - stat_file.close(); + std::ifstream stat_file("/proc/stat"); + std::getline(stat_file, stat_line); + stat_file.close(); - // skip "cpu" - line_start_pos = stat_line.find_first_not_of(" ", 3); - line_end_pos = stat_line.find_first_of(' ', line_start_pos); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); + // skip "cpu" + line_start_pos = stat_line.find_first_not_of(" ", 3); + line_end_pos = stat_line.find_first_of(' ', line_start_pos); + line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); + line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); + line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); - iss >> current_user >> current_nice >> current_system >> current_idle; - iss.clear(); + iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); + iss >> current_user >> current_nice >> current_system >> current_idle; + iss.clear(); - usleep( cpu_usage_delay ); + usleep( cpu_usage_delay ); - stat_file.open("/proc/stat"); - std::getline(stat_file, stat_line); - stat_file.close(); + stat_file.open("/proc/stat"); + std::getline(stat_file, stat_line); + stat_file.close(); - // skip "cpu" - line_start_pos = stat_line.find_first_not_of(" ", 3); - line_end_pos = stat_line.find_first_of(' ', line_start_pos); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); + // skip "cpu" + line_start_pos = stat_line.find_first_not_of(" ", 3); + line_end_pos = stat_line.find_first_of(' ', line_start_pos); + line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); + line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); + line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); - iss >> next_user >> next_nice >> next_system >> next_idle; - iss.clear(); + iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); + iss >> next_user >> next_nice >> next_system >> next_idle; + iss.clear(); - diff_user = next_user - current_user; - diff_system = next_system - current_system; - diff_nice = next_nice - current_nice; - diff_idle = next_idle - current_idle; + diff_user = next_user - current_user; + diff_system = next_system - current_system; + diff_nice = next_nice - current_nice; + diff_idle = next_idle - current_idle; - return static_cast(diff_user + diff_system + diff_nice)/static_cast(diff_user + diff_system + diff_nice + diff_idle)*100.0; + return static_cast(diff_user + diff_system + diff_nice)/static_cast(diff_user + diff_system + diff_nice + diff_idle)*100.0; } std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines ) { - std::string meter( graph_lines + 2, ' ' ); - meter[0] = '['; - meter[meter.length() - 1] = ']'; - int meter_count = 0; - float percentage; - std::ostringstream oss; - oss.precision( 1 ); - oss.setf( std::ios::fixed | std::ios::right ); + std::string meter( graph_lines + 2, ' ' ); + meter[0] = '['; + meter[meter.length() - 1] = ']'; + int meter_count = 0; + float percentage; + std::ostringstream oss; + oss.precision( 1 ); + oss.setf( std::ios::fixed | std::ios::right ); - percentage = cpu_percentage( cpu_usage_delay ); - float meter_step = 99.9 / graph_lines; - meter_count = 1; - while(meter_count*meter_step < percentage) - { - meter[meter_count] = '|'; - meter_count++; - } + percentage = cpu_percentage( cpu_usage_delay ); + float meter_step = 99.9 / graph_lines; + meter_count = 1; + while(meter_count*meter_step < percentage) + { + meter[meter_count] = '|'; + meter_count++; + } - oss << meter; - oss.width( 5 ); - oss << percentage; - oss << "%"; + oss << meter; + oss.width( 5 ); + oss << percentage; + oss << "%"; - return oss.str(); + return oss.str(); } std::string mem_string() { - unsigned int total_mem; - unsigned int used_mem; - unsigned int unused_mem; - size_t line_start_pos; - size_t line_end_pos; - std::istringstream iss; - std::ostringstream oss; - std::string mem_line; + unsigned int total_mem; + unsigned int used_mem; + unsigned int unused_mem; + size_t line_start_pos; + size_t line_end_pos; + std::istringstream iss; + std::ostringstream oss; + std::string mem_line; - std::ifstream meminfo_file( "/proc/meminfo" ); - std::getline( meminfo_file, mem_line ); - line_start_pos = mem_line.find_first_of( ':' ); - line_start_pos++; - line_end_pos = mem_line.find_first_of( 'k' ); - iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); - iss >> total_mem; + std::ifstream meminfo_file( "/proc/meminfo" ); + std::getline( meminfo_file, mem_line ); + line_start_pos = mem_line.find_first_of( ':' ); + line_start_pos++; + line_end_pos = mem_line.find_first_of( 'k' ); + iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); + iss >> total_mem; - used_mem = total_mem; + used_mem = total_mem; - for( unsigned int i = 0; i < 3; i++ ) - { - std::getline( meminfo_file, mem_line ); - line_start_pos = mem_line.find_first_of( ':' ); - line_start_pos++; - line_end_pos = mem_line.find_first_of( 'k' ); - iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); - iss >> unused_mem; - used_mem -= unused_mem; - } - meminfo_file.close(); + for( unsigned int i = 0; i < 3; i++ ) + { + std::getline( meminfo_file, mem_line ); + line_start_pos = mem_line.find_first_of( ':' ); + line_start_pos++; + line_end_pos = mem_line.find_first_of( 'k' ); + iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); + iss >> unused_mem; + used_mem -= unused_mem; + } + meminfo_file.close(); - oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; + oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; - return oss.str(); + return oss.str(); } std::string load_string() { - std::ifstream loadavg_file( "/proc/loadavg" ); - std::string load_line; - std::getline( loadavg_file, load_line ); - loadavg_file.close(); + std::ifstream loadavg_file( "/proc/loadavg" ); + std::string load_line; + std::getline( loadavg_file, load_line ); + loadavg_file.close(); - return load_line.substr( 0, 14 ); + return load_line.substr( 0, 14 ); } int main(int argc, char** argv) { - unsigned int cpu_usage_delay = 900000; - unsigned int graph_lines = 10; - try - { - std::istringstream iss; - iss.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); - if( argc > 1 ) - { - iss.str( argv[1] ); - unsigned int status_interval; - iss >> status_interval; - cpu_usage_delay = status_interval * 1000000 - 100000; - } - if( argc > 2 ) - { - iss.str( argv[2] ); - iss.clear(); - iss >> graph_lines; - } - } - catch(const std::exception &e) - { - std::cerr << "Usage: " << argv[0] << " [tmux_status-interval(seconds)] [graph lines]" << std::endl; - return 1; - } + unsigned int cpu_usage_delay = 900000; + unsigned int graph_lines = 10; + try + { + std::istringstream iss; + iss.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); + if( argc > 1 ) + { + iss.str( argv[1] ); + unsigned int status_interval; + iss >> status_interval; + cpu_usage_delay = status_interval * 1000000 - 100000; + } - std::cout << mem_string() << ' ' << cpu_string( cpu_usage_delay, graph_lines ) << ' ' << load_string(); + if( argc > 2 ) + { + iss.str( argv[2] ); + iss.clear(); + iss >> graph_lines; + } + } + catch(const std::exception &e) + { + std::cerr << "Usage: " << argv[0] << " [tmux_status-interval(seconds)] [graph lines]" << std::endl; + return 1; + } - return 0; + std::cout << mem_string() << ' ' << cpu_string( cpu_usage_delay, graph_lines ) << ' ' << load_string(); + + return 0; } From 06ebd3e9abc6e51cae452086f98fcdb5ce7e83f9 Mon Sep 17 00:00:00 2001 From: Justin Crawford Date: Mon, 15 Apr 2013 12:15:31 -0700 Subject: [PATCH 06/80] Mac OS X support and BSD function stubs Reorder the functions, begin OS X specific functions Load averages and Memory usage now works on OSX (I hope the calculations are correct) Minor edits Finish OSX support - Fixes CPU usage --- tmux-mem-cpu-load.cpp | 290 ++++++++++++++++++++++++++++++++---------- 1 file changed, 224 insertions(+), 66 deletions(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index acac931..52ee5b0 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -19,6 +19,228 @@ #include #include #include // sleep +#include // for floorf + +// Apple specific. +#if defined(__APPLE__) && defined(__MACH__) +// Mach kernel includes for getting memory and CPU statistics +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include // for sysctl +# include // for integer types +#endif + +// if we are on a BSD system +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +// TODO: Includes and *BSD support +# define BSD_BASED 1 +#endif + +// Function declarations for global use. +float cpu_percentage( unsigned int cpu_usage_delay ); +std::string mem_string(); +std::string load_string(); + +// This function is platform independent and therefore can be placed at the top +std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines ) +{ + std::string meter( graph_lines + 2, ' ' ); + meter[0] = '['; + meter[meter.length() - 1] = ']'; + int meter_count = 0; + float percentage; + std::ostringstream oss; + oss.precision( 1 ); + oss.setf( std::ios::fixed | std::ios::right ); + + percentage = cpu_percentage( cpu_usage_delay ); + float meter_step = 99.9 / graph_lines; + meter_count = 1; + while(meter_count*meter_step < percentage) + { + meter[meter_count] = '|'; + meter_count++; + } + + oss << meter; + oss.width( 5 ); + oss << percentage; + oss << "%"; + + return oss.str(); +} + +#if defined(BSD_BASED) || (defined(__APPLE__) && defined(__MACH__)) +// OSX or BSD based system, use BSD APIs instead + +#if defined(__APPLE__) && defined(__MACH__) +std::string mem_string() +{ + // These values are in bytes + int64_t total_mem; + int64_t used_mem; + int64_t unused_mem; + // blah + vm_size_t page_size; + mach_port_t mach_port; + mach_msg_type_number_t count; + vm_statistics_data_t vm_stats; + std::ostringstream oss; + + // Get total physical memory + int mib[2]; + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + size_t length = sizeof(int64_t); + sysctl(mib, 2, &total_mem, &length, NULL, 0); + + mach_port = mach_host_self(); + count = sizeof(vm_stats) / sizeof(natural_t); + if (KERN_SUCCESS == host_page_size(mach_port, &page_size) && + KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count)) + { + unused_mem = (int64_t)vm_stats.free_count * (int64_t)page_size; + + used_mem = ((int64_t)vm_stats.active_count + + (int64_t)vm_stats.inactive_count + + (int64_t)vm_stats.wire_count) * (int64_t)page_size; + } + + oss << used_mem / 1024 / 1024 << '/' << total_mem / 1024 / 1024 << "MB"; + + return oss.str(); +} + +// See: http://www.opensource.apple.com/source/xnu/xnu-201/osfmk/mach/host_info.h +// and: http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/ +host_cpu_load_info_data_t _get_cpu_percentage() +{ + kern_return_t error; + mach_msg_type_number_t count; + host_cpu_load_info_data_t r_load; + mach_port_t mach_port; + + count = HOST_CPU_LOAD_INFO_COUNT; + mach_port = mach_host_self(); + error = host_statistics(mach_port, HOST_CPU_LOAD_INFO, (host_info_t)&r_load, &count); + if (error != KERN_SUCCESS) + return host_cpu_load_info_data_t(); + + return r_load; +} + +float cpu_percentage( unsigned int cpu_usage_delay ) +{ + // Get the load times from the XNU kernel + host_cpu_load_info_data_t load1 = _get_cpu_percentage(); + usleep(cpu_usage_delay); + host_cpu_load_info_data_t load2 = _get_cpu_percentage(); + + // Current load times + unsigned long long current_user = load1.cpu_ticks[CPU_STATE_USER]; + unsigned long long current_system = load1.cpu_ticks[CPU_STATE_SYSTEM]; + unsigned long long current_nice = load1.cpu_ticks[CPU_STATE_NICE]; + unsigned long long current_idle = load1.cpu_ticks[CPU_STATE_IDLE]; + // Next load times + unsigned long long next_user = load2.cpu_ticks[CPU_STATE_USER]; + unsigned long long next_system = load2.cpu_ticks[CPU_STATE_SYSTEM]; + unsigned long long next_nice = load2.cpu_ticks[CPU_STATE_NICE]; + unsigned long long next_idle = load2.cpu_ticks[CPU_STATE_IDLE]; + // Difference between the two + unsigned long long diff_user = next_user - current_user; + unsigned long long diff_system = next_system - current_system; + unsigned long long diff_nice = next_nice - current_nice; + unsigned long long diff_idle = next_idle - current_idle; + + return static_cast(diff_user + diff_system + diff_nice)/static_cast(diff_user + diff_system + diff_nice + diff_idle)*100.0; +} + +#else // APPLE + +// BSD type systems (FreeBSD/NetBSD/OpenBSD) +// Incomplete +float cpu_percentage( unsigned int cpu_usage_delay ) +{ + return 0.0f; +} + +std::string mem_string() +{ + return "0/0 MB"; +} + +#endif // APPLE + +// Both apple and BSD style systems have these api calls +std::string load_string() +{ + std::stringstream ss; + // Only get 3 load averages + int nelem = 3; + double averages[3]; + // based on: http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c + if(getloadavg(averages, nelem) < 0) + ss << "0.00 0.00 0.00"; // couldn't get averages. + else + { + for(int i = 0; i < nelem; ++i) + { + // Round to nearest, make sure this is only a 0.00 value not a 0.0000 + float avg = floorf(static_cast(averages[i]) * 100 + 0.5) / 100; + ss << avg << " "; + } + } + + return ss.str(); +} + +#else // APPLE || BSD_BASED + +// Linux based system, if it's windows, too much work, they can deal with their compile errors - CMD sucks anyway. +std::string mem_string() +{ + unsigned int total_mem; + unsigned int used_mem; + unsigned int unused_mem; + size_t line_start_pos; + size_t line_end_pos; + std::istringstream iss; + std::ostringstream oss; + std::string mem_line; + + std::ifstream meminfo_file( "/proc/meminfo" ); + std::getline( meminfo_file, mem_line ); + line_start_pos = mem_line.find_first_of( ':' ); + line_start_pos++; + line_end_pos = mem_line.find_first_of( 'k' ); + iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); + iss >> total_mem; + + used_mem = total_mem; + + for( unsigned int i = 0; i < 3; i++ ) + { + std::getline( meminfo_file, mem_line ); + line_start_pos = mem_line.find_first_of( ':' ); + line_start_pos++; + line_end_pos = mem_line.find_first_of( 'k' ); + iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); + iss >> unused_mem; + used_mem -= unused_mem; + } + meminfo_file.close(); + + oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; + + return oss.str(); +} float cpu_percentage( unsigned int cpu_usage_delay ) { @@ -79,72 +301,6 @@ float cpu_percentage( unsigned int cpu_usage_delay ) return static_cast(diff_user + diff_system + diff_nice)/static_cast(diff_user + diff_system + diff_nice + diff_idle)*100.0; } -std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines ) -{ - std::string meter( graph_lines + 2, ' ' ); - meter[0] = '['; - meter[meter.length() - 1] = ']'; - int meter_count = 0; - float percentage; - std::ostringstream oss; - oss.precision( 1 ); - oss.setf( std::ios::fixed | std::ios::right ); - - percentage = cpu_percentage( cpu_usage_delay ); - float meter_step = 99.9 / graph_lines; - meter_count = 1; - while(meter_count*meter_step < percentage) - { - meter[meter_count] = '|'; - meter_count++; - } - - oss << meter; - oss.width( 5 ); - oss << percentage; - oss << "%"; - - return oss.str(); -} - -std::string mem_string() -{ - unsigned int total_mem; - unsigned int used_mem; - unsigned int unused_mem; - size_t line_start_pos; - size_t line_end_pos; - std::istringstream iss; - std::ostringstream oss; - std::string mem_line; - - std::ifstream meminfo_file( "/proc/meminfo" ); - std::getline( meminfo_file, mem_line ); - line_start_pos = mem_line.find_first_of( ':' ); - line_start_pos++; - line_end_pos = mem_line.find_first_of( 'k' ); - iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); - iss >> total_mem; - - used_mem = total_mem; - - for( unsigned int i = 0; i < 3; i++ ) - { - std::getline( meminfo_file, mem_line ); - line_start_pos = mem_line.find_first_of( ':' ); - line_start_pos++; - line_end_pos = mem_line.find_first_of( 'k' ); - iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); - iss >> unused_mem; - used_mem -= unused_mem; - } - meminfo_file.close(); - - oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; - - return oss.str(); -} - std::string load_string() { std::ifstream loadavg_file( "/proc/loadavg" ); @@ -155,6 +311,8 @@ std::string load_string() return load_line.substr( 0, 14 ); } +#endif // BSD + int main(int argc, char** argv) { unsigned int cpu_usage_delay = 900000; From 1155ca7c77be4f7e065b178ce285f93a6e6ed8ef Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sun, 9 Jun 2013 20:58:47 -0400 Subject: [PATCH 07/80] Output error on graph_lines < 1. Issue #3. --- tmux-mem-cpu-load.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 501ae64..93ae588 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -358,7 +358,7 @@ std::string load_string( bool use_colors ) int main(int argc, char** argv) { unsigned int cpu_usage_delay = 900000; - unsigned int graph_lines = 10; + int graph_lines = 10; bool use_colors = false; try { @@ -387,6 +387,11 @@ int main(int argc, char** argv) iss.str( argv[arg_index] ); iss.clear(); iss >> graph_lines; + if( graph_lines < 1 ) + { + std::cerr << "graph lines argument must be one or greater." << std::endl; + return 1; + } } } catch(const std::exception &e) From 365502dbf8955c49d82bbe4df9686b82944e3739 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sun, 9 Jun 2013 21:01:32 -0400 Subject: [PATCH 08/80] Use EXIT_SUCCESS/EXIT_FAILURE. --- tmux-mem-cpu-load.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 93ae588..d478d7e 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -21,6 +21,7 @@ #include #include // sleep #include // for floorf +#include // EXIT_SUCCESS // Apple specific. #if defined(__APPLE__) && defined(__MACH__) @@ -390,18 +391,18 @@ int main(int argc, char** argv) if( graph_lines < 1 ) { std::cerr << "graph lines argument must be one or greater." << std::endl; - return 1; + return EXIT_FAILURE; } } } catch(const std::exception &e) { std::cerr << "Usage: " << argv[0] << " [--colors] [tmux_status-interval(seconds)] [graph lines]" << std::endl; - return 1; + return EXIT_FAILURE; } std::cout << mem_string( use_colors ) << ' ' << cpu_string( cpu_usage_delay, graph_lines, use_colors ) << ' ' << load_string( use_colors ); - return 0; + return EXIT_SUCCESS; } From beea1a7cae477b5f724665f4b8c1cd7beac14441 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sun, 9 Jun 2013 22:24:28 -0400 Subject: [PATCH 09/80] Output error on status interval < 1. --- tmux-mem-cpu-load.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index d478d7e..fbd49f7 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -378,8 +378,13 @@ int main(int argc, char** argv) if( argc > arg_index ) { iss.str( argv[arg_index] ); - unsigned int status_interval; + int status_interval; iss >> status_interval; + if( status_interval < 1 ) + { + std::cerr << "Status interval argument must be one or greater." << std::endl; + return EXIT_FAILURE; + } cpu_usage_delay = status_interval * 1000000 - 100000; ++arg_index; } @@ -390,7 +395,7 @@ int main(int argc, char** argv) iss >> graph_lines; if( graph_lines < 1 ) { - std::cerr << "graph lines argument must be one or greater." << std::endl; + std::cerr << "Graph lines argument must be one or greater." << std::endl; return EXIT_FAILURE; } } From e5f3dc1503edf2310a3f768483d649e579e9a307 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sun, 9 Jun 2013 22:50:03 -0400 Subject: [PATCH 10/80] Add tests. --- CMakeLists.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index eacc923..36e1a72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,3 +17,29 @@ add_executable(tmux-mem-cpu-load tmux-mem-cpu-load.cpp) install(TARGETS tmux-mem-cpu-load RUNTIME DESTINATION bin ) + +include( CTest ) +if( BUILD_TESTING ) + add_test( NAME usage + COMMAND tmux-mem-cpu-load -h ) + + add_test( NAME no_arguments + COMMAND tmux-mem-cpu-load ) + + add_test( NAME colors + COMMAND tmux-mem-cpu-load --colors ) + + add_test( NAME arguments + COMMAND tmux-mem-cpu-load --colors 1 4 ) + + add_test( NAME invalid_status_interval + COMMAND tmux-mem-cpu-load -1 4 ) + + add_test( NAME invalid_graph_lines + COMMAND tmux-mem-cpu-load 1 -4 ) + + set_tests_properties( usage + invalid_status_interval + invalid_graph_lines + PROPERTIES WILL_FAIL TRUE ) +endif() From f95aa23b7586f918f747cac63533a8b9d895a8da Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sun, 9 Jun 2013 22:55:08 -0400 Subject: [PATCH 11/80] Update README to note OSX is now supported. --- README.rst | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/README.rst b/README.rst index f0c4adf..6816a36 100644 --- a/README.rst +++ b/README.rst @@ -5,12 +5,9 @@ CPU, RAM memory, and load monitor for use with tmux_ ---------------------------------------------------- - - Description =========== - A simple, lightweight program provided for system monitoring in the *status* line of **tmux**. @@ -44,12 +41,10 @@ passing the **--colors** flag. Installation ============ - Dependencies ------------ -Currently only tested on Linux. Mac OSX is known not to work. Patches or -hardware are welcome. +Currently, Linux and Mac OSX are supported. Building ~~~~~~~~ @@ -57,13 +52,11 @@ Building * >= CMake_ -2.6 * C++ compiler (e.g. gcc/g++) - Download -------- There are links to the source code at the `project homepage`_. - Build ----- @@ -73,7 +66,6 @@ Build cmake . make - Install ------- @@ -84,10 +76,8 @@ Install logout - Configuring tmux_ -======================= - +================= Edit ``$HOME/.tmux.conf`` to display the program's output in *status-left* or *status-right*. For example:: From 8418e297ad19385ebb26904e23f63a7766fde8a0 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sun, 9 Jun 2013 22:57:37 -0400 Subject: [PATCH 12/80] Add contributors to README. --- README.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.rst b/README.rst index 6816a36..de59c21 100644 --- a/README.rst +++ b/README.rst @@ -98,6 +98,11 @@ Author Matt McCormick (thewtex) +Contributions from: + +* Justin Crawford +* krieiter + .. _tmux: http://tmux.sourceforge.net/ .. _CMake: http://www.cmake.org From 4bb0a7676fd5a0e1cbadf636f27e07cccc00e02c Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Tue, 11 Jun 2013 00:12:51 -0400 Subject: [PATCH 13/80] Add load_line variable for OSX. --- tmux-mem-cpu-load.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index fbd49f7..8819c82 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -316,6 +316,8 @@ std::string load_string( bool use_colors ) oss << avg << " "; } } + std::string load_line( oss.str() ); + oss.str( "" ); #else // Linux std::ifstream loadavg_file( "/proc/loadavg" ); From 6f00fc1daa960dec6671d4e2eeeb53e1b575f702 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Fri, 14 Jun 2013 01:49:10 +0000 Subject: [PATCH 14/80] Add .travis.yml. --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..862f2ec --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: cpp +compiler: + - gcc + - clang +script: + - mkdir build + - cd build + - cmake -DCMAKE_INSTALL_PREFIX:PATH=../install .. + - cmake --build . --target install + - ctest -V From c07c80b662f950c527cc5de823631f1804b13cda Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Fri, 14 Jun 2013 01:56:46 +0000 Subject: [PATCH 15/80] Do not run ctest in Travis. The workers apparently do not present themselves as a full linux system. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 862f2ec..8449770 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,3 @@ script: - cd build - cmake -DCMAKE_INSTALL_PREFIX:PATH=../install .. - cmake --build . --target install - - ctest -V From c81bcc3d84fefb9e25cd5d76633b005c6ae1c990 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Fri, 14 Jun 2013 02:07:07 +0000 Subject: [PATCH 16/80] Add Travis icon to README. --- README.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.rst b/README.rst index de59c21..5ca3d4e 100644 --- a/README.rst +++ b/README.rst @@ -5,6 +5,9 @@ CPU, RAM memory, and load monitor for use with tmux_ ---------------------------------------------------- +.. image:: https://travis-ci.org/thewtex/tmux-mem-cpu-load.png + :target: https://travis-ci.org/thewtex/tmux-mem-cpu-load + Description =========== From fac8da7a0c64ba8a06ac0845fcd686c033352ade Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Mon, 15 Jul 2013 23:20:35 +0000 Subject: [PATCH 17/80] Improve foreground contrast with colors. A brightwhite is needed for the white text to have enough contrast. It also allows for non-bright black, which also has better contrast. --- README.rst | 2 +- generate-luts.py | 6 +- luts.h | 300 +++++++++++++++++++++++------------------------ 3 files changed, 154 insertions(+), 154 deletions(-) diff --git a/README.rst b/README.rst index 5ca3d4e..835b2fa 100644 --- a/README.rst +++ b/README.rst @@ -86,7 +86,7 @@ Edit ``$HOME/.tmux.conf`` to display the program's output in *status-left* or *status-right*. For example:: set -g status-interval 2 - set -g status-left "#S #[fg=green,bg=black,bright]#(tmux-mem-cpu-load --colors 2)#[default]" + set -g status-left "#S #[fg=green,bg=black]#(tmux-mem-cpu-load --colors 2)#[default]" Note that the first argument to `tmux-mem-cpu-load` should be the same number of seconds that *status-interval* is set at. diff --git a/generate-luts.py b/generate-luts.py index 477c6e0..8ce00d5 100755 --- a/generate-luts.py +++ b/generate-luts.py @@ -36,8 +36,8 @@ with open('luts.h', 'w') as fp: # hot colormap with white fg for the first half # and black fg for the second half - write_table(fp, 'hot', 'cpu_percentage', 'white', 'black') - write_table(fp, 'gist_earth', 'mem', 'white', 'black') - write_table(fp, 'bone', 'load', 'white', 'black') + write_table(fp, 'hot', 'cpu_percentage', 'brightwhite', 'black') + write_table(fp, 'gist_earth', 'mem', 'brightwhite', 'black') + write_table(fp, 'bone', 'load', 'brightwhite', 'black') fp.write('#endif\n') diff --git a/luts.h b/luts.h index 1bf2945..0c99e08 100644 --- a/luts.h +++ b/luts.h @@ -2,56 +2,56 @@ #define _luts_h static const char cpu_percentage_lut[][32] = { -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour52]", -"#[fg=white,bg=colour52]", -"#[fg=white,bg=colour52]", -"#[fg=white,bg=colour52]", -"#[fg=white,bg=colour52]", -"#[fg=white,bg=colour52]", -"#[fg=white,bg=colour52]", -"#[fg=white,bg=colour52]", -"#[fg=white,bg=colour88]", -"#[fg=white,bg=colour88]", -"#[fg=white,bg=colour88]", -"#[fg=white,bg=colour88]", -"#[fg=white,bg=colour88]", -"#[fg=white,bg=colour88]", -"#[fg=white,bg=colour88]", -"#[fg=white,bg=colour124]", -"#[fg=white,bg=colour124]", -"#[fg=white,bg=colour124]", -"#[fg=white,bg=colour124]", -"#[fg=white,bg=colour124]", -"#[fg=white,bg=colour124]", -"#[fg=white,bg=colour124]", -"#[fg=white,bg=colour160]", -"#[fg=white,bg=colour160]", -"#[fg=white,bg=colour160]", -"#[fg=white,bg=colour160]", -"#[fg=white,bg=colour160]", -"#[fg=white,bg=colour160]", -"#[fg=white,bg=colour160]", -"#[fg=white,bg=colour160]", -"#[fg=white,bg=colour196]", -"#[fg=white,bg=colour196]", -"#[fg=white,bg=colour196]", -"#[fg=white,bg=colour196]", -"#[fg=white,bg=colour196]", -"#[fg=white,bg=colour196]", -"#[fg=white,bg=colour196]", -"#[fg=white,bg=colour196]", -"#[fg=white,bg=colour202]", -"#[fg=white,bg=colour202]", -"#[fg=white,bg=colour202]", -"#[fg=white,bg=colour202]", -"#[fg=white,bg=colour202]", -"#[fg=white,bg=colour202]", -"#[fg=white,bg=colour202]", -"#[fg=white,bg=colour202]", -"#[fg=white,bg=colour208]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour52]", +"#[fg=brightwhite,bg=colour52]", +"#[fg=brightwhite,bg=colour52]", +"#[fg=brightwhite,bg=colour52]", +"#[fg=brightwhite,bg=colour52]", +"#[fg=brightwhite,bg=colour52]", +"#[fg=brightwhite,bg=colour52]", +"#[fg=brightwhite,bg=colour52]", +"#[fg=brightwhite,bg=colour88]", +"#[fg=brightwhite,bg=colour88]", +"#[fg=brightwhite,bg=colour88]", +"#[fg=brightwhite,bg=colour88]", +"#[fg=brightwhite,bg=colour88]", +"#[fg=brightwhite,bg=colour88]", +"#[fg=brightwhite,bg=colour88]", +"#[fg=brightwhite,bg=colour124]", +"#[fg=brightwhite,bg=colour124]", +"#[fg=brightwhite,bg=colour124]", +"#[fg=brightwhite,bg=colour124]", +"#[fg=brightwhite,bg=colour124]", +"#[fg=brightwhite,bg=colour124]", +"#[fg=brightwhite,bg=colour124]", +"#[fg=brightwhite,bg=colour160]", +"#[fg=brightwhite,bg=colour160]", +"#[fg=brightwhite,bg=colour160]", +"#[fg=brightwhite,bg=colour160]", +"#[fg=brightwhite,bg=colour160]", +"#[fg=brightwhite,bg=colour160]", +"#[fg=brightwhite,bg=colour160]", +"#[fg=brightwhite,bg=colour160]", +"#[fg=brightwhite,bg=colour196]", +"#[fg=brightwhite,bg=colour196]", +"#[fg=brightwhite,bg=colour196]", +"#[fg=brightwhite,bg=colour196]", +"#[fg=brightwhite,bg=colour196]", +"#[fg=brightwhite,bg=colour196]", +"#[fg=brightwhite,bg=colour196]", +"#[fg=brightwhite,bg=colour196]", +"#[fg=brightwhite,bg=colour202]", +"#[fg=brightwhite,bg=colour202]", +"#[fg=brightwhite,bg=colour202]", +"#[fg=brightwhite,bg=colour202]", +"#[fg=brightwhite,bg=colour202]", +"#[fg=brightwhite,bg=colour202]", +"#[fg=brightwhite,bg=colour202]", +"#[fg=brightwhite,bg=colour202]", +"#[fg=brightwhite,bg=colour208]", "#[fg=black,bg=colour208]", "#[fg=black,bg=colour208]", "#[fg=black,bg=colour208]", @@ -106,56 +106,56 @@ static const char cpu_percentage_lut[][32] = { }; // end cpu_percentage_lut static const char mem_lut[][32] = { -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour17]", -"#[fg=white,bg=colour18]", -"#[fg=white,bg=colour18]", -"#[fg=white,bg=colour18]", -"#[fg=white,bg=colour18]", -"#[fg=white,bg=colour18]", -"#[fg=white,bg=colour18]", -"#[fg=white,bg=colour24]", -"#[fg=white,bg=colour24]", -"#[fg=white,bg=colour24]", -"#[fg=white,bg=colour24]", -"#[fg=white,bg=colour24]", -"#[fg=white,bg=colour24]", -"#[fg=white,bg=colour24]", -"#[fg=white,bg=colour24]", -"#[fg=white,bg=colour60]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour66]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour72]", -"#[fg=white,bg=colour71]", -"#[fg=white,bg=colour71]", -"#[fg=white,bg=colour71]", -"#[fg=white,bg=colour107]", -"#[fg=white,bg=colour107]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour17]", +"#[fg=brightwhite,bg=colour18]", +"#[fg=brightwhite,bg=colour18]", +"#[fg=brightwhite,bg=colour18]", +"#[fg=brightwhite,bg=colour18]", +"#[fg=brightwhite,bg=colour18]", +"#[fg=brightwhite,bg=colour18]", +"#[fg=brightwhite,bg=colour24]", +"#[fg=brightwhite,bg=colour24]", +"#[fg=brightwhite,bg=colour24]", +"#[fg=brightwhite,bg=colour24]", +"#[fg=brightwhite,bg=colour24]", +"#[fg=brightwhite,bg=colour24]", +"#[fg=brightwhite,bg=colour24]", +"#[fg=brightwhite,bg=colour24]", +"#[fg=brightwhite,bg=colour60]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour66]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour72]", +"#[fg=brightwhite,bg=colour71]", +"#[fg=brightwhite,bg=colour71]", +"#[fg=brightwhite,bg=colour71]", +"#[fg=brightwhite,bg=colour107]", +"#[fg=brightwhite,bg=colour107]", "#[fg=black,bg=colour107]", "#[fg=black,bg=colour107]", "#[fg=black,bg=colour108]", @@ -210,56 +210,56 @@ static const char mem_lut[][32] = { }; // end mem_lut static const char load_lut[][32] = { -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour16]", -"#[fg=white,bg=colour17]", -"#[fg=white,bg=colour17]", -"#[fg=white,bg=colour17]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour59]", -"#[fg=white,bg=colour60]", -"#[fg=white,bg=colour60]", -"#[fg=white,bg=colour60]", -"#[fg=white,bg=colour60]", -"#[fg=white,bg=colour60]", -"#[fg=white,bg=colour60]", -"#[fg=white,bg=colour60]", -"#[fg=white,bg=colour60]", -"#[fg=white,bg=colour60]", -"#[fg=white,bg=colour60]", -"#[fg=white,bg=colour102]", -"#[fg=white,bg=colour102]", -"#[fg=white,bg=colour102]", -"#[fg=white,bg=colour102]", -"#[fg=white,bg=colour102]", -"#[fg=white,bg=colour102]", -"#[fg=white,bg=colour102]", -"#[fg=white,bg=colour102]", -"#[fg=white,bg=colour103]", -"#[fg=white,bg=colour103]", -"#[fg=white,bg=colour103]", -"#[fg=white,bg=colour103]", -"#[fg=white,bg=colour103]", -"#[fg=white,bg=colour103]", -"#[fg=white,bg=colour103]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour16]", +"#[fg=brightwhite,bg=colour17]", +"#[fg=brightwhite,bg=colour17]", +"#[fg=brightwhite,bg=colour17]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour59]", +"#[fg=brightwhite,bg=colour60]", +"#[fg=brightwhite,bg=colour60]", +"#[fg=brightwhite,bg=colour60]", +"#[fg=brightwhite,bg=colour60]", +"#[fg=brightwhite,bg=colour60]", +"#[fg=brightwhite,bg=colour60]", +"#[fg=brightwhite,bg=colour60]", +"#[fg=brightwhite,bg=colour60]", +"#[fg=brightwhite,bg=colour60]", +"#[fg=brightwhite,bg=colour60]", +"#[fg=brightwhite,bg=colour102]", +"#[fg=brightwhite,bg=colour102]", +"#[fg=brightwhite,bg=colour102]", +"#[fg=brightwhite,bg=colour102]", +"#[fg=brightwhite,bg=colour102]", +"#[fg=brightwhite,bg=colour102]", +"#[fg=brightwhite,bg=colour102]", +"#[fg=brightwhite,bg=colour102]", +"#[fg=brightwhite,bg=colour103]", +"#[fg=brightwhite,bg=colour103]", +"#[fg=brightwhite,bg=colour103]", +"#[fg=brightwhite,bg=colour103]", +"#[fg=brightwhite,bg=colour103]", +"#[fg=brightwhite,bg=colour103]", +"#[fg=brightwhite,bg=colour103]", "#[fg=black,bg=colour103]", "#[fg=black,bg=colour103]", "#[fg=black,bg=colour109]", From a7200d2364677bb1387af3bce57443cabdbab2bd Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Mon, 15 Jul 2013 23:23:11 +0000 Subject: [PATCH 18/80] Change the default build type to MinSizeRel. This changes the output size of the executable from 52K to 32K for GCC 4.6.3. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 36e1a72..a9d2c3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ endif(COMMAND cmake_policy) project( tmux-mem-cpu-load ) if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release CACHE STRING + set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) endif(NOT CMAKE_BUILD_TYPE) From fed7b88ccd80f493086052eb33b5e8be4a427b60 Mon Sep 17 00:00:00 2001 From: l0ner Date: Mon, 14 Apr 2014 20:47:51 +0200 Subject: [PATCH 19/80] .gitignore add Version generation by cmake system type detection in cmake Split file code for better management --- .gitignore | 48 +++++++++++++++++++++++++++++++++++++ linux/cpu.cc | 50 ++++++++++++++++++++++++++++++++++++++ linux/cpu.h | 6 +++++ linux/load.cc | 38 +++++++++++++++++++++++++++++ linux/load.h | 8 +++++++ linux/memory.cc | 49 +++++++++++++++++++++++++++++++++++++ linux/memory.h | 8 +++++++ osx/cpu.cc | 60 ++++++++++++++++++++++++++++++++++++++++++++++ osx/cpu.h | 6 +++++ osx/load.cc | 61 ++++++++++++++++++++++++++++++++++++++++++++++ osx/load.h | 8 +++++++ osx/memory.cc | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ osx/memory.h | 8 +++++++ version.h.in | 5 ++++ 14 files changed, 419 insertions(+) create mode 100644 .gitignore create mode 100644 linux/cpu.cc create mode 100644 linux/cpu.h create mode 100644 linux/load.cc create mode 100644 linux/load.h create mode 100644 linux/memory.cc create mode 100644 linux/memory.h create mode 100644 osx/cpu.cc create mode 100644 osx/cpu.h create mode 100644 osx/load.cc create mode 100644 osx/load.h create mode 100644 osx/memory.cc create mode 100644 osx/memory.h create mode 100644 version.h.in diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..52d6332 --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +# Compiled source # +################### +*.com +*.class +*.dll +*.exe +*.o +*.so +sysstat + +# CMake generated # +################### +CMakeFiles +Makefile +cmake_install.cmake +CMakeCache.txt +install_manifest.txt +version.h + +# Packages # +############ +# it's better to unpack this files and commit raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.rar +*.tar +*.zip + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +*.swp +*.swo diff --git a/linux/cpu.cc b/linux/cpu.cc new file mode 100644 index 0000000..a2b549d --- /dev/null +++ b/linux/cpu.cc @@ -0,0 +1,50 @@ +#include +#include +#include // usleep + +#include "cpu.h" + +float cpu_percentage( unsigned cpu_usage_delay ) { + std::string line; + size_t substrStart = 0; + size_t substrLen; + + // cpu stats + // user, nice, system, idle + // in that order + unsigned long long stats[4]; + + std::ifstream stat_file("/proc/stat"); + getline(stat_file, line); + stat_file.close(); + + // skip "cpu" + substrLen = line.find_first_of(" ", 3); + // parse cpu line + for(unsigned i=0; i < 4; i++) { + substrStart = line.find_first_not_of(" ", substrLen); + substrLen = line.find_first_of (" ", substrStart); + stats[i] = std::stoll( + line.substr(substrStart, substrLen)); + } + + usleep( cpu_usage_delay ); + + stat_file.open("/proc/stat"); + getline(stat_file, stat_line); + stat_file.close(); + + // skip "cpu" + substrLen = line.find_first_of(" ", 3); + // parse cpu line + for(unsigned i=0; i < 4; i++) { + substrStart = line.find_first_not_of(" ", substrLen); + substrLen = line.find_first_of (" ", substrStart); + stats[i] = std::stoll( + line.substr(substrStart, substrLen)) - stats[i]; + } + + return static_cast( stats[0] + stats[1] + stats[2]) / + static_cast( stats[0] + stats[1] + stats[2] + stats[3] ) * 100.0; +} + diff --git a/linux/cpu.h b/linux/cpu.h new file mode 100644 index 0000000..aa9e480 --- /dev/null +++ b/linux/cpu.h @@ -0,0 +1,6 @@ +#ifndef CPU_H_ +#define CPU_H_ + +float cpu_precentage(unsigned); + +#endif diff --git a/linux/load.cc b/linux/load.cc new file mode 100644 index 0000000..df4a54f --- /dev/null +++ b/linux/load.cc @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +#include "../luts.h" + +std::string load_string( bool use_colors = false ) { + std::ostringstream oss; + + std::ifstream loadavg_file( "/proc/loadavg" ); + std::string load_line; + std::getline( loadavg_file, load_line ); + loadavg_file.close(); + + if( use_colors ) { + // Likely does not work on BSD, but not tested + unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN ); + + float recent_load = stof(load_line.substr( 0, 4 )); + + // colors range from zero to twice the number of cpu's + // for the most recent load metric + unsigned load_percent = static_cast< unsigned int >( + recent_load / number_of_cpus * 0.5f * 100.0f ); + + if( load_percent > 100 ) + load_percent = 100; + + oss << load_lut[load_percent]; + } + + oss << load_line.substr( 0, 14 ); + if( use_colors ) + oss << "#[fg=default,bg=default]"; + + return oss.str(); +} diff --git a/linux/load.h b/linux/load.h new file mode 100644 index 0000000..3b8d814 --- /dev/null +++ b/linux/load.h @@ -0,0 +1,8 @@ +#ifndef LOAD_H_ +#define LOAD_H_ + +#include + +std::string load_string( bool ); + +#endif diff --git a/linux/memory.cc b/linux/memory.cc new file mode 100644 index 0000000..ce37474 --- /dev/null +++ b/linux/memory.cc @@ -0,0 +1,49 @@ +#include +#include + +#include "memory.h" + +std::string mem_string( bool use_colors = false ) { + std::ostringstream oss; + + unsigned int total_mem; + unsigned int used_mem; + unsigned int unused_mem; + + size_t substrStart; + size_t substrLen; + + std::ifstream meminfo_file( "/proc/meminfo" ); + + std::string mem_line; + + getline( meminfo_file, mem_line ); + substrStart = mem_line.find_first_of( ':' ) + 1; + substrLen = mem_line.find_first_of( 'k' ); + total_mem = stoi(mem_line.substr(substrStart, substrLen); + + used_mem = total_mem; + + for( unsigned int i = 0; i < 3; i++ ) { + getline( meminfo_file, mem_line ); + substrStart = mem_line.find_first_of( ':' ) + 1; + substrLen = mem_line.find_first_of( 'k' ); + unused_mem = stoi(mem_line.substr(substrStart, substrLen); + used_mem -= unused_mem; + } + + meminfo_file.close(); + + if( use_colors ) { + oss << mem_lut[(100 * used_mem) / total_mem]; + } + + oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; + + if( use_colors ) { + oss << "#[fg=default,bg=default]"; + } + + return oss.str(); +} + diff --git a/linux/memory.h b/linux/memory.h new file mode 100644 index 0000000..196dfd6 --- /dev/null +++ b/linux/memory.h @@ -0,0 +1,8 @@ +#ifndef MEMORY_H_ +#define MEMORY_H_ + +#include + +std::string mem_string( bool ); + +#endif diff --git a/osx/cpu.cc b/osx/cpu.cc new file mode 100644 index 0000000..c670793 --- /dev/null +++ b/osx/cpu.cc @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for sysctl +#include // for integer types + +// OSX or BSD based system, use BSD APIs instead +// See: http://www.opensource.apple.com/source/xnu/xnu-201/osfmk/mach/host_info.h +// and: http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/ +// +host_cpu_load_info_data_t _get_cpu_percentage() { + kern_return_t error; + mach_msg_type_number_t count; + host_cpu_load_info_data_t r_load; + mach_port_t mach_port; + + count = HOST_CPU_LOAD_INFO_COUNT; + mach_port = mach_host_self(); + error = host_statistics(mach_port, HOST_CPU_LOAD_INFO, ( + host_info_t)&r_load, &count); + + if (error != KERN_SUCCESS) + return host_cpu_load_info_data_t(); + + return r_load; +} + +float cpu_percentage( unsigned int cpu_usage_delay ) { + // Get the load times from the XNU kernel + host_cpu_load_info_data_t load1 = _get_cpu_percentage(); + usleep(cpu_usage_delay); + host_cpu_load_info_data_t load2 = _get_cpu_percentage(); + + // Current load times + unsigned long long current_user = load1.cpu_ticks[CPU_STATE_USER]; + unsigned long long current_system = load1.cpu_ticks[CPU_STATE_SYSTEM]; + unsigned long long current_nice = load1.cpu_ticks[CPU_STATE_NICE]; + unsigned long long current_idle = load1.cpu_ticks[CPU_STATE_IDLE]; + // Next load times + unsigned long long next_user = load2.cpu_ticks[CPU_STATE_USER]; + unsigned long long next_system = load2.cpu_ticks[CPU_STATE_SYSTEM]; + unsigned long long next_nice = load2.cpu_ticks[CPU_STATE_NICE]; + unsigned long long next_idle = load2.cpu_ticks[CPU_STATE_IDLE]; + // Difference between the two + unsigned long long diff_user = next_user - current_user; + unsigned long long diff_system = next_system - current_system; + unsigned long long diff_nice = next_nice - current_nice; + unsigned long long diff_idle = next_idle - current_idle; + + return static_cast(diff_user + diff_system + diff_nice) / + static_cast( + diff_user + diff_system + diff_nice + diff_idle) * 100.0; +} + diff --git a/osx/cpu.h b/osx/cpu.h new file mode 100644 index 0000000..2dc2b8f --- /dev/null +++ b/osx/cpu.h @@ -0,0 +1,6 @@ +#ifndef CPU_H_ +#define CPU_H_ + +float cpu_percentage ( unsigned ); + +#endif diff --git a/osx/load.cc b/osx/load.cc new file mode 100644 index 0000000..fd31d60 --- /dev/null +++ b/osx/load.cc @@ -0,0 +1,61 @@ +#include +#include +#include + +#include +#include // getloadavg() + +std::string load_string( bool use_colors = false ) { + std::ostringstream oss; + + // Both apple and BSD style systems have these api calls + // Only get 3 load averages + int nelem = 3; + double averages[3]; + // based on: + // http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c + if( getloadavg(averages, nelem) < 0 ) + oss << "0.00 0.00 0.00"; // couldn't get averages. + else + for(int i = 0; i < nelem; ++i) { + // Round to nearest, make sure this is + // only a 0.00 value not a 0.0000 + float avg = floorf( + static_cast(averages[i]) * 100 + 0.5) / 100; + oss << avg << " "; + } + + std::string load_line( oss.str() ); + oss.str( "" ); + + if( use_colors ) { + std::ifstream stat_file( "/proc/stat" ); + std::string stat_line; + std::getline( stat_file, stat_line ); + + // Likely does not work on BSD, but not tested + unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN ); + + std::istringstream iss( load_line.substr( 0, 4 ) ); + float recent_load; + iss >> recent_load; + // colors range from zero to twice the number of + // cpu's for the most recent load metric + + unsigned load_percent = static_cast< unsigned int >( + recent_load / number_of_cpus * 0.5f * 100.0f ); + + if( load_percent > 100 ) + load_percent = 100; + + oss << load_lut[load_percent]; + } + + oss << load_line.substr( 0, 14 ); + + if( use_colors ) + oss << "#[fg=default,bg=default]"; + + return oss.str(); +} + diff --git a/osx/load.h b/osx/load.h new file mode 100644 index 0000000..3b8d814 --- /dev/null +++ b/osx/load.h @@ -0,0 +1,8 @@ +#ifndef LOAD_H_ +#define LOAD_H_ + +#include + +std::string load_string( bool ); + +#endif diff --git a/osx/memory.cc b/osx/memory.cc new file mode 100644 index 0000000..59782a4 --- /dev/null +++ b/osx/memory.cc @@ -0,0 +1,64 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for sysctl +#include // for integer types + +std::string mem_string( bool use_colors ) { + std::ostringstream oss; + + // These values are in bytes + int64_t total_mem; + int64_t used_mem; + int64_t unused_mem; + + vm_size_t page_size; + mach_port_t mach_port; + mach_msg_type_number_t count; + vm_statistics_data_t vm_stats; + + // Get total physical memory + int mib[2]; + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + size_t length = sizeof(int64_t); + sysctl(mib, 2, &total_mem, &length, NULL, 0); + + mach_port = mach_host_self(); + count = sizeof(vm_stats) / sizeof(natural_t); + if (KERN_SUCCESS == host_page_size( mach_port, &page_size) && + KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, + (host_info_t)&vm_stats, &count)) { + unused_mem = (int64_t)vm_stats.free_count * (int64_t)page_size; + + used_mem = ( + (int64_t)vm_stats.active_count + + (int64_t)vm_stats.inactive_count + + (int64_t)vm_stats.wire_count) * + (int64_t)page_size; + } + + // To kilobytes + used_mem /= 1024; + total_mem /= 1024; + + if( use_colors ) + oss << mem_lut[(100 * used_mem) / total_mem]; + + oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; + + if( use_colors ) + oss << "#[fg=default,bg=default]"; + + return oss.str(); +} diff --git a/osx/memory.h b/osx/memory.h new file mode 100644 index 0000000..196dfd6 --- /dev/null +++ b/osx/memory.h @@ -0,0 +1,8 @@ +#ifndef MEMORY_H_ +#define MEMORY_H_ + +#include + +std::string mem_string( bool ); + +#endif diff --git a/version.h.in b/version.h.in new file mode 100644 index 0000000..23711c8 --- /dev/null +++ b/version.h.in @@ -0,0 +1,5 @@ +// the configured options and settings for sysstat +#define tmux-mem-cpu-load_VERSION_MAJOR @tmux-mem-cpu-load_VERSION_MAJOR@ +#define tmux-mem-cpu-load_VERSION_MINOR @tmux-mem-cpu-load_VERSION_MINOR@ +#define tmux-mem-cpu-load_VERSION_PATCH @tmux-mem-cpu-load_VERSION_PATCH@ + From 643fef3a7c1e0fc893e5d73afd13c8cba810ef0b Mon Sep 17 00:00:00 2001 From: l0ner Date: Mon, 14 Apr 2014 20:51:46 +0200 Subject: [PATCH 20/80] Corrections in CMakeLists.txt --- .gitignore | 3 + CMakeLists.txt | 50 ++++++- tmux-mem-cpu-load.cpp | 333 ++++-------------------------------------- 3 files changed, 77 insertions(+), 309 deletions(-) diff --git a/.gitignore b/.gitignore index 52d6332..d0ecef8 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,9 @@ cmake_install.cmake CMakeCache.txt install_manifest.txt version.h +CTestTestfile.cmake +tmux-mem-cpu-load +DartConfiguration.tcl # Packages # ############ diff --git a/CMakeLists.txt b/CMakeLists.txt index a9d2c3e..7e47058 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,15 @@ if(COMMAND cmake_policy) endif(COMMAND cmake_policy) project( tmux-mem-cpu-load ) +set(tmux-mem-cpu-load_VERSION_MAJOR 2) +set(tmux-mem-cpu-load_VERSION_MINOR 3) +set(tmux-mem-cpu-load_VERSION_PATCH 0) + +# generate header file to handle version +configure_file( + "${PROJECT_SOURCE_DIR}/version.h.in" + "${PROJECT_SOURCE_DIR}/version.h" + ) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING @@ -11,12 +20,43 @@ if(NOT CMAKE_BUILD_TYPE) FORCE) endif(NOT CMAKE_BUILD_TYPE) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +# detect system type +if(CMAKE_SYSTEM_NAME MATCHES "Linux") + message( "Linux detected") + SET( METER_SOURCES "linux/memory.cc" "linux/cpu.cc" "linux/load.cc" ) +ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin") + message( "Darwin detected") + SET( METER_SOURCES "osx/memory.cc" "osx/cpu.cc" "osx/load.cc" ) +# Mac OS X source setting will go here +ELSEIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + message( "FreeBSD detected") +# FreeBSD STUFF HERE +ELSEIF(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") + message( "OpenBSD detected") +# OpenBSD Stuff Here +ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux") + message( FATAL_ERROR "Cannot be compiled on this system" ) +endif() -add_executable(tmux-mem-cpu-load tmux-mem-cpu-load.cpp) -install(TARGETS tmux-mem-cpu-load - RUNTIME DESTINATION bin - ) +# Search for boost +# will be needed later +set(Boost_USE_STATIC_LIBS OFF) +set(Boost_USE_MULTITHREADED ON) +set(Boost_SUE_STATIC_RUTIME OFF) +find_package(Boost 1.52.0 REQUIRED COMPONENTS filesystem program_options system) + +# compiler flags +SET( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) +SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) + +# add binary tree so we find version.h +include_directories("${PROJECT_BINARY_DIR}" ${Boost_INCLUDE_DIRS}) + +add_executable(tmux-mem-cpu-load tmux-mem-cpu-load.cpp ${METER_SOURCES}) +target_link_libraries(tmux-mem-cpu-load ${Boost_LIBRARIES}) +install(TARGETS tmux-mem-cpu-load + RUNTIME DESTINATION bin +) include( CTest ) if( BUILD_TESTING ) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 8819c82..f4123fd 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -23,151 +23,37 @@ #include // for floorf #include // EXIT_SUCCESS -// Apple specific. -#if defined(__APPLE__) && defined(__MACH__) -// Mach kernel includes for getting memory and CPU statistics -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include // for sysctl -# include // for integer types -#endif - -// if we are on a BSD system -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) -// TODO: Includes and *BSD support -# define BSD_BASED 1 -#endif - // Tmux color lookup tables for the different metrics. #include "luts.h" +#if defined(__APPLE__) && defined(__MACH__) + // Apple osx system + #include "osx/cpu.h" + #include "osx/memory.h" + #include "osx/load.h" +#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) + // BSD system + // TODO: Includes and *BSD support + #define BSD_BASED 1 + // include _get_cpu_percentage (see osx/cpu.cc) + // include cpu_percentage (see osx/cpu.cc) +#else + // assume linux system + #include "linux/cpu.h" + #include "linux/memory.h" + #include "linux/load.h" +#endif + + // Function declarations. +// TODO: those should stay in separate headers +// LINUX: DONE/partial +// OSX: DONE/partial +// BSD: TODO float cpu_percentage( unsigned int cpu_usage_delay ); -std::string cpu_string( unsigned int cpu_usage_delay, - unsigned int graph_lines, - bool use_colors = false ); -std::string mem_string( bool use_colors = false ); -std::string load_string( bool use_colors = false ); - - -#if defined(BSD_BASED) || (defined(__APPLE__) && defined(__MACH__)) -// OSX or BSD based system, use BSD APIs instead - -// See: http://www.opensource.apple.com/source/xnu/xnu-201/osfmk/mach/host_info.h -// and: http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/ -host_cpu_load_info_data_t _get_cpu_percentage() -{ - kern_return_t error; - mach_msg_type_number_t count; - host_cpu_load_info_data_t r_load; - mach_port_t mach_port; - - count = HOST_CPU_LOAD_INFO_COUNT; - mach_port = mach_host_self(); - error = host_statistics(mach_port, HOST_CPU_LOAD_INFO, (host_info_t)&r_load, &count); - if (error != KERN_SUCCESS) - { - return host_cpu_load_info_data_t(); - } - - return r_load; -} - -float cpu_percentage( unsigned int cpu_usage_delay ) -{ - // Get the load times from the XNU kernel - host_cpu_load_info_data_t load1 = _get_cpu_percentage(); - usleep(cpu_usage_delay); - host_cpu_load_info_data_t load2 = _get_cpu_percentage(); - - // Current load times - unsigned long long current_user = load1.cpu_ticks[CPU_STATE_USER]; - unsigned long long current_system = load1.cpu_ticks[CPU_STATE_SYSTEM]; - unsigned long long current_nice = load1.cpu_ticks[CPU_STATE_NICE]; - unsigned long long current_idle = load1.cpu_ticks[CPU_STATE_IDLE]; - // Next load times - unsigned long long next_user = load2.cpu_ticks[CPU_STATE_USER]; - unsigned long long next_system = load2.cpu_ticks[CPU_STATE_SYSTEM]; - unsigned long long next_nice = load2.cpu_ticks[CPU_STATE_NICE]; - unsigned long long next_idle = load2.cpu_ticks[CPU_STATE_IDLE]; - // Difference between the two - unsigned long long diff_user = next_user - current_user; - unsigned long long diff_system = next_system - current_system; - unsigned long long diff_nice = next_nice - current_nice; - unsigned long long diff_idle = next_idle - current_idle; - -#else // Linux -float cpu_percentage( unsigned int cpu_usage_delay ) -{ - std::string stat_line; - size_t line_start_pos; - size_t line_end_pos; - unsigned long long current_user; - unsigned long long current_system; - unsigned long long current_nice; - unsigned long long current_idle; - unsigned long long next_user; - unsigned long long next_system; - unsigned long long next_nice; - unsigned long long next_idle; - unsigned long long diff_user; - unsigned long long diff_system; - unsigned long long diff_nice; - unsigned long long diff_idle; - std::istringstream iss; - - std::ifstream stat_file("/proc/stat"); - getline(stat_file, stat_line); - stat_file.close(); - - // skip "cpu" - line_start_pos = stat_line.find_first_not_of(" ", 3); - line_end_pos = stat_line.find_first_of(' ', line_start_pos); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - - iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); - iss >> current_user >> current_nice >> current_system >> current_idle; - iss.clear(); - - usleep( cpu_usage_delay ); - - stat_file.open("/proc/stat"); - getline(stat_file, stat_line); - stat_file.close(); - - // skip "cpu" - line_start_pos = stat_line.find_first_not_of(" ", 3); - line_end_pos = stat_line.find_first_of(' ', line_start_pos); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1); - - iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); - iss >> next_user >> next_nice >> next_system >> next_idle; - iss.clear(); - - diff_user = next_user - current_user; - diff_system = next_system - current_system; - diff_nice = next_nice - current_nice; - diff_idle = next_idle - current_idle; -#endif // platform - - return static_cast(diff_user + diff_system + diff_nice)/static_cast(diff_user + diff_system + diff_nice + diff_idle)*100.0; -} std::string cpu_string( unsigned int cpu_usage_delay, - unsigned int graph_lines, - bool use_colors ) -{ + unsigned int graph_lines, bool use_colors = false ) { std::string meter( graph_lines + 2, ' ' ); meter[0] = '['; meter[meter.length() - 1] = ']'; @@ -180,191 +66,30 @@ std::string cpu_string( unsigned int cpu_usage_delay, percentage = cpu_percentage( cpu_usage_delay ); float meter_step = 99.9 / graph_lines; meter_count = 1; - while(meter_count*meter_step < percentage) - { + + while(meter_count*meter_step < percentage) { meter[meter_count] = '|'; meter_count++; } if( use_colors ) - { oss << cpu_percentage_lut[static_cast( percentage )]; - } + oss << meter; oss.width( 5 ); oss << percentage; oss << "%"; if( use_colors ) - { oss << "#[fg=default,bg=default]"; - } return oss.str(); } - -std::string mem_string( bool use_colors ) -{ - std::ostringstream oss; -#if defined(BSD_BASED) || (defined(__APPLE__) && defined(__MACH__)) -// OSX or BSD based system, use BSD APIs instead - -#if defined(__APPLE__) && defined(__MACH__) - // These values are in bytes - int64_t total_mem; - int64_t used_mem; - int64_t unused_mem; - vm_size_t page_size; - mach_port_t mach_port; - mach_msg_type_number_t count; - vm_statistics_data_t vm_stats; - - // Get total physical memory - int mib[2]; - mib[0] = CTL_HW; - mib[1] = HW_MEMSIZE; - size_t length = sizeof(int64_t); - sysctl(mib, 2, &total_mem, &length, NULL, 0); - - mach_port = mach_host_self(); - count = sizeof(vm_stats) / sizeof(natural_t); - if (KERN_SUCCESS == host_page_size(mach_port, &page_size) && - KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count)) - { - unused_mem = (int64_t)vm_stats.free_count * (int64_t)page_size; - - used_mem = ((int64_t)vm_stats.active_count + - (int64_t)vm_stats.inactive_count + - (int64_t)vm_stats.wire_count) * (int64_t)page_size; - } - - // To kilobytes -#endif // Apple - // TODO BSD - - used_mem /= 1024; - total_mem /= 1024; - -#else // Linux - unsigned int total_mem; - unsigned int used_mem; - unsigned int unused_mem; - size_t line_start_pos; - size_t line_end_pos; - std::istringstream iss; - std::string mem_line; - - std::ifstream meminfo_file( "/proc/meminfo" ); - getline( meminfo_file, mem_line ); - line_start_pos = mem_line.find_first_of( ':' ); - line_start_pos++; - line_end_pos = mem_line.find_first_of( 'k' ); - iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); - iss >> total_mem; - - used_mem = total_mem; - - for( unsigned int i = 0; i < 3; i++ ) - { - getline( meminfo_file, mem_line ); - line_start_pos = mem_line.find_first_of( ':' ); - line_start_pos++; - line_end_pos = mem_line.find_first_of( 'k' ); - iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) ); - iss >> unused_mem; - used_mem -= unused_mem; - } - meminfo_file.close(); - -#endif // platform - - if( use_colors ) - { - oss << mem_lut[(100 * used_mem) / total_mem]; - } - oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; - if( use_colors ) - { - oss << "#[fg=default,bg=default]"; - } - - return oss.str(); -} - - -std::string load_string( bool use_colors ) -{ - std::ostringstream oss; - -#if defined(BSD_BASED) || (defined(__APPLE__) && defined(__MACH__)) - // Both apple and BSD style systems have these api calls - - // Only get 3 load averages - int nelem = 3; - double averages[3]; - // based on: http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c - if( getloadavg(averages, nelem) < 0 ) - { - oss << "0.00 0.00 0.00"; // couldn't get averages. - } - else - { - for(int i = 0; i < nelem; ++i) - { - // Round to nearest, make sure this is only a 0.00 value not a 0.0000 - float avg = floorf(static_cast(averages[i]) * 100 + 0.5) / 100; - oss << avg << " "; - } - } - std::string load_line( oss.str() ); - oss.str( "" ); - -#else // Linux - std::ifstream loadavg_file( "/proc/loadavg" ); - std::string load_line; - std::getline( loadavg_file, load_line ); - loadavg_file.close(); - -#endif // platform - - if( use_colors ) - { - std::ifstream stat_file( "/proc/stat" ); - std::string stat_line; - std::getline( stat_file, stat_line ); - // Likely does not work on BSD, but not tested - unsigned int number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN ); - - std::istringstream iss( load_line.substr( 0, 4 ) ); - float recent_load; - iss >> recent_load; - // colors range from zero to twice the number of cpu's for the most recent - // load metric - unsigned int load_percent = static_cast< unsigned int >( recent_load / number_of_cpus * 0.5f * 100.0f ); - if( load_percent > 100 ) - { - load_percent = 100; - } - oss << load_lut[load_percent]; - } - - oss << load_line.substr( 0, 14 ); - if( use_colors ) - { - oss << "#[fg=default,bg=default]"; - } - - return oss.str(); -} - - -int main(int argc, char** argv) -{ +int main(int argc, char** argv) { unsigned int cpu_usage_delay = 900000; int graph_lines = 10; bool use_colors = false; - try - { + try { std::istringstream iss; iss.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); std::string current_arg; From 5e354b92210f8a894ebfb208deff4b945c4290ea Mon Sep 17 00:00:00 2001 From: l0ner Date: Mon, 14 Apr 2014 20:55:00 +0200 Subject: [PATCH 21/80] memory.cc - fixed typos and missing headers --- linux/memory.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/linux/memory.cc b/linux/memory.cc index ce37474..6497ccb 100644 --- a/linux/memory.cc +++ b/linux/memory.cc @@ -1,7 +1,9 @@ #include -#include +#include +#include #include "memory.h" +#include "../luts.h" std::string mem_string( bool use_colors = false ) { std::ostringstream oss; @@ -20,7 +22,7 @@ std::string mem_string( bool use_colors = false ) { getline( meminfo_file, mem_line ); substrStart = mem_line.find_first_of( ':' ) + 1; substrLen = mem_line.find_first_of( 'k' ); - total_mem = stoi(mem_line.substr(substrStart, substrLen); + total_mem = stoi(mem_line.substr(substrStart, substrLen)); used_mem = total_mem; @@ -28,7 +30,7 @@ std::string mem_string( bool use_colors = false ) { getline( meminfo_file, mem_line ); substrStart = mem_line.find_first_of( ':' ) + 1; substrLen = mem_line.find_first_of( 'k' ); - unused_mem = stoi(mem_line.substr(substrStart, substrLen); + unused_mem = stoi(mem_line.substr(substrStart, substrLen)); used_mem -= unused_mem; } From b0ab6ea57a658e7bf6b051eb966376d612b8dfd8 Mon Sep 17 00:00:00 2001 From: l0ner Date: Mon, 14 Apr 2014 20:57:00 +0200 Subject: [PATCH 22/80] cpu.cc - fixed missing header and variable misname --- linux/cpu.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/cpu.cc b/linux/cpu.cc index a2b549d..d5bc804 100644 --- a/linux/cpu.cc +++ b/linux/cpu.cc @@ -3,6 +3,7 @@ #include // usleep #include "cpu.h" +#include "../luts.h" float cpu_percentage( unsigned cpu_usage_delay ) { std::string line; @@ -31,7 +32,7 @@ float cpu_percentage( unsigned cpu_usage_delay ) { usleep( cpu_usage_delay ); stat_file.open("/proc/stat"); - getline(stat_file, stat_line); + getline(stat_file, line); stat_file.close(); // skip "cpu" From ccf33e2a26368eceec30443c4ceb6420113ac384 Mon Sep 17 00:00:00 2001 From: l0ner Date: Mon, 14 Apr 2014 21:46:32 +0200 Subject: [PATCH 23/80] Functions for generating vertical graphs --- graph.cc | 36 ++++++++++++++++++++++++++++++++++++ graph.h | 7 +++++++ 2 files changed, 43 insertions(+) create mode 100644 graph.cc create mode 100644 graph.h diff --git a/graph.cc b/graph.cc new file mode 100644 index 0000000..1a9d2c9 --- /dev/null +++ b/graph.cc @@ -0,0 +1,36 @@ +#include +#include + +#include "graph.h" + +char * getGraphByPrecentage(unsigned value, unsigned len) { + unsigned step = 0; + char * bars = new char[len + 1]; + + unsigned barCount = (float(value) / 100 * len); + + for(step; step < barCount; step++) + bars[step] = '|'; + for(step; step < len; step++) + bars[step] = ' '; + bars[len]='\0'; + + return bars; +} + + +char * getGraphByValue(unsigned value, unsigned max, unsigned len) { + unsigned step = 0; + char * bars = new char[len + 1]; + + unsigned barCount = (float(value) / float(max) * len); + + for(step; step < barCount; step++) + bars[step] = '|'; + for(step; step < len; step++) + bars[step] = ' '; + bars[len]='\0'; + + return bars; +} + diff --git a/graph.h b/graph.h new file mode 100644 index 0000000..4cc550b --- /dev/null +++ b/graph.h @@ -0,0 +1,7 @@ +#ifndef GRAPH_H_ +#define GRAPH_H_ + +char * getGraphByPrecentage(unsigned, unsigned len = 10); +char * getGraphByValue(unsigned, unsigned, unsigned len = 10); + +#endif From 0857cdbfe4c49b41b69785a029fd88662fbc0475 Mon Sep 17 00:00:00 2001 From: l0ner Date: Mon, 14 Apr 2014 22:32:03 +0200 Subject: [PATCH 24/80] Spark graph functions --- spark.cc | 22 ++++++++++++++++++++++ spark.h | 7 +++++++ 2 files changed, 29 insertions(+) create mode 100644 spark.cc create mode 100644 spark.h diff --git a/spark.cc b/spark.cc new file mode 100644 index 0000000..7a7d774 --- /dev/null +++ b/spark.cc @@ -0,0 +1,22 @@ +#include +#include + +#include "spark.h" + +char getSparkByPrecentage(unsigned value) { + char ticks = " ▁▂▃▄▅▆▇█9"; + + unsigned tickVal = (float(value) / 10); + + return ticks[tickVal]; +} + + +char getSparkByValue(unsigned value, unsigned max) { + char ticks = " ▁▂▃▄▅▆▇█9"; + + unsigned tickVal = (float(value) / float(max) * 10); + + return ticks[tickVal]; +} + diff --git a/spark.h b/spark.h new file mode 100644 index 0000000..e400446 --- /dev/null +++ b/spark.h @@ -0,0 +1,7 @@ +#ifndef SPARK_H_ +#define SPARK_H_ + +char * getSparkByPrecentage(unsigned); +char * getSparkByValue(unsigned, unsigned); + +#endif From ea22ccd63fc0d681ef8e318098772eac28cff62e Mon Sep 17 00:00:00 2001 From: l0ner Date: Sat, 19 Apr 2014 20:29:59 +0200 Subject: [PATCH 25/80] spark.cc fixes --- spark.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spark.cc b/spark.cc index 7a7d774..b4ea332 100644 --- a/spark.cc +++ b/spark.cc @@ -4,18 +4,18 @@ #include "spark.h" char getSparkByPrecentage(unsigned value) { - char ticks = " ▁▂▃▄▅▆▇█9"; + char ticks = " ▁▂▃▄▅▆▇█"; - unsigned tickVal = (float(value) / 10); + unsigned tickVal = (float(value) / 9); return ticks[tickVal]; } char getSparkByValue(unsigned value, unsigned max) { - char ticks = " ▁▂▃▄▅▆▇█9"; + char ticks = " ▁▂▃▄▅▆▇█"; - unsigned tickVal = (float(value) / float(max) * 10); + unsigned tickVal = (float(value) / float(max) * 9); return ticks[tickVal]; } From af8c544653e87cfd96ae8f0d69da66ebff671fa2 Mon Sep 17 00:00:00 2001 From: l0ner Date: Sat, 19 Apr 2014 21:09:03 +0000 Subject: [PATCH 26/80] moved spark files to spark branch --- spark.cc | 22 ---------------------- spark.h | 7 ------- 2 files changed, 29 deletions(-) delete mode 100644 spark.cc delete mode 100644 spark.h diff --git a/spark.cc b/spark.cc deleted file mode 100644 index b4ea332..0000000 --- a/spark.cc +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include - -#include "spark.h" - -char getSparkByPrecentage(unsigned value) { - char ticks = " ▁▂▃▄▅▆▇█"; - - unsigned tickVal = (float(value) / 9); - - return ticks[tickVal]; -} - - -char getSparkByValue(unsigned value, unsigned max) { - char ticks = " ▁▂▃▄▅▆▇█"; - - unsigned tickVal = (float(value) / float(max) * 9); - - return ticks[tickVal]; -} - diff --git a/spark.h b/spark.h deleted file mode 100644 index e400446..0000000 --- a/spark.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef SPARK_H_ -#define SPARK_H_ - -char * getSparkByPrecentage(unsigned); -char * getSparkByValue(unsigned, unsigned); - -#endif From 03040e64f2b2c9c5c9bc6c35f2e402d20ad74c8a Mon Sep 17 00:00:00 2001 From: l0ner Date: Sat, 19 Apr 2014 21:13:36 +0000 Subject: [PATCH 27/80] rm cpu_percentage function proto from main source This is useless here, since this proto is provided by {linux,osx}/cpu.h --- tmux-mem-cpu-load.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index f4123fd..f618450 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -44,13 +44,11 @@ #include "linux/load.h" #endif - // Function declarations. // TODO: those should stay in separate headers // LINUX: DONE/partial // OSX: DONE/partial // BSD: TODO -float cpu_percentage( unsigned int cpu_usage_delay ); std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines, bool use_colors = false ) { From 634201aa2c77d61aa4685aca83bfb2611da76ffc Mon Sep 17 00:00:00 2001 From: l0ner Date: Sat, 19 Apr 2014 22:25:53 +0000 Subject: [PATCH 28/80] fixed typos in graph.{cc,h} and linux/cpu.h --- graph.cc | 6 +++--- graph.h | 2 +- linux/cpu.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/graph.cc b/graph.cc index 1a9d2c9..9e23264 100644 --- a/graph.cc +++ b/graph.cc @@ -3,11 +3,11 @@ #include "graph.h" -char * getGraphByPrecentage(unsigned value, unsigned len) { +char * getGraphByPercentage(unsigned value, unsigned len) { unsigned step = 0; char * bars = new char[len + 1]; - unsigned barCount = (float(value) / 100 * len); + unsigned barCount = (float(value) / 99.9 * len); for(step; step < barCount; step++) bars[step] = '|'; @@ -23,7 +23,7 @@ char * getGraphByValue(unsigned value, unsigned max, unsigned len) { unsigned step = 0; char * bars = new char[len + 1]; - unsigned barCount = (float(value) / float(max) * len); + unsigned barCount = (float(value) / (float(max) = 0.1) * len); for(step; step < barCount; step++) bars[step] = '|'; diff --git a/graph.h b/graph.h index 4cc550b..34f96e1 100644 --- a/graph.h +++ b/graph.h @@ -1,7 +1,7 @@ #ifndef GRAPH_H_ #define GRAPH_H_ -char * getGraphByPrecentage(unsigned, unsigned len = 10); +char * getGraphByPercentage(unsigned, unsigned len = 10); char * getGraphByValue(unsigned, unsigned, unsigned len = 10); #endif diff --git a/linux/cpu.h b/linux/cpu.h index aa9e480..beee11f 100644 --- a/linux/cpu.h +++ b/linux/cpu.h @@ -1,6 +1,6 @@ #ifndef CPU_H_ #define CPU_H_ -float cpu_precentage(unsigned); +float cpu_percentage(unsigned); #endif From 444bf2fa1cc83c1a2d0273914e98f92e4ad0bd8c Mon Sep 17 00:00:00 2001 From: l0ner Date: Sat, 19 Apr 2014 22:30:21 +0000 Subject: [PATCH 29/80] fixed typo in graph.cc --- graph.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graph.cc b/graph.cc index 9e23264..6080f8d 100644 --- a/graph.cc +++ b/graph.cc @@ -23,7 +23,7 @@ char * getGraphByValue(unsigned value, unsigned max, unsigned len) { unsigned step = 0; char * bars = new char[len + 1]; - unsigned barCount = (float(value) / (float(max) = 0.1) * len); + unsigned barCount = (float(value) / (float(max) - 0.1) * len); for(step; step < barCount; step++) bars[step] = '|'; From 2040736dd67496449b228d08c71b32f8f4e21951 Mon Sep 17 00:00:00 2001 From: l0ner Date: Sat, 19 Apr 2014 22:36:59 +0000 Subject: [PATCH 30/80] CPU usage graph generation by getGraphByPercentage function. --- CMakeLists.txt | 2 +- tmux-mem-cpu-load.cpp | 25 +++++++++++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e47058..645b162 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,7 @@ SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) # add binary tree so we find version.h include_directories("${PROJECT_BINARY_DIR}" ${Boost_INCLUDE_DIRS}) -add_executable(tmux-mem-cpu-load tmux-mem-cpu-load.cpp ${METER_SOURCES}) +add_executable(tmux-mem-cpu-load tmux-mem-cpu-load.cpp graph.cc ${METER_SOURCES}) target_link_libraries(tmux-mem-cpu-load ${Boost_LIBRARIES}) install(TARGETS tmux-mem-cpu-load RUNTIME DESTINATION bin diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index f618450..c0cea93 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -44,6 +44,8 @@ #include "linux/load.h" #endif +#include "graph.h" + // Function declarations. // TODO: those should stay in separate headers // LINUX: DONE/partial @@ -52,28 +54,23 @@ std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines, bool use_colors = false ) { - std::string meter( graph_lines + 2, ' ' ); - meter[0] = '['; - meter[meter.length() - 1] = ']'; - int meter_count = 0; - float percentage; + + float percentage; + + //output stuff std::ostringstream oss; oss.precision( 1 ); oss.setf( std::ios::fixed | std::ios::right ); + // get % percentage = cpu_percentage( cpu_usage_delay ); - float meter_step = 99.9 / graph_lines; - meter_count = 1; - - while(meter_count*meter_step < percentage) { - meter[meter_count] = '|'; - meter_count++; - } if( use_colors ) oss << cpu_percentage_lut[static_cast( percentage )]; - - oss << meter; + + oss << "["; + oss << getGraphByPercentage( unsigned(percentage), graph_lines ); + oss << "]"; oss.width( 5 ); oss << percentage; oss << "%"; From 47b9f62a1029fab851255b956025f72d2d2eb57e Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 4 Jan 2015 17:21:20 +0100 Subject: [PATCH 31/80] include fixes to make it compile on osx, added *~ files to gitignore --- .gitignore | 3 ++- osx/cpu.cc | 2 ++ osx/load.cc | 3 +++ osx/memory.cc | 5 +++-- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index d0ecef8..3f51360 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.o *.so sysstat +tmux-mem-cpu-load # CMake generated # ################### @@ -17,7 +18,6 @@ CMakeCache.txt install_manifest.txt version.h CTestTestfile.cmake -tmux-mem-cpu-load DartConfiguration.tcl # Packages # @@ -49,3 +49,4 @@ ehthumbs.db Thumbs.db *.swp *.swo +*~ diff --git a/osx/cpu.cc b/osx/cpu.cc index c670793..71aaa3a 100644 --- a/osx/cpu.cc +++ b/osx/cpu.cc @@ -10,6 +10,8 @@ #include // for sysctl #include // for integer types +#include // usleep() + // OSX or BSD based system, use BSD APIs instead // See: http://www.opensource.apple.com/source/xnu/xnu-201/osfmk/mach/host_info.h // and: http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/ diff --git a/osx/load.cc b/osx/load.cc index fd31d60..e6b5b96 100644 --- a/osx/load.cc +++ b/osx/load.cc @@ -1,10 +1,13 @@ #include #include #include +#include // floorf() #include #include // getloadavg() +#include "../luts.h" + std::string load_string( bool use_colors = false ) { std::ostringstream oss; diff --git a/osx/memory.cc b/osx/memory.cc index 59782a4..1bac364 100644 --- a/osx/memory.cc +++ b/osx/memory.cc @@ -1,6 +1,5 @@ #include -#include -#include +#include #include #include @@ -14,6 +13,8 @@ #include // for sysctl #include // for integer types +#include "../luts.h" + std::string mem_string( bool use_colors ) { std::ostringstream oss; From 080e1be24dd43144acea22aa44d2da807b4b0fca Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 4 Jan 2015 17:23:05 +0100 Subject: [PATCH 32/80] use static_cast<> instead of c-like cast --- graph.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graph.cc b/graph.cc index 6080f8d..97130f2 100644 --- a/graph.cc +++ b/graph.cc @@ -7,7 +7,7 @@ char * getGraphByPercentage(unsigned value, unsigned len) { unsigned step = 0; char * bars = new char[len + 1]; - unsigned barCount = (float(value) / 99.9 * len); + unsigned barCount = (static_cast(value) / 99.9 * len); for(step; step < barCount; step++) bars[step] = '|'; @@ -23,7 +23,7 @@ char * getGraphByValue(unsigned value, unsigned max, unsigned len) { unsigned step = 0; char * bars = new char[len + 1]; - unsigned barCount = (float(value) / (float(max) - 0.1) * len); + unsigned barCount = (static_cast(value / (max - 0.1)) * len); for(step; step < barCount; step++) bars[step] = '|'; From 223868f55430699ed484eabc0ee3744d44328494 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 4 Jan 2015 17:23:39 +0100 Subject: [PATCH 33/80] reindent one line --- tmux-mem-cpu-load.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index c0cea93..89e0ae4 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -55,7 +55,7 @@ std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines, bool use_colors = false ) { - float percentage; + float percentage; //output stuff std::ostringstream oss; From 26e89f95faaad15e1ccd450fcf10edb1e94c9056 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 4 Jan 2015 17:33:03 +0100 Subject: [PATCH 34/80] wrap lines that exceed 80 columns --- tmux-mem-cpu-load.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 89e0ae4..a6dd190 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -104,7 +104,8 @@ int main(int argc, char** argv) { iss >> status_interval; if( status_interval < 1 ) { - std::cerr << "Status interval argument must be one or greater." << std::endl; + std::cerr << "Status interval argument must be one or greater." + << std::endl; return EXIT_FAILURE; } cpu_usage_delay = status_interval * 1000000 - 100000; @@ -117,18 +118,23 @@ int main(int argc, char** argv) { iss >> graph_lines; if( graph_lines < 1 ) { - std::cerr << "Graph lines argument must be one or greater." << std::endl; + std::cerr << "Graph lines argument must be one or greater." + << std::endl; return EXIT_FAILURE; } } } catch(const std::exception &e) { - std::cerr << "Usage: " << argv[0] << " [--colors] [tmux_status-interval(seconds)] [graph lines]" << std::endl; + std::cerr << "Usage: " << argv[0] + << " [--colors] [tmux_status-interval(seconds)] [graph lines]" + << std::endl; return EXIT_FAILURE; } - std::cout << mem_string( use_colors ) << ' ' << cpu_string( cpu_usage_delay, graph_lines, use_colors ) << ' ' << load_string( use_colors ); + std::cout << mem_string( use_colors ) << ' ' + << cpu_string( cpu_usage_delay, graph_lines, use_colors ) << ' ' + << load_string( use_colors ); return EXIT_SUCCESS; } From 7a9209e243ce85ddcf249f6c6376602379eea832 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 4 Jan 2015 18:51:43 +0100 Subject: [PATCH 35/80] grime removal: useless includes and code --- osx/load.cc | 4 ---- tmux-mem-cpu-load.cpp | 5 +---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/osx/load.cc b/osx/load.cc index e6b5b96..cea49cc 100644 --- a/osx/load.cc +++ b/osx/load.cc @@ -32,10 +32,6 @@ std::string load_string( bool use_colors = false ) { oss.str( "" ); if( use_colors ) { - std::ifstream stat_file( "/proc/stat" ); - std::string stat_line; - std::getline( stat_file, stat_line ); - // Likely does not work on BSD, but not tested unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN ); diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index a6dd190..41956ec 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -15,12 +15,9 @@ * */ #include -#include -#include +#include #include #include -#include // sleep -#include // for floorf #include // EXIT_SUCCESS // Tmux color lookup tables for the different metrics. From 8e9033ee1eee62b7d73ecffa3e8928372f93a5b9 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Wed, 7 Jan 2015 14:15:08 +0100 Subject: [PATCH 36/80] restore headers --- tmux-mem-cpu-load.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 41956ec..f525014 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -15,7 +15,8 @@ * */ #include -#include +#include +#include #include #include #include // EXIT_SUCCESS From 42c93ac397d495b51a0e401e33415760c60296b7 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Wed, 7 Jan 2015 14:15:28 +0100 Subject: [PATCH 37/80] prune BOOST detection, minor tweaks For not Boost is not needed, uncomment relative lines when it will be. --- CMakeLists.txt | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 645b162..d877628 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,35 +25,38 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") message( "Linux detected") SET( METER_SOURCES "linux/memory.cc" "linux/cpu.cc" "linux/load.cc" ) ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin") + # Mac OS X source setting will go here message( "Darwin detected") SET( METER_SOURCES "osx/memory.cc" "osx/cpu.cc" "osx/load.cc" ) -# Mac OS X source setting will go here ELSEIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + # FreeBSD STUFF HERE message( "FreeBSD detected") -# FreeBSD STUFF HERE + message( FATAL_ERROR "Free BSD is not supported yet" ) ELSEIF(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") + # OpenBSD Stuff Here message( "OpenBSD detected") -# OpenBSD Stuff Here -ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux") + message( FATAL_ERROR "OpenBSD is not supported yet" ) +ELSE() message( FATAL_ERROR "Cannot be compiled on this system" ) endif() # Search for boost # will be needed later -set(Boost_USE_STATIC_LIBS OFF) -set(Boost_USE_MULTITHREADED ON) -set(Boost_SUE_STATIC_RUTIME OFF) -find_package(Boost 1.52.0 REQUIRED COMPONENTS filesystem program_options system) +#set(Boost_USE_STATIC_LIBS OFF) +#set(Boost_USE_MULTITHREADED ON) +#set(Boost_SUE_STATIC_RUTIME OFF) +#find_package(Boost 1.52.0 REQUIRED COMPONENTS filesystem program_options system) # compiler flags SET( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) # add binary tree so we find version.h +#include_directories("${PROJECT_BINARY_DIR}" ${Boost_INCLUDE_DIRS}) include_directories("${PROJECT_BINARY_DIR}" ${Boost_INCLUDE_DIRS}) add_executable(tmux-mem-cpu-load tmux-mem-cpu-load.cpp graph.cc ${METER_SOURCES}) -target_link_libraries(tmux-mem-cpu-load ${Boost_LIBRARIES}) +#target_link_libraries(tmux-mem-cpu-load ${Boost_LIBRARIES}) install(TARGETS tmux-mem-cpu-load RUNTIME DESTINATION bin ) From 72f1b03078373912fc1707f4d17bfc1e526e30e8 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Wed, 7 Jan 2015 14:31:49 +0100 Subject: [PATCH 38/80] shorter DEFINES for versioning --- CMakeLists.txt | 10 +++++++--- tmux-mem-cpu-load.cpp | 2 ++ version.h.in | 6 +++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d877628..476ff9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,10 +3,12 @@ if(COMMAND cmake_policy) cmake_policy(VERSION 2.6) endif(COMMAND cmake_policy) +### General Package stuff + project( tmux-mem-cpu-load ) -set(tmux-mem-cpu-load_VERSION_MAJOR 2) -set(tmux-mem-cpu-load_VERSION_MINOR 3) -set(tmux-mem-cpu-load_VERSION_PATCH 0) +set(VERSION_MAJOR 2) +set(VERSION_MINOR 3) +set(VERSION_PATCH 0) # generate header file to handle version configure_file( @@ -14,6 +16,8 @@ configure_file( "${PROJECT_SOURCE_DIR}/version.h" ) + + if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index f525014..77a9d2f 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -24,6 +24,8 @@ // Tmux color lookup tables for the different metrics. #include "luts.h" +#include "version.h" + #if defined(__APPLE__) && defined(__MACH__) // Apple osx system #include "osx/cpu.h" diff --git a/version.h.in b/version.h.in index 23711c8..8bbfddb 100644 --- a/version.h.in +++ b/version.h.in @@ -1,5 +1,5 @@ // the configured options and settings for sysstat -#define tmux-mem-cpu-load_VERSION_MAJOR @tmux-mem-cpu-load_VERSION_MAJOR@ -#define tmux-mem-cpu-load_VERSION_MINOR @tmux-mem-cpu-load_VERSION_MINOR@ -#define tmux-mem-cpu-load_VERSION_PATCH @tmux-mem-cpu-load_VERSION_PATCH@ +#define VERSION_MAJOR @VERSION_MAJOR@ +#define VERSION_MINOR @VERSION_MINOR@ +#define VERSION_PATCH @VERSION_PATCH@ From e7ee4279f6d4e361f48fb5f4bb489886b799532f Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Wed, 7 Jan 2015 14:58:47 +0100 Subject: [PATCH 39/80] increase sleep time to full sec instead of 1-0.1s --- tmux-mem-cpu-load.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 77a9d2f..fb2a816 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -52,8 +52,8 @@ // OSX: DONE/partial // BSD: TODO -std::string cpu_string( unsigned int cpu_usage_delay, - unsigned int graph_lines, bool use_colors = false ) { +std::string cpu_string(unsigned int cpu_usage_delay, unsigned int graph_lines, + bool use_colors = false) { float percentage; @@ -81,7 +81,7 @@ std::string cpu_string( unsigned int cpu_usage_delay, } int main(int argc, char** argv) { - unsigned int cpu_usage_delay = 900000; + unsigned int cpu_usage_delay = 1000000; int graph_lines = 10; bool use_colors = false; try { @@ -108,7 +108,7 @@ int main(int argc, char** argv) { << std::endl; return EXIT_FAILURE; } - cpu_usage_delay = status_interval * 1000000 - 100000; + cpu_usage_delay = status_interval * 1000000; ++arg_index; } if( argc > arg_index ) From 28040b61dad99cb9cb4cfc604a5d38123b4ac66e Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Wed, 7 Jan 2015 20:57:25 +0100 Subject: [PATCH 40/80] easier to read argv parse using command line argument parser by Michael Hanke --- CMakeLists.txt | 10 +- argParse/argParse.cc | 817 ++++++++++++++++++++++++++++++++++++++++++ argParse/argParse.h | 337 +++++++++++++++++ tmux-mem-cpu-load.cpp | 123 ++++--- 4 files changed, 1225 insertions(+), 62 deletions(-) create mode 100644 argParse/argParse.cc create mode 100644 argParse/argParse.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 476ff9b..8fe9178 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,7 @@ configure_file( "${PROJECT_SOURCE_DIR}/version.h" ) - - +# set buold type if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." @@ -44,6 +43,9 @@ ELSE() message( FATAL_ERROR "Cannot be compiled on this system" ) endif() +# set common source files +SET( COMMON_SOURCES "tmux-mem-cpu-load.cpp" "graph.cc" "argParse/argParse.cc" ) + # Search for boost # will be needed later #set(Boost_USE_STATIC_LIBS OFF) @@ -57,9 +59,9 @@ SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) # add binary tree so we find version.h #include_directories("${PROJECT_BINARY_DIR}" ${Boost_INCLUDE_DIRS}) -include_directories("${PROJECT_BINARY_DIR}" ${Boost_INCLUDE_DIRS}) +include_directories("${PROJECT_BINARY_DIR}" ) -add_executable(tmux-mem-cpu-load tmux-mem-cpu-load.cpp graph.cc ${METER_SOURCES}) +add_executable(tmux-mem-cpu-load ${COMMON_SOURCES} ${METER_SOURCES}) #target_link_libraries(tmux-mem-cpu-load ${Boost_LIBRARIES}) install(TARGETS tmux-mem-cpu-load RUNTIME DESTINATION bin diff --git a/argParse/argParse.cc b/argParse/argParse.cc new file mode 100644 index 0000000..7dbece6 --- /dev/null +++ b/argParse/argParse.cc @@ -0,0 +1,817 @@ +/* + * C++ command line argument parser + * + * Copyright (C) 2005 by + * Michael Hanke michael.hanke@gmail.com + * + * Minor adjustements: 2015 Pawel 'l0ner' Soltys + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include "argParse.h" + +using namespace std; +using namespace ArgvParse; + +ArgvParser::ArgvParser() + : max_key(1), + help_option(0) // must be smaller than max_key initially + +{ + // nothing +} + +ArgvParser::~ArgvParser() +{ + // nothing +} + +void ArgvParser::reset() +{ + max_key = 1; + option2key.clear(); + option2attribute.clear(); + option2descr.clear(); + option2value.clear(); + errorcode2descr.clear(); + argument_container.clear(); + intro_description.clear(); + error_option.clear(); + help_option = 0; +} + +int ArgvParser::optionKey( const string& _name ) const +{ + String2KeyMap::const_iterator it = option2key.find(_name); + + // if not found + if (it == option2key.end()) + return(-1); + + return(it->second); +} + +bool ArgvParser::isDefinedOption( const string& _name ) const +{ + return(option2key.find(_name) != option2key.end()); +} + +bool ArgvParser::foundOption( const string & _name ) const +{ + int key = optionKey(_name); + + // not defined -> cannot by found + if (key == -1) + return(false); + + // return whether the key of the given option name is in the hash of the + // parsed options. + return(option2value.find(key) != option2value.end()); +} + +string ArgvParser::optionValue(const string& _option) const +{ + int key = optionKey(_option); + + // not defined -> cannot by found + if (key == -1) + { + cerr << "ArgvParser::optionValue(): Requested value of an option the" + "parser did not find or does not know." << endl; + return(""); + } + + return(option2value.find(key)->second); +} + +ArgvParser::ParserResults +ArgvParser::parse(int _argc, char ** _argv) +{ + bool finished_options = false; // flag whether an argument was found + // (options are passed) + + // loop over all command line arguments + int i = 1; // argument counter + while( i< _argc ) + { + string argument = _argv[i]; + unsigned int key = 0; + string option; // option name + string value; // option value + + // if argument is an option + if (!isValidOptionString(argument)) + { + // string is a real argument since values are processed elsewhere + finished_options=true; + argument_container.push_back(argument); + } + else // can be a long or multiple short options at this point + { + // check whether we already found an argument + if (finished_options) + { + error_option = argument; + return(OptionAfterArgument); // return error code + } + // check for long options + if (isValidLongOptionString(argument)) + { + // handle long options + + // remove trailing '--' + argument = argument.substr(2); + // check for option value assignment 'option=value' + splitOptionAndValue(argument, option, value); + + if (!isDefinedOption(option)) // is this a known option + { + error_option = option; // store the option that caused the error + return(UnknownOption); // return error code if not + } + + // get the key of this option - now that we know that it is defined + key = option2key.find(option)->second; + if (key == help_option) // if help is requested return error code + return(HelpRequested); + + // do we need to extract a value + // AND a value is not already assigned from the previous step + if ((option2attribute.find(key)->second & RequiresValue) && value.empty()) + { + if (i+1 >= _argc) // are there arguments left? + { + error_option = option; // store the option that caused the error + return(MissingValue); // the was no argument left although we need a value + } + + string temp = _argv[i+1]; // get the next element + ++i; // increase counter now that we moved forward + + if (isValidOptionString(temp)) + { + error_option = option; // store the option that caused the error + return(MissingValue); // missing option value + } + value = temp; // assign value + } + // add option-value map entry + option2value[key] = value; + } + else // handle short options + { + argument = argument.substr(1); // remove trailing '-' + + // check for option value assignment 'option=value' + if (splitOptionAndValue(argument, option, value)) + { + // there was an option <- value assignment + if (option.length() > 1) + { + error_option = option; // store the option that caused the error + return(MalformedMultipleShortOption); // return error code if option has more than one character + } + + if (!isDefinedOption(option)) // is this a known option + { + error_option = option; // store the option that caused the error + return(UnknownOption); // return error code if not + } + key = option2key.find(option)->second; // get the key for the extracted option name + + if (key == help_option) // if help is requested return error code + return(HelpRequested); + + // if value is still empty for some reason: we have an error + if ((option2attribute.find(key)->second & RequiresValue) && value.empty()) + { + error_option = option; // store the option that caused the error + return(MissingValue); // missing option value + } + else + // add option-value map entry + option2value[key] = value; + } + else // no '=' assignment: can be either multiple short options or + // something like '-s 4' + { + // handle short options with value like '-s 4' + option.clear(); + value.clear(); + + if (argument.length() == 1) // if a single short option + { + if (!isDefinedOption(argument)) // is this a known option + { + error_option = argument; // store the option that caused the error + return(UnknownOption); // return error code if not + } + key = option2key.find(argument)->second; // get the key for the extracted option name + + if (key == help_option) // if help is requested return error code + return(HelpRequested); + + // check if option needs a value and next arg is not an option + if ((option2attribute.find(key)->second & RequiresValue)) + { + if (i+1 >= _argc) // are there arguments left? + { + error_option = argument; // store the option that caused the error + return(MissingValue); // the was no argument left although we need a value + } + string temp = _argv[i+1]; // get the next element + ++i; // increase counter now that we moved forward + + if (isValidOptionString(temp)) + { + error_option = argument; // store the option that caused the error + return(MissingValue); // missing option value + } + // add option-value map entry + option2value[key] = temp; + + } + else // no value needed + { + option2value[key] = ""; // assign value + } + } + else // handle multiple short option like '-svxgh' + { + unsigned int short_option_counter = 0; // position in the multiple short option string + while( short_option_counter < argument.length() ) // parse the whole string + { + option = argument[short_option_counter]; // get the option character + + if (!isDefinedOption(option)) // is this a known option + { + error_option = option; // store the option that caused the error + return(UnknownOption); // return error code if not + } + key = option2key.find(option)->second; // get the key for the extracted option name + + if (key == help_option) // if help is requested return error code + return(HelpRequested); + + option2value[key] = value; + + ++short_option_counter; // advance one character forward + } + } + } + } + } + ++i; + } + + map::iterator it; + for( it = option2attribute.begin(); it != option2attribute.end(); it++ ) + { + // if the current option is required look if we got it + if (it->second & Required) + { + // is the object missing + if (option2value.find(it->first) == option2value.end()) + { + // get the list of alternative names for this option + list alternatives = getAllOptionAlternatives(it->first); + + unsigned int count = 0; + for( list::const_iterator alt = alternatives.begin(); + alt != alternatives.end(); + ++alt ) + { + ++count; + // additional '-' for long options + if (alt->length() > 1) + error_option += "-"; + + error_option += "-" + *alt; + + // alternatives to come? + if (count < alternatives.size()) + error_option += ", "; // add separator + } + return(RequiredOptionMissing); + } + } + } + + return(Success); // everthing went fine -> sucess +} + +unsigned int ArgvParser::arguments() const +{ + return(argument_container.size()); +} + +string ArgvParser::argument(unsigned int _id) const +{ + if (_id >= arguments()) + { + cerr << "ArgvParser::argument(): Request for non-existing argument.\n"; + return (""); + } + else + return(argument_container[_id]); +} + +const vector& ArgvParser::allArguments() const +{ + return(argument_container); +} + +string ArgvParser::usageDescription(unsigned int _width) const +{ + string usage; // the usage description text + + if (intro_description.length()) + usage += formatString(intro_description, _width) + "\n\n"; + + if (max_key>1) // if we have some options + usage += formatString("Available options:",_width) + "\n"; + + // loop over all option attribute entries (which equals looping over all + // different options (not option names) + for (Key2AttributeMap::const_iterator it = option2attribute.begin(); + it != option2attribute.end(); + ++it) + { + string os; // temp string for the option + + // get the list of alternative names for this option + list alternatives = getAllOptionAlternatives(it->first); + + unsigned int count = 0; + for( list::const_iterator alt = alternatives.begin(); + alt != alternatives.end(); + ++alt ) + { + ++count; + // additional '-' for long options + if (alt->length() > 1) + os += "-"; + + os += "-" + *alt; + + // note if the option requires a value + if (option2attribute.find(it->first)->second & RequiresValue) + os += " "; + + // alternatives to come? + if (count < alternatives.size()) + os += ", "; // add separator + } + + // note if the option is required + if (option2attribute.find(it->first)->second & Required) + os += " [required]"; + + usage += formatString(os, _width) + "\n"; + + if (option2descr.find(it->first) != option2descr.end()) + usage += formatString(option2descr.find(it->first)->second, _width, 4); + else + usage += formatString("(no description)", _width, 4); + + // finally a little gap + usage += "\n"; + } + usage += "\n"; + + if (!errorcode2descr.size()) // if have no errorcodes + return(usage); + + usage += formatString("Return codes", _width) + "\n"; + + // map::const_iterator eit; + for( std::map::const_iterator alt = errorcode2descr.begin(); + alt != errorcode2descr.end(); + ++alt ) + { + ostringstream code; + code << alt->first; + string label = formatString(code.str(), _width, 4); + string descr = formatString(alt->second, _width, 10); + usage += label + descr.substr(label.length()) + "\n"; + } + + return(usage); +} + +const string& ArgvParser::errorOption( ) const +{ + return(error_option); +} + +std::string ArgvParser::parseErrorDescription( ParserResults _error_code ) const +{ + string descr; + + switch (_error_code) + { + case ArgvParser::Success: + // no error -> nothing to do + break; + case ArgvParser::UnknownOption: + descr = "Unknown option: '" + errorOption() + "'\n"; + break; + case ArgvParser::MissingValue: + descr = "Missing required value for option: '" + errorOption()+ "'\n"; + break; + case ArgvParser::OptionAfterArgument: + descr = "Misplaced option '" + errorOption() + + "' detected. All option have to be BEFORE the first argument\n"; + break; + case ArgvParser::MalformedMultipleShortOption: + descr = "Malformed short-options: '" + errorOption() + "'\n"; + break; + case ArgvParser::ArgvParser::RequiredOptionMissing: + descr = "Required option missing: '" + errorOption() + "'\n"; + break; + case ArgvParser::HelpRequested: // help + descr = usageDescription(); + break; + default: + cerr << "ArgvParser::documentParserErrors(): Unknown error code\n"; + } + + return(descr); +} + +bool ArgvParser::defineOption( const string & _name, + const string& _descr, + OptionAttributes _attrs) +{ + // do nothing if there already is an option of this name + if (isDefinedOption(_name)) + { + cerr << "ArgvParser::defineOption(): The option label equals an already defined option." << endl; + return(false); + } + + // no digits as short options allowed + if (_name.length() == 1 && isDigit(_name[0])) + { + cerr << "ArgvParser::defineOption(): Digits as short option labels are not allowd." << endl; + return(false); + } + + option2key[_name] = max_key; // give the option a unique key + + // store the option attributes + option2attribute[max_key] = _attrs; + + // store the option description if there is one + if (_descr.length()) + option2descr[max_key] = _descr; + + // inc the key counter + ++max_key; + + return(true); +} + +bool ArgvParser::defineOptionAlternative( const string & _original, + const string & _alternative ) +{ + // do nothing if there already is no option of this name + if (!isDefinedOption(_original)) + { + cerr << "ArgvParser::defineOptionAlternative(): Original option label is not a defined option." << endl; + return(false); + } + + // AND no digits as short options allowed + if (_alternative.length() == 1 && isDigit(_alternative[0])) + { + cerr << "ArgvParser::defineOptionAlternative(): Digits as short option labels are not allowd." << endl; + return(false); + } + + // AND do nothing if there already is an option with the alternativ name + if (isDefinedOption(_alternative)) + { + cerr << "ArgvParser::defineOptionAlternative(): The alternative option label equals an already defined option." << endl; + return(false); + } + + option2key[_alternative] = optionKey(_original); + + return(true); +} + +bool ArgvParser::defineOption( const string & _shortname, + const string & _name, + const string& _descr, + OptionAttributes _attrs) +{ + + defineOption( _name, _descr, _attrs); + defineOptionAlternative( _name, _shortname ); + + return(true); + +} + + +bool ArgvParser::setHelpOption(const string& _shortname, + const string& _longname, + const string& _descr) +{ + // do nothing if any name is already in use + if (isDefinedOption(_shortname) || isDefinedOption(_longname)) + { + cerr << "ArgvParser::setHelpOption(): Short or long help option label equals an already defined option." << endl; + return(false); + } + + // define the help option's short name and the alternative + // longname + defineOption(_shortname, _descr, NoAttribute); + defineOptionAlternative(_shortname, _longname); + + help_option = max_key-1; // store the key in a special member + + return(true); +} + +void ArgvParser::addErrorCode(int _code, const string& _descr) +{ + errorcode2descr[_code] = _descr; +} + +void ArgvParser::setIntroduction(const string& _descr) +{ + intro_description = _descr; +} + +list ArgvParser::getAllOptionAlternatives( unsigned int _key ) const +{ + // keys go here + list keys; + // for all container elements + for( map::const_iterator it = option2key.begin(); + it != option2key.end(); + ++it ) + { + if (it->second == _key) + keys.push_back(it->first); + } + return(keys); +} + +bool ArgvParse::isDigit(const char& _char) +{ + if (_char == '0' || _char == '1' || _char == '2' || _char == '3' + || _char == '4' || _char == '5' || _char == '6' || _char == '7' + || _char == '8' || _char == '9') + return(true); + else + return(false); +} + +bool ArgvParse::isValidOptionString(const string& _string) +{ + // minimal short option length is 2 + if (_string.length() < 2) + return(false); + + // is it an option (check for '-' as first character) + if (_string.compare(0, 1, "-")) + return(false); + + // not an option if just '--' + if (_string.length() == 2 && _string == "--") + return(false); + + // it might still be a negative number + // (but not if there is no digit afterwards) + if (isDigit(_string[1])) + return(false); + + // let's consider this an option + return(true); +} + +bool ArgvParse::isValidLongOptionString(const string& _string) +{ + if (_string.length() < 4) // must be at least '--??' + return(false); + + // is it an option (check for '--') + if (_string.compare(0, 2, "--")) + return(false); + else + return(true); +} + +bool ArgvParse::splitOptionAndValue(const string& _string, + string& _option, string& _value) +{ + // string token container + std::vector tokens; + + // split string by '=' delimiter + splitString(tokens, _string, "="); + + // check for option value assignment 'option=value' + if (tokens.size() < 2) + { + _option = _string; // the option is the whole string + return(false); + } + + // separate option and value + _option = tokens[0]; + + // concat all remaining tokens to the value string + for (unsigned int i=1; i & _expanded ) +{ + list tokens; + // split string by delimiter + splitString(tokens, _string, ","); + + // loop over all entries + for(list::const_iterator it = tokens.begin(); it != tokens.end(); it++) + { + const string& entry = *it; // convenience reference + +#ifdef ARGVPARSER_DEBUG + + cout << "TOKEN: " << entry << endl; +#endif + + // if range was given + if (entry.find("-") != string::npos) + { + // split into upper and lower border + list range_borders; + splitString(range_borders, entry, "-"); + + // fail if insane range spec + if (range_borders.size() != 2) + return(false); + + int first = atoi(range_borders.begin()->c_str()); + int second = atoi((++range_borders.begin())->c_str()); + + // write id in increasing order + if (first <= second) + + { + for (int j=first; j<=second; ++j) + { + _expanded.push_back(j); + } + } + else // write id in decreasing order + { + for (int k=first; k>=second; k--) + { + _expanded.push_back(k); + } + } + } + else // single number was given + _expanded.push_back(atoi(entry.c_str())); // store id + } + + return(true); +} + +std::string ArgvParse::formatString(const std::string& _string, + unsigned int _width, + unsigned int _indent) +{ + // if insane parameters do nothing + if (_indent >= _width) + return(_string); + + // list of lines of the formated string + list lines; + + // current position in the string + unsigned int pos = 0; + + // till the end of the string + while (pos < _string.length()) + { + // get the next line of the string + string line = _string.substr(pos, _width - _indent ); + +#ifdef ARGVPARSER_DEBUG + + cout << "EXTRACT: '" << line << "'" << endl; +#endif + + // check for newlines in the line and break line at first occurence (if any) + string::size_type first_newline = line.find_first_of("\n"); + if (first_newline != string::npos) + { + line = line.substr(0, first_newline); + } + + // we need to check for possible breaks within words only if the extracted + // line spans the whole allowed width + bool check_truncation = true; + if (line.length() < _width - _indent) + check_truncation = false; + + // remove unecessary whitespace at front and back + line = trimmedString(line); + +#ifdef ARGVPARSER_DEBUG + + cout << "TRIMMED: '" << line << "'" << endl; +#endif + + // only perform truncation if there was enough data for a full line + if (!check_truncation) + pos += line.length() + 1; + else + { + // look for the last whitespace character + string::size_type last_white_space = line.find_last_of(" \a\b\f\n\r\t\v"); + + if (last_white_space != string::npos) // whitespace found! + { + // truncated the line at the last whitespace + line = string(line, 0, last_white_space); + pos += last_white_space + 1; + } + else // no whitespace found + // rude break! we can leave the line in its current state + pos += _width - _indent; + } + + if (!line.empty()) + { +#ifdef ARGVPARSER_DEBUG + cout << "UNINDEN: '" << line << "'" << endl; +#endif + + if (_indent) + line.insert(0, _indent, ' '); + +#ifdef ARGVPARSER_DEBUG + + cout << "INDENT: '" << line << "'" << endl; +#endif + + lines.push_back(line); + } + } + + // concat the formated string + string formated; + bool first = true; + // for all lines + for (list::iterator it = lines.begin(); it != lines.end(); ++it) + { + // prefix with newline if not first + if (!first) + formated += "\n"; + else + first = false; + + formated += *it; + } + return(formated); +} + diff --git a/argParse/argParse.h b/argParse/argParse.h new file mode 100644 index 0000000..6b8ae27 --- /dev/null +++ b/argParse/argParse.h @@ -0,0 +1,337 @@ +/* + * C++ command line argument parser + * + * Copyright (C) 2005 by + * Michael Hanke michael.hanke@gmail.com + * + * Minor adjustements: 2015 Pawel 'l0ner' Soltys + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __ARGVPARSER_H +#define __ARGVPARSER_H + +#include +#include +#include +#include + +namespace ArgvParse +{ + +/** Provides parsing and storage of POSIX-like command line arguments (argc, argv). +* To use this class for CLI-option parsing, first define a set of valid options using +* the defineOption() method. An option can have several attributes: it can be required +* itself (its missing is considered as an error) and/or it can require a value. +* Options with optional values can be realized by defining the option to not need a +* value and use the syntax '--option=value' or '-o=value' on the command line. +* Every option can have different alternative labels; see defineOptionAlternative(). +* A usage description (see usageDescription()) can be generated from the set of defined options (also see the +* addErrorCode(), setIntroductoryDescription() and setHelpOption() methods). +* \note The implemented parsing algorithm requires that all options have to be given at +* the beginning of the command line. Everything on the commandline after the first +* non-option (or option value) is considered as an argument. +* \attention Short option labels (single letter options) must not be digits +* (the option string itself not a possible value). +* Valid syntaxes are: +* \li program --long-option value -sdfgh -u=5 -i 7 --last=val arg1 arg2 arg3 +* Here is a small code example: +* \code +* #include +* ArgvParser cmd; // the command line parser +* +* // init +* cmd.setIntroductoryDescription("This is foo written by bar."); +* +* //define error codes +* cmd.addErrorCode(0, "Success"); +* cmd.addErrorCode(1, "Error"); +* +* cmd.setHelpOption("h", "help", "Print this help"); +* +* cmd.defineOption("version", ArgvParser::NoOptionAttribute, "Be verbose"); +* cmd.defineOptionAlternative("verbose","v"); +* +* cmd.defineOption("foo", ArgvParser::OptionRequiresValue, "Fooishness. Default value: 0"); +* +* // finally parse and handle return codes (display help etc...) +* int result = cmd.parse(argc, argv); +* +* if (result != ArgvParser::NoParserError) +* cout << cmd.parseErrorDescription(results); +* exit(1); +* \endcode +* +* \author Michael Hanke +*/ +class ArgvParser +{ +public: + typedef int OptionAttributes; + typedef int ParserResults; + typedef std::map String2KeyMap; + typedef std::map Key2AttributeMap; + typedef std::map Key2StringMap; + typedef std::vector ArgumentContainer; + + ArgvParser(); + ~ArgvParser(); + + /** Attributes for options. */ + enum + { + NoAttribute = 0x00, + RequiresValue = 0x01, + Required = 0x02 + }; + /** Return values of the parser. */ + enum + { + Success = 0x00, + UnknownOption = 0x01, + MissingValue = 0x02, + OptionAfterArgument = 0x04, + MalformedMultipleShortOption = 0x08, + RequiredOptionMissing = 0x16, + HelpRequested = 0x32 + }; + + bool defineOption(const std::string& _name, + const std::string& _description = std::string(), + OptionAttributes _attributes = NoAttribute); + + bool defineOption(const std::string& _shortname, + const std::string& _name, + const std::string& _description = std::string(), + OptionAttributes _attributes = NoAttribute); + /** Defines an option with optional attributes (required, ...) and an + * additional (also optional) description. The description becomes part of the + * generated usage help that can be requested by calling the usageDescription() + * method. + * \return Returns FALSE if there already is an option with this name + * OR if a short option string (length == 1) is a digit. In that case no + * action is peformed. + */ + bool defineOptionAlternative(const std::string& _original, + const std::string& _alternative); + /** Define an alternative name for an option that was previously defined by + * defineOption(). + * \return Returns FALSE if there already is an option with the alternative + * name or no option with the original name OR if a short option string + * (length == 1) is a digit. In that case no action is performed. + */ + bool isDefinedOption(const std::string& _name) const; + /** Returns whether _name is a defined option. */ + bool foundOption(const std::string& _name) const; + /** Returns whether _name is an option that was found while parsing + * the command line arguments with the parse() method. In other word: This + * method returns true if the string is an option AND it was given on the + * parsed command line. + */ + bool setHelpOption(const std::string& _longname = "h", + const std::string& _shortname = "help", + const std::string& _descr = ""); + /** Define a help option. If this option is found a special error code is + * returned by the parse method. + * \attention If this method is called twice without an intermediate call + * to the reset() method the previously set help option will remain a valid + * option but is not detected as the special help option and will therefore + * not cause the parse() method to return the special help error code. + * \return Returns FALSE if there already is an option defined that equals + * the short or long name. + */ + unsigned int arguments() const; + /** Returns the number of read arguments. Arguments are efined as beeing + * neither options nor option values and are specified at the end of the + * command line after all options and their values. */ + std::string argument(unsigned int _number) const; + /** Returns the Nth argument. See arguments(). + * \return Argument string or an empty string if there was no argument of + * that id. + */ + const std::vector& allArguments() const; + /** Get the complete argument vector. The order of the arguments in the + * vector is the same as on the commandline. + */ + void addErrorCode(int _code, const std::string& _descr = ""); + /** Add an error code and its description to the command line parser. + * This will do nothing more than adding an entry to the usage description. + */ + void setIntroduction(const std::string& _descr); + /** Set some string as a general description, that will be printed before + * the list of available options. + */ + ParserResults parse(int _argc, char ** _argv); + /** Parse the command line arguments for all known options and arguments. + * \return Error code with parsing result. + * \retval NoParserError Everything went fine. + * \retval ParserUnknownOption Unknown option was found. + * \retval ParserMissingValue A value to a given option is missing. + * \retval ParserOptionAfterArgument Option after an argument detected. All + * options have to given before the first argument. + * \retval ParserMalformedMultipleShortOption Malformed short option string. + * \retval ParserRequiredOptionMissing Required option is missing. + * \retval ParserHelpRequested Help option detected. + */ + std::string optionValue(const std::string& _option) const; + /** Return the value of an option. + * \return Value of a commandline options given by the name of the option or + * an empty string if there was no such option or the option required no + * value. + */ + void reset(); + /** Reset the parser. Call this function if you want to parse another set of + * command line arguments with the same parser object. + */ + const std::string& errorOption() const; + /** Returns the name of the option that was responsible for a parser error. + * An empty string is returned if no error occured at all. + */ + std::string parseErrorDescription(ParserResults _error_code) const; + /** This method can be used to evaluate parser error codes and generate a + * human-readable description. In case of a help request error code the + * usage description as returned by usageDescription() is printed. + */ + std::string usageDescription(unsigned int _width = 80) const; + /** Returns a string with the usage descriptions for all options. The + * description string is formated to fit into a terminal of width _width.*/ + +private: + int optionKey( const std::string& _name ) const; + /** Returns the key of a defined option with name _name or -1 if such option + * is not defined. */ + std::list getAllOptionAlternatives(unsigned int _key) const; + /** Returns a list of option names that are all alternative names associated + * with a single key value. + */ + + /** The current maximum key value for an option. */ + unsigned int max_key; + + /** Map option names to a numeric key. */ + String2KeyMap option2key; + + /** Map option key to option attributes. */ + Key2AttributeMap option2attribute; + + /** Map option key to option description. */ + Key2StringMap option2descr; + + /** Map option key to option value. */ + Key2StringMap option2value; + + /** Map error code to its description. */ + std::map errorcode2descr; + + /** Vector of command line arguments. */ + ArgumentContainer argument_container; + + /** General description to be returned as first part of the generated help page. */ + std::string intro_description; + + /** Holds the key for the help option. */ + unsigned int help_option; + + /** Holds the name of the option that was responsible for a parser error. + */ + std::string error_option; +}; // class ArgvParser + + +// Auxillary functions + +bool isValidOptionString(const std::string& _string); +/** Returns whether the given string is a valid (correct syntax) option string. + * It has to fullfill the following criteria: + * 1. minimum length is 2 characters + * 2. Start with '-' + * 3. if if minimal length -> must not be '--' + * 4. first short option character must not be a digit (to distinguish negative numbers) + */ + +bool isValidLongOptionString(const std::string& _string); +/** Returns whether the given string is a valid (correct syntax) long option string. + * It has to fullfill the following criteria: + * 1. minimum length is 4 characters + * 2. Start with '--' + */ + +bool splitOptionAndValue(const std::string& _string, std::string& _option, + std::string& _value); +/** Splits option and value string if they are given in the form 'option=value'. +* \return Returns TRUE if a value was found. +*/ + +template +void splitString(Container& _container, const std::string& _in, + const char* const _delimiters = " \t\n") +{ +/** String tokenizer using standard C++ functions. Taken from here: + * http://gcc.gnu.org/onlinedocs/libstdc++/21_strings/howto.html#3 + * Splits the string _in by _delimiters and store the tokens in _container. + */ + const std::string::size_type len = _in.length(); + std::string::size_type i = 0; + + while ( i < len ) + { + // eat leading whitespace + i = _in.find_first_not_of (_delimiters, i); + if (i == std::string::npos) + return; // nothing left but white space + + // find the end of the token + std::string::size_type j = _in.find_first_of (_delimiters, i); + + // push token + if (j == std::string::npos) + { + _container.push_back (_in.substr(i)); + return; + } + else + _container.push_back (_in.substr(i, j-i)); + + // set up for next loop + i = j + 1; + } +} + +bool isDigit(const char& _char); +/** Returns true if the character is a digit (what else?). */ + +bool expandRangeStringToUInt(const std::string& _string, + std::vector& _expanded); +/** Build a vector of integers from a string of the form: +* '1,3-5,14,25-20'. This string will be expanded to a list of positive +* integers with the following elements: 1,3,4,5,14,25,24,23,22,21,20. +* All of the expanded elements will be added to the provided list. +* \return Returns FALSE if there was any syntax error in the given string +* In that case the function stops at the point where the error occured. +* Only elements processed up to that point will be added to the expanded +* list. +* \attention This function can only handle unsigned integers! +*/ + +std::string trimmedString(const std::string& _str); +/** Returns a copy of _str with whitespace removed from front and back. */ + +std::string formatString(const std::string& _string, + unsigned int _width, + unsigned int _indent = 0); +/** Formats a string of an arbitrary length to fit a terminal of width +* _width and to be indented by _indent columns. +*/ + +} +; // namespace CommandLineProcessing + +#endif // __CMDLINEPARSER_H diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index fb2a816..095a687 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -20,6 +20,7 @@ #include #include #include // EXIT_SUCCESS +#include "argParse/argParse.h" // Tmux color lookup tables for the different metrics. #include "luts.h" @@ -52,12 +53,13 @@ // OSX: DONE/partial // BSD: TODO + std::string cpu_string(unsigned int cpu_usage_delay, unsigned int graph_lines, - bool use_colors = false) { - + bool use_colors = false) { + float percentage; - //output stuff + //output stuff std::ostringstream oss; oss.precision( 1 ); oss.setf( std::ios::fixed | std::ios::right ); @@ -66,75 +68,80 @@ std::string cpu_string(unsigned int cpu_usage_delay, unsigned int graph_lines, percentage = cpu_percentage( cpu_usage_delay ); if( use_colors ) - oss << cpu_percentage_lut[static_cast( percentage )]; - + oss << cpu_percentage_lut[static_cast( percentage )]; + oss << "["; oss << getGraphByPercentage( unsigned(percentage), graph_lines ); - oss << "]"; + oss << "]"; oss.width( 5 ); oss << percentage; oss << "%"; if( use_colors ) - oss << "#[fg=default,bg=default]"; + oss << "#[fg=default,bg=default]"; return oss.str(); } int main(int argc, char** argv) { - unsigned int cpu_usage_delay = 1000000; - int graph_lines = 10; + using namespace ArgvParse; + + unsigned cpu_usage_delay = 1000000; + unsigned short graph_lines = 10; // max 65535 should be enough bool use_colors = false; - try { - std::istringstream iss; - iss.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); - std::string current_arg; - unsigned int arg_index = 1; - if( argc > arg_index ) - { - if( strcmp( argv[arg_index], "--colors" ) == 0 ) - { - use_colors = true; - ++arg_index; - } - } - if( argc > arg_index ) - { - iss.str( argv[arg_index] ); - int status_interval; - iss >> status_interval; - if( status_interval < 1 ) - { - std::cerr << "Status interval argument must be one or greater." - << std::endl; - return EXIT_FAILURE; - } - cpu_usage_delay = status_interval * 1000000; - ++arg_index; - } - if( argc > arg_index ) - { - iss.str( argv[arg_index] ); - iss.clear(); - iss >> graph_lines; - if( graph_lines < 1 ) - { - std::cerr << "Graph lines argument must be one or greater." - << std::endl; - return EXIT_FAILURE; - } - } - } - catch(const std::exception &e) - { - std::cerr << "Usage: " << argv[0] - << " [--colors] [tmux_status-interval(seconds)] [graph lines]" - << std::endl; - return EXIT_FAILURE; - } + + // Argv parser + ArgvParser arg; + + arg.setIntroduction("tmux-mem-cpu-load \n" + "Usage: tmux-mem-cpu-load [OPTIONS]"); + + arg.setHelpOption("h", "help", "Prints this help message"); + + // define actual options + arg.defineOption("colors", "Use tmux colors in output", + ArgvParser::NoAttribute); + arg.defineOption("i", "interval", "set tmux status refresh interval in " + "seconds. Default: 1 second", ArgvParser::RequiresValue); + arg.defineOption("g", "graph-lines", "Set how many lines should be drawn in " + "a graph. Default: 10", ArgvParser::RequiresValue); + + int result = arg.parse(argc, argv); + + if (result != ArgvParser::Success) { + std::cerr << arg.parseErrorDescription(result); + return EXIT_FAILURE; + } + + // mangle arguments + std::istringstream iss; + iss.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); + + if (arg.foundOption("colors")) + use_colors = true; + + if (arg.foundOption("interval")){ + iss.str(arg.optionValue("interval")); + iss >> cpu_usage_delay; + if (cpu_usage_delay < 1) { + std::cerr << "Status interval argument must be one or greater.\n"; + return EXIT_FAILURE; + } + cpu_usage_delay *= 1000000; + } + + if (arg.foundOption("graph-lines")) { + iss.str( arg.optionValue("graph-lines") ); + iss.clear(); + iss >> graph_lines; + if( graph_lines < 1 ) { + std::cerr << "Graph lines argument must be one or greater.\n"; + return EXIT_FAILURE; + } + } std::cout << mem_string( use_colors ) << ' ' - << cpu_string( cpu_usage_delay, graph_lines, use_colors ) << ' ' - << load_string( use_colors ); + << cpu_string( cpu_usage_delay, graph_lines, use_colors ) << ' ' + << load_string( use_colors ); return EXIT_SUCCESS; } From d92113644ca64a19a887e38bd9ca2692e86e5c54 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Thu, 8 Jan 2015 19:31:25 +0100 Subject: [PATCH 41/80] use version generated by cmake, some vim auto reindent --- tmux-mem-cpu-load.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 095a687..f4bc060 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -92,8 +92,13 @@ int main(int argc, char** argv) { // Argv parser ArgvParser arg; - arg.setIntroduction("tmux-mem-cpu-load \n" - "Usage: tmux-mem-cpu-load [OPTIONS]"); + // ugly, I know + std::string intro = "tmux-mem-cpu-load v"; + intro += std::to_string(VERSION_MAJOR) + "." + std::to_string(VERSION_MINOR); + intro += "." + std::to_string(VERSION_PATCH) + "\n"; + intro += "Usage: tmux-mem-cpu-load [OPTIONS]"; + + arg.setIntroduction(intro); arg.setHelpOption("h", "help", "Prints this help message"); @@ -123,20 +128,20 @@ int main(int argc, char** argv) { iss.str(arg.optionValue("interval")); iss >> cpu_usage_delay; if (cpu_usage_delay < 1) { - std::cerr << "Status interval argument must be one or greater.\n"; - return EXIT_FAILURE; + std::cerr << "Status interval argument must be one or greater.\n"; + return EXIT_FAILURE; } cpu_usage_delay *= 1000000; } if (arg.foundOption("graph-lines")) { - iss.str( arg.optionValue("graph-lines") ); - iss.clear(); - iss >> graph_lines; - if( graph_lines < 1 ) { - std::cerr << "Graph lines argument must be one or greater.\n"; - return EXIT_FAILURE; - } + iss.str( arg.optionValue("graph-lines") ); + iss.clear(); + iss >> graph_lines; + if( graph_lines < 1 ) { + std::cerr << "Graph lines argument must be one or greater.\n"; + return EXIT_FAILURE; + } } std::cout << mem_string( use_colors ) << ' ' From aadca0d325db4e212bae7daea932497df5dc4c2e Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Thu, 8 Jan 2015 19:52:46 +0100 Subject: [PATCH 42/80] cleanups, fix tests to follow new arguments --- CMakeLists.txt | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fe9178..190ed8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,23 +46,15 @@ endif() # set common source files SET( COMMON_SOURCES "tmux-mem-cpu-load.cpp" "graph.cc" "argParse/argParse.cc" ) -# Search for boost -# will be needed later -#set(Boost_USE_STATIC_LIBS OFF) -#set(Boost_USE_MULTITHREADED ON) -#set(Boost_SUE_STATIC_RUTIME OFF) -#find_package(Boost 1.52.0 REQUIRED COMPONENTS filesystem program_options system) # compiler flags SET( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) # add binary tree so we find version.h -#include_directories("${PROJECT_BINARY_DIR}" ${Boost_INCLUDE_DIRS}) include_directories("${PROJECT_BINARY_DIR}" ) add_executable(tmux-mem-cpu-load ${COMMON_SOURCES} ${METER_SOURCES}) -#target_link_libraries(tmux-mem-cpu-load ${Boost_LIBRARIES}) install(TARGETS tmux-mem-cpu-load RUNTIME DESTINATION bin ) @@ -78,14 +70,11 @@ if( BUILD_TESTING ) add_test( NAME colors COMMAND tmux-mem-cpu-load --colors ) - add_test( NAME arguments - COMMAND tmux-mem-cpu-load --colors 1 4 ) - add_test( NAME invalid_status_interval - COMMAND tmux-mem-cpu-load -1 4 ) + COMMAND tmux-mem-cpu-load -i -1 ) add_test( NAME invalid_graph_lines - COMMAND tmux-mem-cpu-load 1 -4 ) + COMMAND tmux-mem-cpu-load -g -4 ) set_tests_properties( usage invalid_status_interval From c6fc061f9d6438a9c238e7177387589daf5ecd2d Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Thu, 8 Jan 2015 19:53:22 +0100 Subject: [PATCH 43/80] instead of using istringstream to convert form strin to int use stoi() function --- tmux-mem-cpu-load.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index f4bc060..85b008b 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -86,7 +86,7 @@ int main(int argc, char** argv) { using namespace ArgvParse; unsigned cpu_usage_delay = 1000000; - unsigned short graph_lines = 10; // max 65535 should be enough + short graph_lines = 10; // max 32767 should be enough bool use_colors = false; // Argv parser @@ -118,26 +118,20 @@ int main(int argc, char** argv) { } // mangle arguments - std::istringstream iss; - iss.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); - if (arg.foundOption("colors")) use_colors = true; - if (arg.foundOption("interval")){ - iss.str(arg.optionValue("interval")); - iss >> cpu_usage_delay; - if (cpu_usage_delay < 1) { + if (arg.foundOption("interval")) { + int delay = std::stoi(arg.optionValue("interval")); + if (delay < 1) { std::cerr << "Status interval argument must be one or greater.\n"; return EXIT_FAILURE; } - cpu_usage_delay *= 1000000; + cpu_usage_delay = delay * 1000000; } if (arg.foundOption("graph-lines")) { - iss.str( arg.optionValue("graph-lines") ); - iss.clear(); - iss >> graph_lines; + graph_lines = std::stoi(arg.optionValue("graph-lines")); if( graph_lines < 1 ) { std::cerr << "Graph lines argument must be one or greater.\n"; return EXIT_FAILURE; From 5001bc4fe7e0466ea08253ec7ff4667ebb0ace1b Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Thu, 8 Jan 2015 20:04:27 +0100 Subject: [PATCH 44/80] added custom interval test --- CMakeLists.txt | 5 ++++- tmux-mem-cpu-load.cpp | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 190ed8b..eef1146 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,9 @@ if( BUILD_TESTING ) add_test( NAME no_arguments COMMAND tmux-mem-cpu-load ) + add_test( NAME custom_interval + COMMAND tmux-mem-cpu-load -i 3 ) + add_test( NAME colors COMMAND tmux-mem-cpu-load --colors ) @@ -74,7 +77,7 @@ if( BUILD_TESTING ) COMMAND tmux-mem-cpu-load -i -1 ) add_test( NAME invalid_graph_lines - COMMAND tmux-mem-cpu-load -g -4 ) + COMMAND tmux-mem-cpu-load --graph_lines -2 ) set_tests_properties( usage invalid_status_interval diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 85b008b..4e343db 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -85,7 +85,7 @@ std::string cpu_string(unsigned int cpu_usage_delay, unsigned int graph_lines, int main(int argc, char** argv) { using namespace ArgvParse; - unsigned cpu_usage_delay = 1000000; + unsigned cpu_usage_delay = 990000; short graph_lines = 10; // max 32767 should be enough bool use_colors = false; @@ -127,7 +127,7 @@ int main(int argc, char** argv) { std::cerr << "Status interval argument must be one or greater.\n"; return EXIT_FAILURE; } - cpu_usage_delay = delay * 1000000; + cpu_usage_delay = delay * 1000000 - 10000; } if (arg.foundOption("graph-lines")) { From b02d0000e965074fcbb45a8f4f13f78c70cd3e81 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Fri, 9 Jan 2015 14:10:26 +0100 Subject: [PATCH 45/80] pulled Joe136 solution to MemAvailable being present in /proc/meminfo on some systems --- linux/memory.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/linux/memory.cc b/linux/memory.cc index 6497ccb..56d76ad 100644 --- a/linux/memory.cc +++ b/linux/memory.cc @@ -28,10 +28,17 @@ std::string mem_string( bool use_colors = false ) { for( unsigned int i = 0; i < 3; i++ ) { getline( meminfo_file, mem_line ); - substrStart = mem_line.find_first_of( ':' ) + 1; - substrLen = mem_line.find_first_of( 'k' ); - unused_mem = stoi(mem_line.substr(substrStart, substrLen)); - used_mem -= unused_mem; + // accomodate MemAvailable potentially being in lines 2-4 of + // /proc/meminfo. do this in a way to not break the original logic of the + // loop + if( mem_line.find("MemAvailable") == 0 ) + i--; + else { + substrStart = mem_line.find_first_of( ':' ) + 1; + substrLen = mem_line.find_first_of( 'k' ); + unused_mem = stoi(mem_line.substr(substrStart, substrLen)); + used_mem -= unused_mem; + } } meminfo_file.close(); From e7f2dd25e82c6ec6fc596e686c2f835f51e22eef Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Fri, 9 Jan 2015 14:52:50 +0100 Subject: [PATCH 46/80] use sysinfo() to get ram stats instead of parsing meminfo file. Idea pulled from seculabird gihub user. see: https://github.com/secularbird/tmux-mem-cpu-load/commit/880f8b196749ad2ed0ed376db0ba4da0595eeead --- linux/memory.cc | 44 ++++++++------------------------------------ 1 file changed, 8 insertions(+), 36 deletions(-) diff --git a/linux/memory.cc b/linux/memory.cc index 56d76ad..8e9d33f 100644 --- a/linux/memory.cc +++ b/linux/memory.cc @@ -1,6 +1,5 @@ -#include #include -#include +#include #include "memory.h" #include "../luts.h" @@ -8,41 +7,14 @@ std::string mem_string( bool use_colors = false ) { std::ostringstream oss; - unsigned int total_mem; - unsigned int used_mem; - unsigned int unused_mem; + struct sysinfo sinfo; + sysinfo(&sinfo); + + unsigned int total_mem = sinfo.totalram / 1014; + unsigned int used_mem = total_mem - sinfo.freeram / 1024; + // we don't need this for now + //unsigned int unused_mem = sinfo.freeram / 1024; - size_t substrStart; - size_t substrLen; - - std::ifstream meminfo_file( "/proc/meminfo" ); - - std::string mem_line; - - getline( meminfo_file, mem_line ); - substrStart = mem_line.find_first_of( ':' ) + 1; - substrLen = mem_line.find_first_of( 'k' ); - total_mem = stoi(mem_line.substr(substrStart, substrLen)); - - used_mem = total_mem; - - for( unsigned int i = 0; i < 3; i++ ) { - getline( meminfo_file, mem_line ); - // accomodate MemAvailable potentially being in lines 2-4 of - // /proc/meminfo. do this in a way to not break the original logic of the - // loop - if( mem_line.find("MemAvailable") == 0 ) - i--; - else { - substrStart = mem_line.find_first_of( ':' ) + 1; - substrLen = mem_line.find_first_of( 'k' ); - unused_mem = stoi(mem_line.substr(substrStart, substrLen)); - used_mem -= unused_mem; - } - } - - meminfo_file.close(); - if( use_colors ) { oss << mem_lut[(100 * used_mem) / total_mem]; } From 220d260673bfcce8a156329952386e793b28919e Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sat, 10 Jan 2015 17:27:54 +0100 Subject: [PATCH 47/80] use sysinfo() to get load avg instead of parsing /proc/ file --- linux/load.cc | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/linux/load.cc b/linux/load.cc index df4a54f..73d1779 100644 --- a/linux/load.cc +++ b/linux/load.cc @@ -1,23 +1,24 @@ #include #include -#include -#include +#include // sysconf()? +#include +#include // SI_LOAD_SHIFT #include "../luts.h" std::string load_string( bool use_colors = false ) { std::ostringstream oss; - std::ifstream loadavg_file( "/proc/loadavg" ); - std::string load_line; - std::getline( loadavg_file, load_line ); - loadavg_file.close(); + float f = static_cast(1 << SI_LOAD_SHIFT); + + struct sysinfo sinfo; + sysinfo(&sinfo); if( use_colors ) { // Likely does not work on BSD, but not tested unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN ); - float recent_load = stof(load_line.substr( 0, 4 )); + float recent_load = sinfo.loads[0] / f; // colors range from zero to twice the number of cpu's // for the most recent load metric @@ -29,8 +30,14 @@ std::string load_string( bool use_colors = false ) { oss << load_lut[load_percent]; } - - oss << load_line.substr( 0, 14 ); + + // set precision so we get results like "0.22" + oss.setf( std::ios::fixed ); + oss.precision(2); + + oss << sinfo.loads[0] / f << " " << sinfo.load[1] / f << " " + << sinfo.load[2] / f; + if( use_colors ) oss << "#[fg=default,bg=default]"; From 3e743ee1c204f74fde69178f6c7dd5a29a442df0 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sat, 10 Jan 2015 17:32:08 +0100 Subject: [PATCH 48/80] Hide cpu usage graph if graph_lines == 0. --- tmux-mem-cpu-load.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 85b008b..6970119 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -70,9 +70,11 @@ std::string cpu_string(unsigned int cpu_usage_delay, unsigned int graph_lines, if( use_colors ) oss << cpu_percentage_lut[static_cast( percentage )]; - oss << "["; - oss << getGraphByPercentage( unsigned(percentage), graph_lines ); - oss << "]"; + if( graph_lines > 0) { + oss << "["; + oss << getGraphByPercentage( unsigned(percentage), graph_lines ); + oss << "]"; + } oss.width( 5 ); oss << percentage; oss << "%"; @@ -132,8 +134,8 @@ int main(int argc, char** argv) { if (arg.foundOption("graph-lines")) { graph_lines = std::stoi(arg.optionValue("graph-lines")); - if( graph_lines < 1 ) { - std::cerr << "Graph lines argument must be one or greater.\n"; + if( graph_lines < 0 ) { + std::cerr << "Graph lines argument must be zero or greater.\n"; return EXIT_FAILURE; } } From 6b8b746a0ff6c93e30f41397b5e3407f72cfdc92 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sat, 10 Jan 2015 17:58:34 +0100 Subject: [PATCH 49/80] pull initial *BDS port from Justin Crawford (see github.com/Justasic/tmux-mem-cpu-load) --- bsd/FreeBSD.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++++++++ bsd/OpenBSD.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 290 insertions(+) create mode 100644 bsd/FreeBSD.cpp create mode 100644 bsd/OpenBSD.cpp diff --git a/bsd/FreeBSD.cpp b/bsd/FreeBSD.cpp new file mode 100644 index 0000000..725c240 --- /dev/null +++ b/bsd/FreeBSD.cpp @@ -0,0 +1,145 @@ +/* + * Copyright 2012 Matthew McCormick + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * */ +// This file was Authored by Justin Crawford +// Based on: https://github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c +// Based on: Apple.cpp for load_string/mem_string and apple's documentation + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Memory Sizes +#define KILOBYTES(x) ((x)/1024) +#define MEGABYTES(x) (KILOBYTES((x))/1024) +#define GIGABYTES(x) (MEGABYTES((x))/1024) + +// CPU percentages stuff +#define CP_USER 0 +#define CP_NICE 1 +#define CP_SYS 2 +#define CP_INTR 3 +#define CP_IDLE 4 +#define CPUSTATES 5 + +#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) +static inline void getsysctl(const char *name, void *ptr, size_t len) +{ + size_t nlen = len; + + if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) + { + fprintf(stderr, "sysctl(%s...) failed: %s\n", name, strerror(errno)); + exit(23); + } + + if (nlen != len) + { + fprintf(stderr, "sysctl(%s...) expected %lu bytes, got %lu bytes\n", name, (unsigned long)len, (unsigned long)nlen); + //exit(23); + } +} + +float cpu_percentage(unsigned int cpu_usage_delay) +{ + int64_t load1[CPUSTATES]; + int64_t load2[CPUSTATES]; + + GETSYSCTL("kern.cp_time", load1); + usleep(cpu_usage_delay); + GETSYSCTL("kern.cp_time", load2); + + // Current load times + unsigned long long current_user = load1[CP_USER]; + unsigned long long current_system = load1[CP_SYS]; + unsigned long long current_nice = load1[CP_NICE]; + unsigned long long current_idle = load1[CP_IDLE]; + // Next load times + unsigned long long next_user = load2[CP_USER]; + unsigned long long next_system = load2[CP_SYS]; + unsigned long long next_nice = load2[CP_NICE]; + unsigned long long next_idle = load2[CP_IDLE]; + // Difference between the two + unsigned long long diff_user = next_user - current_user; + unsigned long long diff_system = next_system - current_system; + unsigned long long diff_nice = next_nice - current_nice; + unsigned long long diff_idle = next_idle - current_idle; + + return static_cast(diff_user + diff_system + diff_nice)/static_cast(diff_user + diff_system + diff_nice + diff_idle)*100.0; +} + +std::string mem_string() +{ + // These values are in bytes + int64_t total_mem = 0; + int64_t used_mem = 0; + int64_t unused_mem = 0; + int32_t inactive_mem = 0; + int32_t active_mem = 0; + int32_t free_mem = 0; + int32_t wired_mem = 0; + int32_t page_size = 0; + int32_t cache_mem = 0; + std::ostringstream oss; + + // Get total physical memory, page size, and some other needed info + GETSYSCTL("hw.realmem", total_mem); + GETSYSCTL("hw.pagesize", page_size); + + GETSYSCTL("vm.stats.vm.v_free_count", free_mem); + GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_mem); + GETSYSCTL("vm.stats.vm.v_cache_count", cache_mem); + GETSYSCTL("vm.stats.vm.v_wire_count", wired_mem); + GETSYSCTL("vm.stats.vm.v_active_count", active_mem); + + // Get all memory which can be allocated + //unused_mem = (cache_mem + free_mem) * page_size; + used_mem = ((int64_t)active_mem + (int64_t)inactive_mem + (int64_t)wired_mem) * (int64_t)page_size; + + oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; + + return oss.str(); +} + +// Load Averages +std::string load_string() +{ + std::stringstream ss; + // Only get 3 load averages + int nelem = 3; + double averages[3]; + // based on: http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c + if(getloadavg(averages, nelem) < 0) + ss << "0.00 0.00 0.00"; // couldn't get averages. + else + { + for(int i = 0; i < nelem; ++i) + { + // Round to nearest, make sure this is only a 0.00 value not a 0.0000 + float avg = floorf(static_cast(averages[i]) * 100 + 0.5) / 100; + ss << avg << " "; + } + } + + return ss.str(); +} + diff --git a/bsd/OpenBSD.cpp b/bsd/OpenBSD.cpp new file mode 100644 index 0000000..f25e7d0 --- /dev/null +++ b/bsd/OpenBSD.cpp @@ -0,0 +1,145 @@ +/* + * Copyright 2012 Matthew McCormick + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * */ +// This file was Authored by Justin Crawford +// Based on: https://github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c +// Based on: Apple.cpp for load_string/mem_string and apple's documentation + +#error ToDo: OpenBSD. This file is incomplete and likely will not compile if you remove this error (it is here to tell you it's unfinished) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Memory Sizes +#define KILOBYTES(x) ((x)/1024) +#define MEGABYTES(x) (KILOBYTES((x))/1024) +#define GIGABYTES(x) (MEGABYTES((x))/1024) + +// CPU percentages stuff +#define CP_USER 0 +#define CP_NICE 1 +#define CP_SYS 2 +#define CP_INTR 3 +#define CP_IDLE 4 +#define CPUSTATES 5 + +#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) +static inline void getsysctl(const char *name, void *ptr, size_t len) +{ + size_t nlen = len; + + if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) + { + fprintf(stderr, "sysctl(%s...) failed: %s\n", name, strerror(errno)); + exit(23); + } + + if (nlen != len) + { + fprintf(stderr, "sysctl(%s...) expected %lu bytes, got %lu bytes\n", name, (unsigned long)len, (unsigned long)nlen); + //exit(23); + } +} + +float cpu_percentage(unsigned int cpu_usage_delay) +{ + int64_t load1[CPUSTATES]; + int64_t load2[CPUSTATES]; + + GETSYSCTL("kern.cp_time", load1); + usleep(cpu_usage_delay); + GETSYSCTL("kern.cp_time", load2); + + // Current load times + unsigned long long current_user = load1[CP_USER]; + unsigned long long current_system = load1[CP_SYS]; + unsigned long long current_nice = load1[CP_NICE]; + unsigned long long current_idle = load1[CP_IDLE]; + // Next load times + unsigned long long next_user = load2[CP_USER]; + unsigned long long next_system = load2[CP_SYS]; + unsigned long long next_nice = load2[CP_NICE]; + unsigned long long next_idle = load2[CP_IDLE]; + // Difference between the two + unsigned long long diff_user = next_user - current_user; + unsigned long long diff_system = next_system - current_system; + unsigned long long diff_nice = next_nice - current_nice; + unsigned long long diff_idle = next_idle - current_idle; + + return static_cast(diff_user + diff_system + diff_nice)/static_cast(diff_user + diff_system + diff_nice + diff_idle)*100.0; +} + +std::string mem_string() +{ + // These values are in bytes + int64_t total_mem = 0; + int64_t used_mem = 0; + int64_t unused_mem = 0; + int32_t inactive_mem = 0; + int32_t active_mem = 0; + int32_t free_mem = 0; + int32_t wired_mem = 0; + int32_t page_size = 0; + int32_t cache_mem = 0; + std::ostringstream oss; + + // Get total physical memory, page size, and some other needed info + GETSYSCTL("hw.realmem", total_mem); + GETSYSCTL("hw.pagesize", page_size); + + GETSYSCTL("vm.stats.vm.v_free_count", free_mem); + GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_mem); + GETSYSCTL("vm.stats.vm.v_cache_count", cache_mem); + GETSYSCTL("vm.stats.vm.v_wire_count", wired_mem); + + // Get all memory which can be allocated + //unused_mem = (inactive_mem + cache_mem + free_mem) * page_size; + used_mem = ((int64_t)active_mem + (int64_t)wired_mem + (int64_t)inactive_mem) * (int64_t)page_size; + + oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; + + return oss.str(); +} + +// Load Averages +std::string load_string() +{ + std::stringstream ss; + // Only get 3 load averages + int nelem = 3; + double averages[3]; + // based on: http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c + if(getloadavg(averages, nelem) < 0) + ss << "0.00 0.00 0.00"; // couldn't get averages. + else + { + for(int i = 0; i < nelem; ++i) + { + // Round to nearest, make sure this is only a 0.00 value not a 0.0000 + float avg = floorf(static_cast(averages[i]) * 100 + 0.5) / 100; + ss << avg << " "; + } + } + + return ss.str(); +} + From f59b11971f35990c58fb70b79b9415be74444849 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sat, 10 Jan 2015 18:34:37 +0100 Subject: [PATCH 50/80] *BDS port: - split *BDS files - add CMake confingure instructions on bsd systems - add includes to main file --- CMakeLists.txt | 6 +- bsd/FreeBSD.cpp | 145 ------------------------------------------ bsd/OpenBSD.cpp | 145 ------------------------------------------ bsd/common.h | 59 +++++++++++++++++ bsd/cpu.cc | 53 +++++++++++++++ bsd/cpu.h | 6 ++ bsd/load.cc | 47 ++++++++++++++ bsd/load.h | 8 +++ bsd/memory.h | 8 +++ bsd/memory_freebsd.cc | 61 ++++++++++++++++++ bsd/memory_openbsd.cc | 63 ++++++++++++++++++ tmux-mem-cpu-load.cpp | 13 +--- 12 files changed, 312 insertions(+), 302 deletions(-) delete mode 100644 bsd/FreeBSD.cpp delete mode 100644 bsd/OpenBSD.cpp create mode 100644 bsd/common.h create mode 100644 bsd/cpu.cc create mode 100644 bsd/cpu.h create mode 100644 bsd/load.cc create mode 100644 bsd/load.h create mode 100644 bsd/memory.h create mode 100644 bsd/memory_freebsd.cc create mode 100644 bsd/memory_openbsd.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index eef1146..cf08326 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,11 +34,13 @@ ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin") ELSEIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") # FreeBSD STUFF HERE message( "FreeBSD detected") - message( FATAL_ERROR "Free BSD is not supported yet" ) + message( WARNING "FreeBSD is still experimental!" ) + SET( METER_SOURCES "bsd/memory_freebsd.cc" "bsd/cpu.cc" "bsd/load.cc" ) ELSEIF(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") # OpenBSD Stuff Here message( "OpenBSD detected") - message( FATAL_ERROR "OpenBSD is not supported yet" ) + message( WARNING "OpenBSD is still experimental!" ) + SET( METER_SOURCES "bsd/memory_openbsd.cc" "bsd/cpu.cc" "bsd/load.cc" ) ELSE() message( FATAL_ERROR "Cannot be compiled on this system" ) endif() diff --git a/bsd/FreeBSD.cpp b/bsd/FreeBSD.cpp deleted file mode 100644 index 725c240..0000000 --- a/bsd/FreeBSD.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2012 Matthew McCormick - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * */ -// This file was Authored by Justin Crawford -// Based on: https://github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c -// Based on: Apple.cpp for load_string/mem_string and apple's documentation - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Memory Sizes -#define KILOBYTES(x) ((x)/1024) -#define MEGABYTES(x) (KILOBYTES((x))/1024) -#define GIGABYTES(x) (MEGABYTES((x))/1024) - -// CPU percentages stuff -#define CP_USER 0 -#define CP_NICE 1 -#define CP_SYS 2 -#define CP_INTR 3 -#define CP_IDLE 4 -#define CPUSTATES 5 - -#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) -static inline void getsysctl(const char *name, void *ptr, size_t len) -{ - size_t nlen = len; - - if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) - { - fprintf(stderr, "sysctl(%s...) failed: %s\n", name, strerror(errno)); - exit(23); - } - - if (nlen != len) - { - fprintf(stderr, "sysctl(%s...) expected %lu bytes, got %lu bytes\n", name, (unsigned long)len, (unsigned long)nlen); - //exit(23); - } -} - -float cpu_percentage(unsigned int cpu_usage_delay) -{ - int64_t load1[CPUSTATES]; - int64_t load2[CPUSTATES]; - - GETSYSCTL("kern.cp_time", load1); - usleep(cpu_usage_delay); - GETSYSCTL("kern.cp_time", load2); - - // Current load times - unsigned long long current_user = load1[CP_USER]; - unsigned long long current_system = load1[CP_SYS]; - unsigned long long current_nice = load1[CP_NICE]; - unsigned long long current_idle = load1[CP_IDLE]; - // Next load times - unsigned long long next_user = load2[CP_USER]; - unsigned long long next_system = load2[CP_SYS]; - unsigned long long next_nice = load2[CP_NICE]; - unsigned long long next_idle = load2[CP_IDLE]; - // Difference between the two - unsigned long long diff_user = next_user - current_user; - unsigned long long diff_system = next_system - current_system; - unsigned long long diff_nice = next_nice - current_nice; - unsigned long long diff_idle = next_idle - current_idle; - - return static_cast(diff_user + diff_system + diff_nice)/static_cast(diff_user + diff_system + diff_nice + diff_idle)*100.0; -} - -std::string mem_string() -{ - // These values are in bytes - int64_t total_mem = 0; - int64_t used_mem = 0; - int64_t unused_mem = 0; - int32_t inactive_mem = 0; - int32_t active_mem = 0; - int32_t free_mem = 0; - int32_t wired_mem = 0; - int32_t page_size = 0; - int32_t cache_mem = 0; - std::ostringstream oss; - - // Get total physical memory, page size, and some other needed info - GETSYSCTL("hw.realmem", total_mem); - GETSYSCTL("hw.pagesize", page_size); - - GETSYSCTL("vm.stats.vm.v_free_count", free_mem); - GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_mem); - GETSYSCTL("vm.stats.vm.v_cache_count", cache_mem); - GETSYSCTL("vm.stats.vm.v_wire_count", wired_mem); - GETSYSCTL("vm.stats.vm.v_active_count", active_mem); - - // Get all memory which can be allocated - //unused_mem = (cache_mem + free_mem) * page_size; - used_mem = ((int64_t)active_mem + (int64_t)inactive_mem + (int64_t)wired_mem) * (int64_t)page_size; - - oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; - - return oss.str(); -} - -// Load Averages -std::string load_string() -{ - std::stringstream ss; - // Only get 3 load averages - int nelem = 3; - double averages[3]; - // based on: http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c - if(getloadavg(averages, nelem) < 0) - ss << "0.00 0.00 0.00"; // couldn't get averages. - else - { - for(int i = 0; i < nelem; ++i) - { - // Round to nearest, make sure this is only a 0.00 value not a 0.0000 - float avg = floorf(static_cast(averages[i]) * 100 + 0.5) / 100; - ss << avg << " "; - } - } - - return ss.str(); -} - diff --git a/bsd/OpenBSD.cpp b/bsd/OpenBSD.cpp deleted file mode 100644 index f25e7d0..0000000 --- a/bsd/OpenBSD.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2012 Matthew McCormick - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * */ -// This file was Authored by Justin Crawford -// Based on: https://github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c -// Based on: Apple.cpp for load_string/mem_string and apple's documentation - -#error ToDo: OpenBSD. This file is incomplete and likely will not compile if you remove this error (it is here to tell you it's unfinished) - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Memory Sizes -#define KILOBYTES(x) ((x)/1024) -#define MEGABYTES(x) (KILOBYTES((x))/1024) -#define GIGABYTES(x) (MEGABYTES((x))/1024) - -// CPU percentages stuff -#define CP_USER 0 -#define CP_NICE 1 -#define CP_SYS 2 -#define CP_INTR 3 -#define CP_IDLE 4 -#define CPUSTATES 5 - -#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) -static inline void getsysctl(const char *name, void *ptr, size_t len) -{ - size_t nlen = len; - - if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) - { - fprintf(stderr, "sysctl(%s...) failed: %s\n", name, strerror(errno)); - exit(23); - } - - if (nlen != len) - { - fprintf(stderr, "sysctl(%s...) expected %lu bytes, got %lu bytes\n", name, (unsigned long)len, (unsigned long)nlen); - //exit(23); - } -} - -float cpu_percentage(unsigned int cpu_usage_delay) -{ - int64_t load1[CPUSTATES]; - int64_t load2[CPUSTATES]; - - GETSYSCTL("kern.cp_time", load1); - usleep(cpu_usage_delay); - GETSYSCTL("kern.cp_time", load2); - - // Current load times - unsigned long long current_user = load1[CP_USER]; - unsigned long long current_system = load1[CP_SYS]; - unsigned long long current_nice = load1[CP_NICE]; - unsigned long long current_idle = load1[CP_IDLE]; - // Next load times - unsigned long long next_user = load2[CP_USER]; - unsigned long long next_system = load2[CP_SYS]; - unsigned long long next_nice = load2[CP_NICE]; - unsigned long long next_idle = load2[CP_IDLE]; - // Difference between the two - unsigned long long diff_user = next_user - current_user; - unsigned long long diff_system = next_system - current_system; - unsigned long long diff_nice = next_nice - current_nice; - unsigned long long diff_idle = next_idle - current_idle; - - return static_cast(diff_user + diff_system + diff_nice)/static_cast(diff_user + diff_system + diff_nice + diff_idle)*100.0; -} - -std::string mem_string() -{ - // These values are in bytes - int64_t total_mem = 0; - int64_t used_mem = 0; - int64_t unused_mem = 0; - int32_t inactive_mem = 0; - int32_t active_mem = 0; - int32_t free_mem = 0; - int32_t wired_mem = 0; - int32_t page_size = 0; - int32_t cache_mem = 0; - std::ostringstream oss; - - // Get total physical memory, page size, and some other needed info - GETSYSCTL("hw.realmem", total_mem); - GETSYSCTL("hw.pagesize", page_size); - - GETSYSCTL("vm.stats.vm.v_free_count", free_mem); - GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_mem); - GETSYSCTL("vm.stats.vm.v_cache_count", cache_mem); - GETSYSCTL("vm.stats.vm.v_wire_count", wired_mem); - - // Get all memory which can be allocated - //unused_mem = (inactive_mem + cache_mem + free_mem) * page_size; - used_mem = ((int64_t)active_mem + (int64_t)wired_mem + (int64_t)inactive_mem) * (int64_t)page_size; - - oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; - - return oss.str(); -} - -// Load Averages -std::string load_string() -{ - std::stringstream ss; - // Only get 3 load averages - int nelem = 3; - double averages[3]; - // based on: http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c - if(getloadavg(averages, nelem) < 0) - ss << "0.00 0.00 0.00"; // couldn't get averages. - else - { - for(int i = 0; i < nelem; ++i) - { - // Round to nearest, make sure this is only a 0.00 value not a 0.0000 - float avg = floorf(static_cast(averages[i]) * 100 + 0.5) / 100; - ss << avg << " "; - } - } - - return ss.str(); -} - diff --git a/bsd/common.h b/bsd/common.h new file mode 100644 index 0000000..6925357 --- /dev/null +++ b/bsd/common.h @@ -0,0 +1,59 @@ +/* + * Copyright 2012 Matthew McCormick + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * */ +// This file was Authored by Justin Crawford +// Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c +// Based on: Apple.cpp for load_string/mem_string and apple's documentation + +#ifndef BSD_METER_COMMON_H_ +#define BSD_METER_COMMON_H_ + +#include +#include +#include +#include + +// Memory Sizes +#define KILOBYTES(x) ((x)/1024) +#define MEGABYTES(x) (KILOBYTES((x))/1024) +#define GIGABYTES(x) (MEGABYTES((x))/1024) + +// CPU percentages stuff +#define CP_USER 0 +#define CP_NICE 1 +#define CP_SYS 2 +#define CP_INTR 3 +#define CP_IDLE 4 +#define CPUSTATES 5 + +#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) +static inline void getsysctl(const char *name, void *ptr, size_t len) { + size_t nlen = len; + + if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) { + std::cerr << "sysctl(" << name << "...) failed: " << strerror(errno) + << std::endl; + exit(23); + } + + if (nlen != len) { + std::cerr << "sysctl(" << name << "...) expected " + << static_cast(len) << " bytes, got " + << static_cast(nlen) << " bytes\n"; + //exit(23); + } +} + +#endif diff --git a/bsd/cpu.cc b/bsd/cpu.cc new file mode 100644 index 0000000..a11b318 --- /dev/null +++ b/bsd/cpu.cc @@ -0,0 +1,53 @@ +/* + * Copyright 2012 Matthew McCormick + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * */ +// This file was Authored by Justin Crawford +// Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c +// Based on: Apple.cpp for load_string/mem_string and apple's documentation + +#include + +#include "common.h" +#include "cpu.h" + +float cpu_percentage(unsigned int cpu_usage_delay) +{ + int64_t load1[CPUSTATES]; + int64_t load2[CPUSTATES]; + + GETSYSCTL("kern.cp_time", load1); + usleep(cpu_usage_delay); + GETSYSCTL("kern.cp_time", load2); + + // Current load times + unsigned long long current_user = load1[CP_USER]; + unsigned long long current_system = load1[CP_SYS]; + unsigned long long current_nice = load1[CP_NICE]; + unsigned long long current_idle = load1[CP_IDLE]; + // Next load times + unsigned long long next_user = load2[CP_USER]; + unsigned long long next_system = load2[CP_SYS]; + unsigned long long next_nice = load2[CP_NICE]; + unsigned long long next_idle = load2[CP_IDLE]; + // Difference between the two + unsigned long long diff_user = next_user - current_user; + unsigned long long diff_system = next_system - current_system; + unsigned long long diff_nice = next_nice - current_nice; + unsigned long long diff_idle = next_idle - current_idle; + + return static_cast(diff_user + diff_system + diff_nice) / + static_cast(diff_user + diff_system + diff_nice + diff_idle) * + 100.0; +} diff --git a/bsd/cpu.h b/bsd/cpu.h new file mode 100644 index 0000000..beee11f --- /dev/null +++ b/bsd/cpu.h @@ -0,0 +1,6 @@ +#ifndef CPU_H_ +#define CPU_H_ + +float cpu_percentage(unsigned); + +#endif diff --git a/bsd/load.cc b/bsd/load.cc new file mode 100644 index 0000000..3515d5b --- /dev/null +++ b/bsd/load.cc @@ -0,0 +1,47 @@ +/* + * Copyright 2012 Matthew McCormick + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * */ +// This file was Authored by Justin Crawford +// Based on: https://github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c +// Based on: Apple.cpp for load_string/mem_string and apple's documentation + + +#include +#include +#include // getloadavg() +#include // floorf() + +#include "load.h" + +// Load Averages +std::string load_string() { + std::stringstream ss; + // Only get 3 load averages + int nelem = 3; + double averages[3]; + // based on: opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c + if(getloadavg(averages, nelem) < 0) + ss << "0.00 0.00 0.00"; // couldn't get averages. + else { + for(int i = 0; i < nelem; ++i) { + // Round to nearest, make sure this is only a 0.00 value not a 0.0000 + float avg = floorf(static_cast(averages[i]) * 100 + 0.5) / 100; + ss << avg << " "; + } + } + + return ss.str(); +} + diff --git a/bsd/load.h b/bsd/load.h new file mode 100644 index 0000000..3b8d814 --- /dev/null +++ b/bsd/load.h @@ -0,0 +1,8 @@ +#ifndef LOAD_H_ +#define LOAD_H_ + +#include + +std::string load_string( bool ); + +#endif diff --git a/bsd/memory.h b/bsd/memory.h new file mode 100644 index 0000000..196dfd6 --- /dev/null +++ b/bsd/memory.h @@ -0,0 +1,8 @@ +#ifndef MEMORY_H_ +#define MEMORY_H_ + +#include + +std::string mem_string( bool ); + +#endif diff --git a/bsd/memory_freebsd.cc b/bsd/memory_freebsd.cc new file mode 100644 index 0000000..e4991d6 --- /dev/null +++ b/bsd/memory_freebsd.cc @@ -0,0 +1,61 @@ +/* + * Copyright 2012 Matthew McCormick + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * */ +// This file was Authored by Justin Crawford +// Based on: https://github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c +// Based on: Apple.cpp for load_string/mem_string and apple's documentation + + +#include +#include +#include + +#include "common.h" +#include "memory.h" + +std::string mem_string() { + // These values are in bytes + int64_t total_mem = 0; + int64_t used_mem = 0; + int64_t unused_mem = 0; + int32_t inactive_mem = 0; + int32_t active_mem = 0; + int32_t free_mem = 0; + int32_t wired_mem = 0; + int32_t page_size = 0; + int32_t cache_mem = 0; + std::ostringstream oss; + + // Get total physical memory, page size, and some other needed info + GETSYSCTL("hw.realmem", total_mem); + GETSYSCTL("hw.pagesize", page_size); + + GETSYSCTL("vm.stats.vm.v_free_count", free_mem); + GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_mem); + GETSYSCTL("vm.stats.vm.v_cache_count", cache_mem); + GETSYSCTL("vm.stats.vm.v_wire_count", wired_mem); + GETSYSCTL("vm.stats.vm.v_active_count", active_mem); + + // Get all memory which can be allocated + //unused_mem = (cache_mem + free_mem) * page_size; + used_mem = ( + static_cast(active_mem) + static_cast(inactive_mem) + + static_cast(wired_mem)) * static_cast(page_size); + + oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; + + return oss.str(); +} + diff --git a/bsd/memory_openbsd.cc b/bsd/memory_openbsd.cc new file mode 100644 index 0000000..574fea0 --- /dev/null +++ b/bsd/memory_openbsd.cc @@ -0,0 +1,63 @@ +/* + * Copyright 2012 Matthew McCormick + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * */ +// This file was Authored by Justin Crawford +// Based on: https://github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c +// Based on: Apple.cpp for load_string/mem_string and apple's documentation + +#error ToDo: OpenBSD. This file is incomplete and likely will not compile if you remove this error (it is here to tell you it's unfinished) + +#include +#include +#include + +#include "common.h" +#include "memory.h" + +std::string mem_string() { + // These values are in bytes + int64_t total_mem = 0; + int64_t used_mem = 0; + int64_t unused_mem = 0; + int32_t inactive_mem = 0; + int32_t active_mem = 0; + int32_t free_mem = 0; + int32_t wired_mem = 0; + int32_t page_size = 0; + int32_t cache_mem = 0; + std::ostringstream oss; + + // Get total physical memory, page size, and some other needed info + GETSYSCTL("hw.realmem", total_mem); + GETSYSCTL("hw.pagesize", page_size); + + GETSYSCTL("vm.stats.vm.v_free_count", free_mem); + GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_mem); + GETSYSCTL("vm.stats.vm.v_cache_count", cache_mem); + GETSYSCTL("vm.stats.vm.v_wire_count", wired_mem); + + // Get all memory which can be allocated + //unused_mem = (inactive_mem + cache_mem + free_mem) * page_size; + used_mem = ( + static_cast(active_mem) + + static_cast(wired_mem) + + static_cast(inactive_mem)) * + static_cast(page_size); + + oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; + + return oss.str(); +} + diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 4e343db..979f469 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -34,10 +34,10 @@ #include "osx/load.h" #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) // BSD system - // TODO: Includes and *BSD support #define BSD_BASED 1 - // include _get_cpu_percentage (see osx/cpu.cc) - // include cpu_percentage (see osx/cpu.cc) + #include "bsd/cpu.h" + #include "bsd/load.h" + #include "bsd/memory.h" #else // assume linux system #include "linux/cpu.h" @@ -47,13 +47,6 @@ #include "graph.h" -// Function declarations. -// TODO: those should stay in separate headers -// LINUX: DONE/partial -// OSX: DONE/partial -// BSD: TODO - - std::string cpu_string(unsigned int cpu_usage_delay, unsigned int graph_lines, bool use_colors = false) { From df5d66fdbf81093158283dad12347da8d20cab4f Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 11 Jan 2015 18:01:13 +0100 Subject: [PATCH 51/80] fixed incorrect cpu usage While (as for manual) correct size of cpu states variable sould be 64 bits, the systctl actually return 32 bits for kern.cp_time. --- bsd/cpu.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bsd/cpu.cc b/bsd/cpu.cc index a11b318..3893b61 100644 --- a/bsd/cpu.cc +++ b/bsd/cpu.cc @@ -18,14 +18,15 @@ // Based on: Apple.cpp for load_string/mem_string and apple's documentation #include +#include // usleep #include "common.h" #include "cpu.h" float cpu_percentage(unsigned int cpu_usage_delay) { - int64_t load1[CPUSTATES]; - int64_t load2[CPUSTATES]; + int32_t load1[CPUSTATES]; + int32_t load2[CPUSTATES]; GETSYSCTL("kern.cp_time", load1); usleep(cpu_usage_delay); From a2e845945702012dfd39bde5a6e12446e4424eaa Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 11 Jan 2015 18:03:22 +0100 Subject: [PATCH 52/80] fixed uncorrect ram usage While (as per specification) size of total ram reported by sysctl should be 64 bits it's actually 32. --- bsd/memory_freebsd.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsd/memory_freebsd.cc b/bsd/memory_freebsd.cc index e4991d6..9651fa6 100644 --- a/bsd/memory_freebsd.cc +++ b/bsd/memory_freebsd.cc @@ -25,9 +25,9 @@ #include "common.h" #include "memory.h" -std::string mem_string() { +std::string mem_string( bool use_colors = false ) { // These values are in bytes - int64_t total_mem = 0; + int32_t total_mem = 0; int64_t used_mem = 0; int64_t unused_mem = 0; int32_t inactive_mem = 0; From e8dd4b442f8dc2c1eb30547d5cc2bfe9dc876b0a Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 11 Jan 2015 18:05:08 +0100 Subject: [PATCH 53/80] fixed functions headers to account for use_colors --- bsd/load.cc | 2 +- bsd/memory_openbsd.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bsd/load.cc b/bsd/load.cc index 3515d5b..f53d470 100644 --- a/bsd/load.cc +++ b/bsd/load.cc @@ -26,7 +26,7 @@ #include "load.h" // Load Averages -std::string load_string() { +std::string load_string( bool use_colors = false ) { std::stringstream ss; // Only get 3 load averages int nelem = 3; diff --git a/bsd/memory_openbsd.cc b/bsd/memory_openbsd.cc index 574fea0..c2cc3a9 100644 --- a/bsd/memory_openbsd.cc +++ b/bsd/memory_openbsd.cc @@ -26,7 +26,7 @@ #include "common.h" #include "memory.h" -std::string mem_string() { +std::string mem_string( bool use_colors = false ) { // These values are in bytes int64_t total_mem = 0; int64_t used_mem = 0; From a2df46dae53cb0b5fe540f492f4921918b7dabf2 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 11 Jan 2015 18:27:08 +0100 Subject: [PATCH 54/80] colorized output on *BSD systems --- bsd/load.cc | 22 ++++++++++++++++++++++ bsd/memory_freebsd.cc | 7 +++++++ bsd/memory_openbsd.cc | 15 ++++++++++----- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/bsd/load.cc b/bsd/load.cc index f53d470..695ca96 100644 --- a/bsd/load.cc +++ b/bsd/load.cc @@ -22,8 +22,11 @@ #include #include // getloadavg() #include // floorf() +#include +#include "common.h" #include "load.h" +#include "../luts.h" // Load Averages std::string load_string( bool use_colors = false ) { @@ -32,14 +35,33 @@ std::string load_string( bool use_colors = false ) { int nelem = 3; double averages[3]; // based on: opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c + if(getloadavg(averages, nelem) < 0) ss << "0.00 0.00 0.00"; // couldn't get averages. else { + if( use_colors ) { + // may not work + int32_t cpu_count = 0; + GETSYSCTL("hw.ncpu", cpu_count); + + unsigned load_percent = static_cast( + averages[0] / cpu_count * 0.5f * 100.0f); + + if( load_percent > 100 ) + load_percent = 100; + + ss << load_lut[load_percent]; + } + for(int i = 0; i < nelem; ++i) { // Round to nearest, make sure this is only a 0.00 value not a 0.0000 float avg = floorf(static_cast(averages[i]) * 100 + 0.5) / 100; ss << avg << " "; } + + if( use_colors ) + ss << "#[fg=default,bg=default]"; + } return ss.str(); diff --git a/bsd/memory_freebsd.cc b/bsd/memory_freebsd.cc index 9651fa6..ce7fe56 100644 --- a/bsd/memory_freebsd.cc +++ b/bsd/memory_freebsd.cc @@ -24,6 +24,7 @@ #include "common.h" #include "memory.h" +#include "../luts.h" std::string mem_string( bool use_colors = false ) { // These values are in bytes @@ -54,8 +55,14 @@ std::string mem_string( bool use_colors = false ) { static_cast(active_mem) + static_cast(inactive_mem) + static_cast(wired_mem)) * static_cast(page_size); + if( use_colors ) + oss << mem_lut[(100 * used_mem) / total_mem]; + oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; + if( use_colors ) + oss << "#[fg=default,bg=default]"; + return oss.str(); } diff --git a/bsd/memory_openbsd.cc b/bsd/memory_openbsd.cc index c2cc3a9..8264054 100644 --- a/bsd/memory_openbsd.cc +++ b/bsd/memory_openbsd.cc @@ -25,6 +25,7 @@ #include "common.h" #include "memory.h" +#include "../luts.h" std::string mem_string( bool use_colors = false ) { // These values are in bytes @@ -50,14 +51,18 @@ std::string mem_string( bool use_colors = false ) { // Get all memory which can be allocated //unused_mem = (inactive_mem + cache_mem + free_mem) * page_size; - used_mem = ( - static_cast(active_mem) + - static_cast(wired_mem) + - static_cast(inactive_mem)) * - static_cast(page_size); + used_mem = ( + static_cast(active_mem) + static_cast(wired_mem) + + static_cast(inactive_mem)) * static_cast(page_size); + + if( use_colors ) + oss << mem_lut[(100 * used_mem) / total_mem]; oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; + if( use_colors ) + oss << "#[fg=default,bg=default]"; + return oss.str(); } From 8264c6e2a29d3e1bbdfa8466c2b5ffcf7ab5e7f6 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Mon, 12 Jan 2015 15:21:43 +0100 Subject: [PATCH 55/80] drop OpenBSD support. See bsd/openBSD.txt for info --- CMakeLists.txt | 3 ++- bsd/openBSD.txt | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 bsd/openBSD.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index cf08326..b9406c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,8 @@ ELSEIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") ELSEIF(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") # OpenBSD Stuff Here message( "OpenBSD detected") - message( WARNING "OpenBSD is still experimental!" ) + message( FATAL_ERROR "OpenBSD is not supported! See bsd/openBSD.txt for more + info" ) SET( METER_SOURCES "bsd/memory_openbsd.cc" "bsd/cpu.cc" "bsd/load.cc" ) ELSE() message( FATAL_ERROR "Cannot be compiled on this system" ) diff --git a/bsd/openBSD.txt b/bsd/openBSD.txt new file mode 100644 index 0000000..4a7c804 --- /dev/null +++ b/bsd/openBSD.txt @@ -0,0 +1,19 @@ +About OpenBSD Port +================== + +I've decided not to do OpenBSD port. Some preparations has been made both +by myself and (mainly) by Justin Crawford, so finish it shouldn't be difficult. +Personally, after installing OpenBSD and trying to finish the port I've +discovered that g++ supplied by OpenBSD (version 5.7) doesn't support c++11. +This means we lose the ability to use to_string() and stoi() functions. I could +write replacements for them, or try to get c++11 working on OpenBSD. But I +decided not to. At least for the moment. + +I don't know OpenBSD, it's unfamiliar ground for me. And while FreeBSD was easy +to get into, I have found OpenBSD a little bit more difficult. + +So, no OpenBSD port for now. If you are OpenBSD user and know a little bit c++ +finishing the port should be easy (once you get C++11 working). + +l0ner + From f073450eddbf6252fdf1c8cb4c678e770458f8c7 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Mon, 12 Jan 2015 15:57:41 +0100 Subject: [PATCH 56/80] OSX: removed useless includes --- osx/cpu.cc | 13 ++----------- osx/load.cc | 1 + osx/memory.cc | 11 +---------- 3 files changed, 4 insertions(+), 21 deletions(-) diff --git a/osx/cpu.cc b/osx/cpu.cc index 71aaa3a..5f92aa3 100644 --- a/osx/cpu.cc +++ b/osx/cpu.cc @@ -1,17 +1,8 @@ -#include -#include -#include -#include -#include -#include -#include -#include #include -#include // for sysctl -#include // for integer types - #include // usleep() +#include "cpu.h" + // OSX or BSD based system, use BSD APIs instead // See: http://www.opensource.apple.com/source/xnu/xnu-201/osfmk/mach/host_info.h // and: http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/ diff --git a/osx/load.cc b/osx/load.cc index cea49cc..5469f46 100644 --- a/osx/load.cc +++ b/osx/load.cc @@ -6,6 +6,7 @@ #include #include // getloadavg() +#include "load.h" #include "../luts.h" std::string load_string( bool use_colors = false ) { diff --git a/osx/memory.cc b/osx/memory.cc index 1bac364..0c2f8e1 100644 --- a/osx/memory.cc +++ b/osx/memory.cc @@ -1,18 +1,9 @@ #include #include - -#include -#include -#include -#include -#include -#include -#include -#include #include #include // for sysctl -#include // for integer types +#include "memory.h" #include "../luts.h" std::string mem_string( bool use_colors ) { From d692eeaf93b0e86c6a39d098e68088ef36e0849a Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Mon, 12 Jan 2015 15:58:31 +0100 Subject: [PATCH 57/80] added missing include "load.h" --- linux/load.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/load.cc b/linux/load.cc index 73d1779..61a779a 100644 --- a/linux/load.cc +++ b/linux/load.cc @@ -4,6 +4,7 @@ #include #include // SI_LOAD_SHIFT +#include "load.h" #include "../luts.h" std::string load_string( bool use_colors = false ) { From 7151b70c700233867ad575735a178d0b3f38f5d2 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sat, 17 Jan 2015 16:23:55 +0100 Subject: [PATCH 58/80] Fixed typos in linux/load.cc --- linux/load.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/load.cc b/linux/load.cc index 61a779a..4a7443f 100644 --- a/linux/load.cc +++ b/linux/load.cc @@ -36,8 +36,8 @@ std::string load_string( bool use_colors = false ) { oss.setf( std::ios::fixed ); oss.precision(2); - oss << sinfo.loads[0] / f << " " << sinfo.load[1] / f << " " - << sinfo.load[2] / f; + oss << sinfo.loads[0] / f << " " << sinfo.loads[1] / f << " " + << sinfo.loads[2] / f; if( use_colors ) oss << "#[fg=default,bg=default]"; From 2cc9efb1873e9103f21255e13edcd19cae9dc94f Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sat, 17 Jan 2015 16:30:31 +0100 Subject: [PATCH 59/80] added compiler (and it's version) detection This should fix problems with different flags for c++11 across different gcc versions. Should compile on Clang and gcc >= 4.6. Lower versions of gcc are untested. I don't even know wheteher they support c++11 (gcc 4.2.1 on OpenBSD 5.7 does not). --- CMakeLists.txt | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b9406c6..97ec4ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,9 +49,24 @@ endif() # set common source files SET( COMMON_SOURCES "tmux-mem-cpu-load.cpp" "graph.cc" "argParse/argParse.cc" ) - # compiler flags -SET( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) +if (CMAKE_COMPILER_IS_GNUCC) + execute_process(COMMAD ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE GCC_VERSION) + if (GCC_VERSION VERSION_EQUAL 4.6) + SET( GCC_COVERAGE_COMPILE_FLAGS "-std=c++0x " ) + elseif (GCC_VERSION GREATER 4.6) + SET( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) + else() + message( FATAL_ERROR "You need gcc version >= 4.6") + endif() +elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + SET( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) +else() + message( WARNING "Untested compiler detected. You may need to set c++11 + support manually through CMakeList.txt file") + SET( GCC_COVERAGE_COMPILE_FLAGS "" ) +endif() SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) # add binary tree so we find version.h From 3475328dc414683af00bf49624c32be2b10b7018 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sat, 17 Jan 2015 16:37:45 +0100 Subject: [PATCH 60/80] added note to README about C++11 reqirement --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 3ce53be..53bf8f4 100644 --- a/README.rst +++ b/README.rst @@ -53,7 +53,7 @@ Building ~~~~~~~~ * >= CMake_ -2.6 -* C++ compiler (e.g. gcc/g++) +* C++ compiler with C++11 support (e.g. gcc/g++ >= 4.6) Download -------- From acaf9b0b2b8540d6e8ceb1f4e4d0fa6dd234fad7 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sat, 17 Jan 2015 16:46:33 +0100 Subject: [PATCH 61/80] fixed typo in CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97ec4ba..b9c58dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ SET( COMMON_SOURCES "tmux-mem-cpu-load.cpp" "graph.cc" "argParse/argParse.cc" ) # compiler flags if (CMAKE_COMPILER_IS_GNUCC) - execute_process(COMMAD ${CMAKE_C_COMPILER} -dumpversion + execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) if (GCC_VERSION VERSION_EQUAL 4.6) SET( GCC_COVERAGE_COMPILE_FLAGS "-std=c++0x " ) From 5fdb0e62272f8a1344d6e773e824e9f09234bcf5 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sat, 17 Jan 2015 17:15:01 +0100 Subject: [PATCH 62/80] remove merge leftovers from README --- README.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.rst b/README.rst index 53bf8f4..a4599eb 100644 --- a/README.rst +++ b/README.rst @@ -105,10 +105,7 @@ Contributions from: * Justin Crawford * krieiter -<<<<<<< HEAD -======= * Mark Palmeri ->>>>>>> upstream/master .. _tmux: http://tmux.sourceforge.net/ From 1cc6b0c9efd5aa07d98923af1e98417f5e0879c4 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sat, 17 Jan 2015 23:23:21 +0100 Subject: [PATCH 63/80] CMake style corrections --- CMakeLists.txt | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b9c58dd..e2bbfe1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,24 +25,24 @@ endif(NOT CMAKE_BUILD_TYPE) # detect system type if(CMAKE_SYSTEM_NAME MATCHES "Linux") - message( "Linux detected") - SET( METER_SOURCES "linux/memory.cc" "linux/cpu.cc" "linux/load.cc" ) -ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin") + message("Linux detected") + set(METER_SOURCES "linux/memory.cc" "linux/cpu.cc" "linux/load.cc") +elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") # Mac OS X source setting will go here message( "Darwin detected") - SET( METER_SOURCES "osx/memory.cc" "osx/cpu.cc" "osx/load.cc" ) -ELSEIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + set(METER_SOURCES "osx/memory.cc" "osx/cpu.cc" "osx/load.cc") +elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") # FreeBSD STUFF HERE - message( "FreeBSD detected") + message("FreeBSD detected") message( WARNING "FreeBSD is still experimental!" ) - SET( METER_SOURCES "bsd/memory_freebsd.cc" "bsd/cpu.cc" "bsd/load.cc" ) -ELSEIF(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") + set( METER_SOURCES "bsd/memory_freebsd.cc" "bsd/cpu.cc" "bsd/load.cc" ) +elseif(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") # OpenBSD Stuff Here message( "OpenBSD detected") message( FATAL_ERROR "OpenBSD is not supported! See bsd/openBSD.txt for more info" ) - SET( METER_SOURCES "bsd/memory_openbsd.cc" "bsd/cpu.cc" "bsd/load.cc" ) -ELSE() + set( METER_SOURCES "bsd/memory_openbsd.cc" "bsd/cpu.cc" "bsd/load.cc" ) +else() message( FATAL_ERROR "Cannot be compiled on this system" ) endif() @@ -54,20 +54,20 @@ if (CMAKE_COMPILER_IS_GNUCC) execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) if (GCC_VERSION VERSION_EQUAL 4.6) - SET( GCC_COVERAGE_COMPILE_FLAGS "-std=c++0x " ) + set( GCC_COVERAGE_COMPILE_FLAGS "-std=c++0x " ) elseif (GCC_VERSION GREATER 4.6) - SET( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) + set( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) else() message( FATAL_ERROR "You need gcc version >= 4.6") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - SET( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) + set( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) else() message( WARNING "Untested compiler detected. You may need to set c++11 support manually through CMakeList.txt file") - SET( GCC_COVERAGE_COMPILE_FLAGS "" ) + set( GCC_COVERAGE_COMPILE_FLAGS "" ) endif() -SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) # add binary tree so we find version.h include_directories("${PROJECT_BINARY_DIR}" ) From f2b75f7531b363308858f604def3c44b490f2c97 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sat, 17 Jan 2015 23:48:54 +0100 Subject: [PATCH 64/80] graph.cc: coding style fixes --- graph.cc | 48 ++++++++++++++++++++++++++++-------------------- graph.h | 6 ++++-- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/graph.cc b/graph.cc index 97130f2..bd172b3 100644 --- a/graph.cc +++ b/graph.cc @@ -3,34 +3,42 @@ #include "graph.h" -char * getGraphByPercentage(unsigned value, unsigned len) { - unsigned step = 0; - char * bars = new char[len + 1]; +std::string get_graph_by_percentage(unsigned value, unsigned len) +{ + unsigned step = 0; + std::string bars; - unsigned barCount = (static_cast(value) / 99.9 * len); + unsigned bar_count = (static_cast(value) / 99.9 * len); - for(step; step < barCount; step++) - bars[step] = '|'; - for(step; step < len; step++) - bars[step] = ' '; - bars[len]='\0'; + for(step; step < bar_count; step++) + { + bars.append("|"); + } + for(step; step < len; step++) + { + bars.append(" "); + } - return bars; + return bars; } -char * getGraphByValue(unsigned value, unsigned max, unsigned len) { - unsigned step = 0; - char * bars = new char[len + 1]; +std::string get_graph_by_value(unsigned value, unsigned max, unsigned len) +{ + unsigned step = 0; + std::string bars; - unsigned barCount = (static_cast(value / (max - 0.1)) * len); + unsigned bar_count = (static_cast(value / (max - 0.1)) * len); - for(step; step < barCount; step++) - bars[step] = '|'; - for(step; step < len; step++) - bars[step] = ' '; - bars[len]='\0'; + for(step; step < bar_count; step++) + { + bars.append("|"); + } + for(step; step < len; step++) + { + bars.append(" "); + } - return bars; + return bars; } diff --git a/graph.h b/graph.h index 34f96e1..7dd4c4e 100644 --- a/graph.h +++ b/graph.h @@ -1,7 +1,9 @@ #ifndef GRAPH_H_ #define GRAPH_H_ -char * getGraphByPercentage(unsigned, unsigned len = 10); -char * getGraphByValue(unsigned, unsigned, unsigned len = 10); +#include + +std::string get_graph_by_percentage(unsigned, unsigned len = 10); +std::string get_graph_by_value(unsigned, unsigned, unsigned len = 10); #endif From 3f4647a278247c33204b572615dee81c2d491190 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 14:27:30 +0100 Subject: [PATCH 65/80] added AUTHORS file to store all contributors --- AUTHORS | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 AUTHORS diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..1dc35ec --- /dev/null +++ b/AUTHORS @@ -0,0 +1,12 @@ +Original author and maintainer: + + Mattherw McCormick + +Contributors (in alphabetical order): + + Justin Crawford + krieiter + Mark Palmeri + Pawel 'l0ner' Soltys + + From d5506ac7973cfd08d797afe151d3fa20428a81a7 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 14:30:38 +0100 Subject: [PATCH 66/80] added myself (l0ner) to contributors list --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index a4599eb..9cf0128 100644 --- a/README.rst +++ b/README.rst @@ -106,9 +106,11 @@ Contributions from: * Justin Crawford * krieiter * Mark Palmeri +* `Pawel 'l0ner' Soltys`_ .. _tmux: http://tmux.sourceforge.net/ .. _CMake: http://www.cmake.org .. _`project homepage`: http://github.com/thewtex/tmux-mem-cpu-load .. _`terminals with 256 color support`: http://misc.flogisoft.com/bash/tip_colors_and_formatting#terminals_compatibility +.. _`Pawel 'l0ner' Soltys` : http://l0ner.github.io/ From 51f85ba0328dd727898eb616e5904f168dd9be97 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 14:31:04 +0100 Subject: [PATCH 67/80] code syntax style, vim modelines, license * Use std::sting instead of char[] in the graph drawing functions. This is the only change to the code. Rest is just styling. * Corrected whole code to follow Allman/GNU coding style, with 2 spaces for each indentation step. * Added license headers to all code files * Added vim modelines to all files. They sit on the first line and enable the following settings: 2 space indentation, tab expansion to spaces, line at 80th column, automatic line breaking on "\ !@*+-;:,./?" characters, automatic line break if line exceeds 80 colums. This should keep the code nice and tidy. --- CMakeLists.txt | 72 +++++++++++++++++---------- bsd/common.h | 29 ++++++----- bsd/cpu.cc | 59 +++++++++++----------- bsd/cpu.h | 20 +++++++- bsd/load.cc | 70 +++++++++++++++----------- bsd/load.h | 18 +++++++ bsd/memory.h | 18 +++++++ bsd/memory_freebsd.cc | 44 ++++++++++------- bsd/memory_openbsd.cc | 76 +++++++++++++++------------- graph.cc | 42 +++++++++++----- graph.h | 22 ++++++++- linux/cpu.cc | 89 ++++++++++++++++++++------------- linux/cpu.h | 20 +++++++- linux/load.cc | 84 ++++++++++++++++++++----------- linux/load.h | 18 +++++++ linux/memory.cc | 59 +++++++++++++++------- linux/memory.h | 18 +++++++ osx/cpu.cc | 96 ++++++++++++++++++++++-------------- osx/cpu.h | 17 +++++++ osx/load.cc | 112 ++++++++++++++++++++++++++---------------- osx/load.h | 17 +++++++ osx/memory.cc | 104 +++++++++++++++++++++++---------------- osx/memory.h | 18 +++++++ tmux-mem-cpu-load.cpp | 105 ++++++++++++++++++++++----------------- version.h.in | 18 +++++++ 25 files changed, 830 insertions(+), 415 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2bbfe1..69478ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,24 @@ +# vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap +# +# Copyright 2012 Matthew McCormick +# Copyright 2015 Pawel 'l0ner' Soltys +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + cmake_minimum_required(VERSION 2.6) if(COMMAND cmake_policy) - cmake_policy(VERSION 2.6) + cmake_policy(VERSION 2.6) endif(COMMAND cmake_policy) ### General Package stuff @@ -12,38 +30,38 @@ set(VERSION_PATCH 0) # generate header file to handle version configure_file( - "${PROJECT_SOURCE_DIR}/version.h.in" - "${PROJECT_SOURCE_DIR}/version.h" - ) + "${PROJECT_SOURCE_DIR}/version.h.in" + "${PROJECT_SOURCE_DIR}/version.h" + ) # set buold type if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING - "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." - FORCE) + "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." + FORCE) endif(NOT CMAKE_BUILD_TYPE) # detect system type if(CMAKE_SYSTEM_NAME MATCHES "Linux") - message("Linux detected") - set(METER_SOURCES "linux/memory.cc" "linux/cpu.cc" "linux/load.cc") + message("Linux detected") + set(METER_SOURCES "linux/memory.cc" "linux/cpu.cc" "linux/load.cc") elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") - # Mac OS X source setting will go here - message( "Darwin detected") - set(METER_SOURCES "osx/memory.cc" "osx/cpu.cc" "osx/load.cc") + # Mac OS X source setting will go here + message( "Darwin detected") + set(METER_SOURCES "osx/memory.cc" "osx/cpu.cc" "osx/load.cc") elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - # FreeBSD STUFF HERE - message("FreeBSD detected") - message( WARNING "FreeBSD is still experimental!" ) - set( METER_SOURCES "bsd/memory_freebsd.cc" "bsd/cpu.cc" "bsd/load.cc" ) + # FreeBSD STUFF HERE + message("FreeBSD detected") + message( WARNING "FreeBSD is still experimental!" ) + set( METER_SOURCES "bsd/memory_freebsd.cc" "bsd/cpu.cc" "bsd/load.cc" ) elseif(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") - # OpenBSD Stuff Here - message( "OpenBSD detected") - message( FATAL_ERROR "OpenBSD is not supported! See bsd/openBSD.txt for more - info" ) - set( METER_SOURCES "bsd/memory_openbsd.cc" "bsd/cpu.cc" "bsd/load.cc" ) + # OpenBSD Stuff Here + message( "OpenBSD detected") + message( FATAL_ERROR "OpenBSD is not supported! See bsd/openBSD.txt for more + info" ) + set( METER_SOURCES "bsd/memory_openbsd.cc" "bsd/cpu.cc" "bsd/load.cc" ) else() - message( FATAL_ERROR "Cannot be compiled on this system" ) + message( FATAL_ERROR "Cannot be compiled on this system" ) endif() # set common source files @@ -52,13 +70,13 @@ SET( COMMON_SOURCES "tmux-mem-cpu-load.cpp" "graph.cc" "argParse/argParse.cc" ) # compiler flags if (CMAKE_COMPILER_IS_GNUCC) execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion - OUTPUT_VARIABLE GCC_VERSION) + OUTPUT_VARIABLE GCC_VERSION) if (GCC_VERSION VERSION_EQUAL 4.6) - set( GCC_COVERAGE_COMPILE_FLAGS "-std=c++0x " ) + set( GCC_COVERAGE_COMPILE_FLAGS "-std=c++0x " ) elseif (GCC_VERSION GREATER 4.6) - set( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) + set( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) else() - message( FATAL_ERROR "You need gcc version >= 4.6") + message( FATAL_ERROR "You need gcc version >= 4.6") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) @@ -74,8 +92,8 @@ include_directories("${PROJECT_BINARY_DIR}" ) add_executable(tmux-mem-cpu-load ${COMMON_SOURCES} ${METER_SOURCES}) install(TARGETS tmux-mem-cpu-load - RUNTIME DESTINATION bin -) + RUNTIME DESTINATION bin + ) include( CTest ) if( BUILD_TESTING ) diff --git a/bsd/common.h b/bsd/common.h index 6925357..fb0ff7f 100644 --- a/bsd/common.h +++ b/bsd/common.h @@ -1,5 +1,7 @@ /* * Copyright 2012 Matthew McCormick + * Copyright 2013 Justin Crawford + * Copyright 2015 Pawel 'l0ner' Soltys * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,8 +14,8 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ -// This file was Authored by Justin Crawford + */ + // Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c // Based on: Apple.cpp for load_string/mem_string and apple's documentation @@ -39,20 +41,23 @@ #define CPUSTATES 5 #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) -static inline void getsysctl(const char *name, void *ptr, size_t len) { +static inline void getsysctl( const char *name, void *ptr, size_t len ) +{ size_t nlen = len; - if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) { - std::cerr << "sysctl(" << name << "...) failed: " << strerror(errno) - << std::endl; - exit(23); + if( sysctlbyname( name, ptr, &nlen, NULL, 0 ) == -1 ) + { + std::cerr << "sysctl(" << name << "...) failed: " << strerror( errno ) + << std::endl; + exit( 23 ); } - if (nlen != len) { - std::cerr << "sysctl(" << name << "...) expected " - << static_cast(len) << " bytes, got " - << static_cast(nlen) << " bytes\n"; - //exit(23); + if( nlen != len ) + { + std::cerr << "sysctl(" << name << "...) expected " + << static_cast( len ) << " bytes, got " + << static_cast( nlen ) << " bytes\n"; + //exit( 23 ); } } diff --git a/bsd/cpu.cc b/bsd/cpu.cc index 3893b61..9235ed1 100644 --- a/bsd/cpu.cc +++ b/bsd/cpu.cc @@ -1,5 +1,8 @@ -/* +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * * Copyright 2012 Matthew McCormick + * Copyright 2013 Justin Crawford + * Copyright 2015 Pawel 'l0ner' Soltys * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,8 +15,8 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ -// This file was Authored by Justin Crawford + */ + // Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c // Based on: Apple.cpp for load_string/mem_string and apple's documentation @@ -23,32 +26,32 @@ #include "common.h" #include "cpu.h" -float cpu_percentage(unsigned int cpu_usage_delay) +float cpu_percentage( unsigned int cpu_usage_delay ) { - int32_t load1[CPUSTATES]; - int32_t load2[CPUSTATES]; - - GETSYSCTL("kern.cp_time", load1); - usleep(cpu_usage_delay); - GETSYSCTL("kern.cp_time", load2); + int32_t load1[CPUSTATES]; + int32_t load2[CPUSTATES]; - // Current load times - unsigned long long current_user = load1[CP_USER]; - unsigned long long current_system = load1[CP_SYS]; - unsigned long long current_nice = load1[CP_NICE]; - unsigned long long current_idle = load1[CP_IDLE]; - // Next load times - unsigned long long next_user = load2[CP_USER]; - unsigned long long next_system = load2[CP_SYS]; - unsigned long long next_nice = load2[CP_NICE]; - unsigned long long next_idle = load2[CP_IDLE]; - // Difference between the two - unsigned long long diff_user = next_user - current_user; - unsigned long long diff_system = next_system - current_system; - unsigned long long diff_nice = next_nice - current_nice; - unsigned long long diff_idle = next_idle - current_idle; + GETSYSCTL( "kern.cp_time", load1 ); + usleep( cpu_usage_delay ); + GETSYSCTL( "kern.cp_time", load2 ); - return static_cast(diff_user + diff_system + diff_nice) / - static_cast(diff_user + diff_system + diff_nice + diff_idle) * - 100.0; + // Current load times + unsigned long long current_user = load1[CP_USER]; + unsigned long long current_system = load1[CP_SYS]; + unsigned long long current_nice = load1[CP_NICE]; + unsigned long long current_idle = load1[CP_IDLE]; + // Next load times + unsigned long long next_user = load2[CP_USER]; + unsigned long long next_system = load2[CP_SYS]; + unsigned long long next_nice = load2[CP_NICE]; + unsigned long long next_idle = load2[CP_IDLE]; + // Difference between the two + unsigned long long diff_user = next_user - current_user; + unsigned long long diff_system = next_system - current_system; + unsigned long long diff_nice = next_nice - current_nice; + unsigned long long diff_idle = next_idle - current_idle; + + return static_cast( diff_user + diff_system + diff_nice ) / + static_cast( diff_user + diff_system + diff_nice + diff_idle ) * + 100.0; } diff --git a/bsd/cpu.h b/bsd/cpu.h index beee11f..ebc0e8e 100644 --- a/bsd/cpu.h +++ b/bsd/cpu.h @@ -1,6 +1,24 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef CPU_H_ #define CPU_H_ -float cpu_percentage(unsigned); +float cpu_percentage( unsigned ); #endif diff --git a/bsd/load.cc b/bsd/load.cc index 695ca96..8b05ba4 100644 --- a/bsd/load.cc +++ b/bsd/load.cc @@ -1,5 +1,8 @@ -/* +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * * Copyright 2012 Matthew McCormick + * Copyright 2013 Justin Crawford + * Copyright 2015 Pawel 'l0ner' Soltys * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,11 +15,10 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ -// This file was Authored by Justin Crawford -// Based on: https://github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c -// Based on: Apple.cpp for load_string/mem_string and apple's documentation + */ +// Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c +// Based on: Apple.cpp for load_string/mem_string and apple's documentation #include #include @@ -29,38 +31,48 @@ #include "../luts.h" // Load Averages -std::string load_string( bool use_colors = false ) { +std::string load_string( bool use_colors = false ) +{ std::stringstream ss; - // Only get 3 load averages - int nelem = 3; - double averages[3]; + // Get only 3 load averages + const int nelem = 3; + double averages[nelem]; // based on: opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c - if(getloadavg(averages, nelem) < 0) - ss << "0.00 0.00 0.00"; // couldn't get averages. - else { - if( use_colors ) { - // may not work - int32_t cpu_count = 0; - GETSYSCTL("hw.ncpu", cpu_count); + if( getloadavg( averages, nelem ) < 0 ) + { + ss << "0.00 0.00 0.00"; // couldn't get averages. + } + else + { + if( use_colors ) + { + // may not work + int32_t cpu_count = 0; + GETSYSCTL( "hw.ncpu", cpu_count ); - unsigned load_percent = static_cast( - averages[0] / cpu_count * 0.5f * 100.0f); + unsigned load_percent = static_cast( averages[0] / + cpu_count * 0.5f * 100.0f ); - if( load_percent > 100 ) - load_percent = 100; + if( load_percent > 100 ) + { + load_percent = 100; + } - ss << load_lut[load_percent]; - } + ss << load_lut[load_percent]; + } - for(int i = 0; i < nelem; ++i) { - // Round to nearest, make sure this is only a 0.00 value not a 0.0000 - float avg = floorf(static_cast(averages[i]) * 100 + 0.5) / 100; - ss << avg << " "; - } + for( int i = 0; i < nelem; ++i ) + { + // Round to nearest, make sure this is only a 0.00 value not a 0.0000 + float avg = floorf( static_cast( averages[i] ) * 100 + 0.5 ) / 100; + ss << avg << " "; + } - if( use_colors ) - ss << "#[fg=default,bg=default]"; + if( use_colors ) + { + ss << "#[fg=default,bg=default]"; + } } diff --git a/bsd/load.h b/bsd/load.h index 3b8d814..f1bbc58 100644 --- a/bsd/load.h +++ b/bsd/load.h @@ -1,3 +1,21 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef LOAD_H_ #define LOAD_H_ diff --git a/bsd/memory.h b/bsd/memory.h index 196dfd6..3a123bb 100644 --- a/bsd/memory.h +++ b/bsd/memory.h @@ -1,3 +1,21 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef MEMORY_H_ #define MEMORY_H_ diff --git a/bsd/memory_freebsd.cc b/bsd/memory_freebsd.cc index ce7fe56..50d3e11 100644 --- a/bsd/memory_freebsd.cc +++ b/bsd/memory_freebsd.cc @@ -1,5 +1,7 @@ -/* +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,11 +14,10 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ -// This file was Authored by Justin Crawford -// Based on: https://github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c -// Based on: Apple.cpp for load_string/mem_string and apple's documentation + */ +// Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c +// Based on: Apple.cpp for load_string/mem_string and apple's documentation #include #include @@ -26,7 +27,8 @@ #include "memory.h" #include "../luts.h" -std::string mem_string( bool use_colors = false ) { +std::string mem_string( bool use_colors = false ) +{ // These values are in bytes int32_t total_mem = 0; int64_t used_mem = 0; @@ -40,28 +42,32 @@ std::string mem_string( bool use_colors = false ) { std::ostringstream oss; // Get total physical memory, page size, and some other needed info - GETSYSCTL("hw.realmem", total_mem); - GETSYSCTL("hw.pagesize", page_size); + GETSYSCTL( "hw.realmem", total_mem ); + GETSYSCTL( "hw.pagesize", page_size ); - GETSYSCTL("vm.stats.vm.v_free_count", free_mem); - GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_mem); - GETSYSCTL("vm.stats.vm.v_cache_count", cache_mem); - GETSYSCTL("vm.stats.vm.v_wire_count", wired_mem); - GETSYSCTL("vm.stats.vm.v_active_count", active_mem); + GETSYSCTL( "vm.stats.vm.v_free_count", free_mem ); + GETSYSCTL( "vm.stats.vm.v_inactive_count", inactive_mem ); + GETSYSCTL( "vm.stats.vm.v_cache_count", cache_mem ); + GETSYSCTL( "vm.stats.vm.v_wire_count", wired_mem ); + GETSYSCTL( "vm.stats.vm.v_active_count", active_mem ); // Get all memory which can be allocated //unused_mem = (cache_mem + free_mem) * page_size; - used_mem = ( - static_cast(active_mem) + static_cast(inactive_mem) + - static_cast(wired_mem)) * static_cast(page_size); + used_mem = ( static_cast( active_mem ) + + static_cast( inactive_mem ) + + static_cast( wired_mem ) ) * static_cast( page_size ); if( use_colors ) - oss << mem_lut[(100 * used_mem) / total_mem]; + { + oss << mem_lut[( 100 * used_mem ) / total_mem]; + } - oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; + oss << MEGABYTES( used_mem ) << '/' << MEGABYTES( total_mem ) << "MB"; if( use_colors ) - oss << "#[fg=default,bg=default]"; + { + oss << "#[fg=default,bg=default]"; + } return oss.str(); } diff --git a/bsd/memory_openbsd.cc b/bsd/memory_openbsd.cc index 8264054..84e29b8 100644 --- a/bsd/memory_openbsd.cc +++ b/bsd/memory_openbsd.cc @@ -1,5 +1,8 @@ -/* +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * * Copyright 2012 Matthew McCormick + * Copyright 2013 Justin Crawford + * Copyright 2015 Pawel 'l0ner' Soltys * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,9 +15,9 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ -// This file was Authored by Justin Crawford -// Based on: https://github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c + */ + +// Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c // Based on: Apple.cpp for load_string/mem_string and apple's documentation #error ToDo: OpenBSD. This file is incomplete and likely will not compile if you remove this error (it is here to tell you it's unfinished) @@ -27,42 +30,47 @@ #include "memory.h" #include "../luts.h" -std::string mem_string( bool use_colors = false ) { - // These values are in bytes - int64_t total_mem = 0; - int64_t used_mem = 0; - int64_t unused_mem = 0; - int32_t inactive_mem = 0; - int32_t active_mem = 0; - int32_t free_mem = 0; - int32_t wired_mem = 0; - int32_t page_size = 0; - int32_t cache_mem = 0; - std::ostringstream oss; +std::string mem_string( bool use_colors = false ) +{ + // These values are in bytes + int64_t total_mem = 0; + int64_t used_mem = 0; + int64_t unused_mem = 0; + int32_t inactive_mem = 0; + int32_t active_mem = 0; + int32_t free_mem = 0; + int32_t wired_mem = 0; + int32_t page_size = 0; + int32_t cache_mem = 0; + std::ostringstream oss; - // Get total physical memory, page size, and some other needed info - GETSYSCTL("hw.realmem", total_mem); - GETSYSCTL("hw.pagesize", page_size); + // Get total physical memory, page size, and some other needed info + GETSYSCTL( "hw.realmem", total_mem ); + GETSYSCTL( "hw.pagesize", page_size ); - GETSYSCTL("vm.stats.vm.v_free_count", free_mem); - GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_mem); - GETSYSCTL("vm.stats.vm.v_cache_count", cache_mem); - GETSYSCTL("vm.stats.vm.v_wire_count", wired_mem); + GETSYSCTL( "vm.stats.vm.v_free_count", free_mem ); + GETSYSCTL( "vm.stats.vm.v_inactive_count", inactive_mem ); + GETSYSCTL( "vm.stats.vm.v_cache_count", cache_mem ); + GETSYSCTL( "vm.stats.vm.v_wire_count", wired_mem ); - // Get all memory which can be allocated - //unused_mem = (inactive_mem + cache_mem + free_mem) * page_size; - used_mem = ( - static_cast(active_mem) + static_cast(wired_mem) + - static_cast(inactive_mem)) * static_cast(page_size); + // Get all memory which can be allocated + //unused_mem = (inactive_mem + cache_mem + free_mem) * page_size; + used_mem = ( + static_cast( active_mem ) + static_cast( wired_mem ) + + static_cast( inactive_mem ) ) * static_cast( page_size ); - if( use_colors ) - oss << mem_lut[(100 * used_mem) / total_mem]; + if( use_colors ) + { + oss << mem_lut[( 100 * used_mem ) / total_mem]; + } - oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; + oss << MEGABYTES( used_mem ) << '/' << MEGABYTES( total_mem ) << "MB"; - if( use_colors ) - oss << "#[fg=default,bg=default]"; + if( use_colors ) + { + oss << "#[fg=default,bg=default]"; + } - return oss.str(); + return oss.str(); } diff --git a/graph.cc b/graph.cc index bd172b3..8491f21 100644 --- a/graph.cc +++ b/graph.cc @@ -1,42 +1,60 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include #include #include "graph.h" -std::string get_graph_by_percentage(unsigned value, unsigned len) +std::string get_graph_by_percentage( unsigned value, unsigned len ) { unsigned step = 0; std::string bars; - unsigned bar_count = (static_cast(value) / 99.9 * len); + unsigned bar_count = ( static_cast(value) / 99.9 * len ); - for(step; step < bar_count; step++) + for( step; step < bar_count; step++ ) { - bars.append("|"); + bars.append( "|" ); } - for(step; step < len; step++) + for( step; step < len; step++ ) { - bars.append(" "); + bars.append( " " ); } return bars; } -std::string get_graph_by_value(unsigned value, unsigned max, unsigned len) +std::string get_graph_by_value( unsigned value, unsigned max, unsigned len ) { unsigned step = 0; std::string bars; - unsigned bar_count = (static_cast(value / (max - 0.1)) * len); + unsigned bar_count = ( static_cast( value / ( max - 0.1 ) ) * len ); - for(step; step < bar_count; step++) + for( step; step < bar_count; step++ ) { - bars.append("|"); + bars.append( "|" ); } - for(step; step < len; step++) + for( step; step < len; step++ ) { - bars.append(" "); + bars.append( " " ); } return bars; diff --git a/graph.h b/graph.h index 7dd4c4e..4034161 100644 --- a/graph.h +++ b/graph.h @@ -1,9 +1,27 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef GRAPH_H_ #define GRAPH_H_ #include -std::string get_graph_by_percentage(unsigned, unsigned len = 10); -std::string get_graph_by_value(unsigned, unsigned, unsigned len = 10); +std::string get_graph_by_percentage( unsigned, unsigned len = 10 ); +std::string get_graph_by_value( unsigned, unsigned, unsigned len = 10 ); #endif diff --git a/linux/cpu.cc b/linux/cpu.cc index d5bc804..e55ccb2 100644 --- a/linux/cpu.cc +++ b/linux/cpu.cc @@ -1,3 +1,21 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include #include #include // usleep @@ -5,47 +23,48 @@ #include "cpu.h" #include "../luts.h" -float cpu_percentage( unsigned cpu_usage_delay ) { - std::string line; - size_t substrStart = 0; - size_t substrLen; +float cpu_percentage( unsigned cpu_usage_delay ) +{ + std::string line; + size_t substr_start = 0; + size_t substr_len; - // cpu stats - // user, nice, system, idle - // in that order - unsigned long long stats[4]; + // cpu stats + // user, nice, system, idle + // in that order + unsigned long long stats[4]; - std::ifstream stat_file("/proc/stat"); - getline(stat_file, line); - stat_file.close(); + std::ifstream stat_file( "/proc/stat" ); + getline( stat_file, line ); + stat_file.close(); - // skip "cpu" - substrLen = line.find_first_of(" ", 3); - // parse cpu line - for(unsigned i=0; i < 4; i++) { - substrStart = line.find_first_not_of(" ", substrLen); - substrLen = line.find_first_of (" ", substrStart); - stats[i] = std::stoll( - line.substr(substrStart, substrLen)); - } + // skip "cpu" + substr_len = line.find_first_of( " ", 3 ); + // parse cpu line + for( unsigned i=0; i < 4; i++ ) + { + substr_start = line.find_first_not_of( " ", substr_len ); + substr_len = line.find_first_of( " ", substr_start ); + stats[i] = std::stoll( line.substr( substr_start, substr_len ) ); + } - usleep( cpu_usage_delay ); + usleep( cpu_usage_delay ); - stat_file.open("/proc/stat"); - getline(stat_file, line); - stat_file.close(); + stat_file.open( "/proc/stat" ); + getline( stat_file, line ); + stat_file.close(); - // skip "cpu" - substrLen = line.find_first_of(" ", 3); - // parse cpu line - for(unsigned i=0; i < 4; i++) { - substrStart = line.find_first_not_of(" ", substrLen); - substrLen = line.find_first_of (" ", substrStart); - stats[i] = std::stoll( - line.substr(substrStart, substrLen)) - stats[i]; - } + // skip "cpu" + substr_len = line.find_first_of( " ", 3 ); + // parse cpu line + for( unsigned i=0; i < 4; i++ ) + { + substr_start = line.find_first_not_of( " ", substr_len ); + substr_len = line.find_first_of ( " ", substr_start ); + stats[i] = std::stoll( line.substr( substr_start, substr_len ) ) - stats[i]; + } - return static_cast( stats[0] + stats[1] + stats[2]) / - static_cast( stats[0] + stats[1] + stats[2] + stats[3] ) * 100.0; + return static_cast( stats[0] + stats[1] + stats[2]) / + static_cast( stats[0] + stats[1] + stats[2] + stats[3] ) * 100.0; } diff --git a/linux/cpu.h b/linux/cpu.h index beee11f..ebc0e8e 100644 --- a/linux/cpu.h +++ b/linux/cpu.h @@ -1,6 +1,24 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef CPU_H_ #define CPU_H_ -float cpu_percentage(unsigned); +float cpu_percentage( unsigned ); #endif diff --git a/linux/load.cc b/linux/load.cc index 4a7443f..917a20b 100644 --- a/linux/load.cc +++ b/linux/load.cc @@ -1,3 +1,21 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include #include #include // sysconf()? @@ -7,40 +25,46 @@ #include "load.h" #include "../luts.h" -std::string load_string( bool use_colors = false ) { - std::ostringstream oss; +std::string load_string( bool use_colors = false ) +{ + std::ostringstream oss; - float f = static_cast(1 << SI_LOAD_SHIFT); + float f = static_cast( 1 << SI_LOAD_SHIFT ); - struct sysinfo sinfo; - sysinfo(&sinfo); + struct sysinfo sinfo; + sysinfo( &sinfo ); - if( use_colors ) { - // Likely does not work on BSD, but not tested - unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN ); + if( use_colors ) + { + // Likely does not work on BSD, but not tested + unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN ); - float recent_load = sinfo.loads[0] / f; + float recent_load = sinfo.loads[0] / f; - // colors range from zero to twice the number of cpu's - // for the most recent load metric - unsigned load_percent = static_cast< unsigned int >( - recent_load / number_of_cpus * 0.5f * 100.0f ); - - if( load_percent > 100 ) - load_percent = 100; - - oss << load_lut[load_percent]; - } - - // set precision so we get results like "0.22" - oss.setf( std::ios::fixed ); - oss.precision(2); - - oss << sinfo.loads[0] / f << " " << sinfo.loads[1] / f << " " - << sinfo.loads[2] / f; - - if( use_colors ) - oss << "#[fg=default,bg=default]"; + // colors range from zero to twice the number of cpu's + // for the most recent load metric + unsigned load_percent = static_cast< unsigned int >( + recent_load / number_of_cpus * 0.5f * 100.0f ); - return oss.str(); + if( load_percent > 100 ) + { + load_percent = 100; + } + + oss << load_lut[load_percent]; + } + + // set precision so we get results like "0.22" + oss.setf( std::ios::fixed ); + oss.precision( 2 ); + + oss << sinfo.loads[0] / f << " " << sinfo.loads[1] / f << " " + << sinfo.loads[2] / f; + + if( use_colors ) + { + oss << "#[fg=default,bg=default]"; + } + + return oss.str(); } diff --git a/linux/load.h b/linux/load.h index 3b8d814..f1bbc58 100644 --- a/linux/load.h +++ b/linux/load.h @@ -1,3 +1,21 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef LOAD_H_ #define LOAD_H_ diff --git a/linux/memory.cc b/linux/memory.cc index 8e9d33f..42580a5 100644 --- a/linux/memory.cc +++ b/linux/memory.cc @@ -1,30 +1,51 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include #include #include "memory.h" #include "../luts.h" -std::string mem_string( bool use_colors = false ) { - std::ostringstream oss; +std::string mem_string( bool use_colors = false ) +{ + std::ostringstream oss; - struct sysinfo sinfo; - sysinfo(&sinfo); + struct sysinfo sinfo; + sysinfo(&sinfo); - unsigned int total_mem = sinfo.totalram / 1014; - unsigned int used_mem = total_mem - sinfo.freeram / 1024; - // we don't need this for now - //unsigned int unused_mem = sinfo.freeram / 1024; - - if( use_colors ) { - oss << mem_lut[(100 * used_mem) / total_mem]; - } - - oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; - - if( use_colors ) { - oss << "#[fg=default,bg=default]"; - } + unsigned int total_mem = sinfo.totalram / 1014; + unsigned int used_mem = total_mem - sinfo.freeram / 1024; + // we don't need this for now + //unsigned int unused_mem = sinfo.freeram / 1024; - return oss.str(); + if( use_colors ) + { + oss << mem_lut[(100 * used_mem) / total_mem]; + } + + oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; + + if( use_colors ) + { + oss << "#[fg=default,bg=default]"; + } + + return oss.str(); } diff --git a/linux/memory.h b/linux/memory.h index 196dfd6..3a123bb 100644 --- a/linux/memory.h +++ b/linux/memory.h @@ -1,3 +1,21 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef MEMORY_H_ #define MEMORY_H_ diff --git a/osx/cpu.cc b/osx/cpu.cc index 5f92aa3..f38fbe4 100644 --- a/osx/cpu.cc +++ b/osx/cpu.cc @@ -1,3 +1,21 @@ +/* + * Copyright 2012 Matthew McCormick + * Copyright 2013 Justin Crawford + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include #include // usleep() @@ -6,48 +24,52 @@ // OSX or BSD based system, use BSD APIs instead // See: http://www.opensource.apple.com/source/xnu/xnu-201/osfmk/mach/host_info.h // and: http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/ -// -host_cpu_load_info_data_t _get_cpu_percentage() { - kern_return_t error; - mach_msg_type_number_t count; - host_cpu_load_info_data_t r_load; - mach_port_t mach_port; - count = HOST_CPU_LOAD_INFO_COUNT; - mach_port = mach_host_self(); - error = host_statistics(mach_port, HOST_CPU_LOAD_INFO, ( - host_info_t)&r_load, &count); - - if (error != KERN_SUCCESS) - return host_cpu_load_info_data_t(); +host_cpu_load_info_data_t _get_cpu_percentage() +{ + kern_return_t error; + mach_msg_type_number_t count; + host_cpu_load_info_data_t r_load; + mach_port_t mach_port; - return r_load; + count = HOST_CPU_LOAD_INFO_COUNT; + mach_port = mach_host_self(); + error = host_statistics(mach_port, HOST_CPU_LOAD_INFO, + ( host_info_t )&r_load, &count ); + + if ( error != KERN_SUCCESS ) + { + return host_cpu_load_info_data_t(); + } + + return r_load; } -float cpu_percentage( unsigned int cpu_usage_delay ) { - // Get the load times from the XNU kernel - host_cpu_load_info_data_t load1 = _get_cpu_percentage(); - usleep(cpu_usage_delay); - host_cpu_load_info_data_t load2 = _get_cpu_percentage(); +float cpu_percentage( unsigned int cpu_usage_delay ) +{ + // Get the load times from the XNU kernel + host_cpu_load_info_data_t load1 = _get_cpu_percentage(); + usleep( cpu_usage_delay ); + host_cpu_load_info_data_t load2 = _get_cpu_percentage(); - // Current load times - unsigned long long current_user = load1.cpu_ticks[CPU_STATE_USER]; - unsigned long long current_system = load1.cpu_ticks[CPU_STATE_SYSTEM]; - unsigned long long current_nice = load1.cpu_ticks[CPU_STATE_NICE]; - unsigned long long current_idle = load1.cpu_ticks[CPU_STATE_IDLE]; - // Next load times - unsigned long long next_user = load2.cpu_ticks[CPU_STATE_USER]; - unsigned long long next_system = load2.cpu_ticks[CPU_STATE_SYSTEM]; - unsigned long long next_nice = load2.cpu_ticks[CPU_STATE_NICE]; - unsigned long long next_idle = load2.cpu_ticks[CPU_STATE_IDLE]; - // Difference between the two - unsigned long long diff_user = next_user - current_user; - unsigned long long diff_system = next_system - current_system; - unsigned long long diff_nice = next_nice - current_nice; - unsigned long long diff_idle = next_idle - current_idle; + // Current load times + unsigned long long current_user = load1.cpu_ticks[CPU_STATE_USER]; + unsigned long long current_system = load1.cpu_ticks[CPU_STATE_SYSTEM]; + unsigned long long current_nice = load1.cpu_ticks[CPU_STATE_NICE]; + unsigned long long current_idle = load1.cpu_ticks[CPU_STATE_IDLE]; + // Next load times + unsigned long long next_user = load2.cpu_ticks[CPU_STATE_USER]; + unsigned long long next_system = load2.cpu_ticks[CPU_STATE_SYSTEM]; + unsigned long long next_nice = load2.cpu_ticks[CPU_STATE_NICE]; + unsigned long long next_idle = load2.cpu_ticks[CPU_STATE_IDLE]; + // Difference between the two + unsigned long long diff_user = next_user - current_user; + unsigned long long diff_system = next_system - current_system; + unsigned long long diff_nice = next_nice - current_nice; + unsigned long long diff_idle = next_idle - current_idle; - return static_cast(diff_user + diff_system + diff_nice) / - static_cast( - diff_user + diff_system + diff_nice + diff_idle) * 100.0; + return static_cast( diff_user + diff_system + diff_nice ) / + static_cast( diff_user + diff_system + diff_nice + diff_idle ) * + 100.0; } diff --git a/osx/cpu.h b/osx/cpu.h index 2dc2b8f..1652c03 100644 --- a/osx/cpu.h +++ b/osx/cpu.h @@ -1,3 +1,20 @@ +/* + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef CPU_H_ #define CPU_H_ diff --git a/osx/load.cc b/osx/load.cc index 5469f46..029add2 100644 --- a/osx/load.cc +++ b/osx/load.cc @@ -1,3 +1,21 @@ +/* + * Copyright 2012 Matthew McCormick + * Copyright 2013 Justin Crawford + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include #include #include @@ -9,53 +27,63 @@ #include "load.h" #include "../luts.h" -std::string load_string( bool use_colors = false ) { - std::ostringstream oss; +std::string load_string( bool use_colors = false ) +{ + std::ostringstream oss; - // Both apple and BSD style systems have these api calls - // Only get 3 load averages - int nelem = 3; - double averages[3]; - // based on: - // http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c - if( getloadavg(averages, nelem) < 0 ) - oss << "0.00 0.00 0.00"; // couldn't get averages. - else - for(int i = 0; i < nelem; ++i) { - // Round to nearest, make sure this is - // only a 0.00 value not a 0.0000 - float avg = floorf( - static_cast(averages[i]) * 100 + 0.5) / 100; - oss << avg << " "; - } + // Both apple and BSD style systems have these api calls + // Only get 3 load averages + const int nelem = 3; + double averages[nelem]; + // based on: + // http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c + if( getloadavg( averages, nelem ) < 0 ) + { + oss << "0.00 0.00 0.00"; // couldn't get averages. + } + else + { + for( int i = 0; i < nelem; ++i ) + { + // Round to nearest, make sure this is + // only a 0.00 value not a 0.0000 + float avg = floorf( static_cast( averages[i] ) * 100 + 0.5 ) / 100; + oss << avg << " "; + } + } - std::string load_line( oss.str() ); - oss.str( "" ); + std::string load_line( oss.str() ); + oss.str( "" ); - if( use_colors ) { - // Likely does not work on BSD, but not tested - unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN ); + if( use_colors ) + { + // Likely does not work on BSD, but not tested + unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN ); - std::istringstream iss( load_line.substr( 0, 4 ) ); - float recent_load; - iss >> recent_load; - // colors range from zero to twice the number of - // cpu's for the most recent load metric - - unsigned load_percent = static_cast< unsigned int >( - recent_load / number_of_cpus * 0.5f * 100.0f ); - - if( load_percent > 100 ) - load_percent = 100; - - oss << load_lut[load_percent]; - } + std::istringstream iss( load_line.substr( 0, 4 ) ); + float recent_load; + iss >> recent_load; + // colors range from zero to twice the number of + // cpu's for the most recent load metric - oss << load_line.substr( 0, 14 ); - - if( use_colors ) - oss << "#[fg=default,bg=default]"; + unsigned load_percent = static_cast< unsigned int >( + recent_load / number_of_cpus * 0.5f * 100.0f ); - return oss.str(); + if( load_percent > 100 ) + { + load_percent = 100; + } + + oss << load_lut[load_percent]; + } + + oss << load_line.substr( 0, 14 ); + + if( use_colors ) + { + oss << "#[fg=default,bg=default]"; + } + + return oss.str(); } diff --git a/osx/load.h b/osx/load.h index 3b8d814..16cd762 100644 --- a/osx/load.h +++ b/osx/load.h @@ -1,3 +1,20 @@ +/* + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef LOAD_H_ #define LOAD_H_ diff --git a/osx/memory.cc b/osx/memory.cc index 0c2f8e1..d83e5be 100644 --- a/osx/memory.cc +++ b/osx/memory.cc @@ -1,3 +1,21 @@ +/* + * Copyright 2012 Matthew McCormick + * Copyright 2013 Justin Crawford + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include #include #include @@ -6,51 +24,55 @@ #include "memory.h" #include "../luts.h" -std::string mem_string( bool use_colors ) { - std::ostringstream oss; - - // These values are in bytes - int64_t total_mem; - int64_t used_mem; - int64_t unused_mem; - - vm_size_t page_size; - mach_port_t mach_port; - mach_msg_type_number_t count; - vm_statistics_data_t vm_stats; +std::string mem_string( bool use_colors ) +{ + std::ostringstream oss; - // Get total physical memory - int mib[2]; - mib[0] = CTL_HW; - mib[1] = HW_MEMSIZE; - size_t length = sizeof(int64_t); - sysctl(mib, 2, &total_mem, &length, NULL, 0); + // These values are in bytes + int64_t total_mem; + int64_t used_mem; + int64_t unused_mem; - mach_port = mach_host_self(); - count = sizeof(vm_stats) / sizeof(natural_t); - if (KERN_SUCCESS == host_page_size( mach_port, &page_size) && - KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, - (host_info_t)&vm_stats, &count)) { - unused_mem = (int64_t)vm_stats.free_count * (int64_t)page_size; + vm_size_t page_size; + mach_port_t mach_port; + mach_msg_type_number_t count; + vm_statistics_data_t vm_stats; - used_mem = ( - (int64_t)vm_stats.active_count + - (int64_t)vm_stats.inactive_count + - (int64_t)vm_stats.wire_count) * - (int64_t)page_size; - } + // Get total physical memory + int mib[2]; + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + size_t length = sizeof( int64_t ); + sysctl( mib, 2, &total_mem, &length, NULL, 0 ); - // To kilobytes - used_mem /= 1024; - total_mem /= 1024; + mach_port = mach_host_self(); + count = sizeof( vm_stats ) / sizeof( natural_t ); + if( KERN_SUCCESS == host_page_size( mach_port, &page_size ) && + KERN_SUCCESS == host_statistics( mach_port, HOST_VM_INFO, + ( host_info_t )&vm_stats, &count ) ) + { + unused_mem = ( int64_t )vm_stats.free_count * ( int64_t )page_size; - if( use_colors ) - oss << mem_lut[(100 * used_mem) / total_mem]; - - oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; - - if( use_colors ) - oss << "#[fg=default,bg=default]"; + used_mem = ( ( int64_t )vm_stats.active_count + + ( int64_t )vm_stats.inactive_count + ( int64_t )vm_stats.wire_count + ) * ( int64_t )page_size; + } - return oss.str(); + // To kilobytes + used_mem /= 1024; + total_mem /= 1024; + + if( use_colors ) + { + oss << mem_lut[( 100 * used_mem ) / total_mem]; + } + + oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; + + if( use_colors ) + { + oss << "#[fg=default,bg=default]"; + } + + return oss.str(); } diff --git a/osx/memory.h b/osx/memory.h index 196dfd6..3d89aa3 100644 --- a/osx/memory.h +++ b/osx/memory.h @@ -1,3 +1,21 @@ +/* + * Copyright 2012 Matthew McCormick + * Copyright 2013 Justin Crawford + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef MEMORY_H_ #define MEMORY_H_ diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 6f99a9d..a859889 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -1,4 +1,5 @@ -/* +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * * Copyright 2012 Matthew McCormick * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +13,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ + */ #include #include @@ -20,13 +21,14 @@ #include #include #include // EXIT_SUCCESS + #include "argParse/argParse.h" +#include "version.h" +#include "graph.h" // Tmux color lookup tables for the different metrics. #include "luts.h" -#include "version.h" - #if defined(__APPLE__) && defined(__MACH__) // Apple osx system #include "osx/cpu.h" @@ -45,10 +47,9 @@ #include "linux/load.h" #endif -#include "graph.h" - -std::string cpu_string(unsigned int cpu_usage_delay, unsigned int graph_lines, - bool use_colors = false) { +std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines, + bool use_colors = false ) +{ float percentage; @@ -61,23 +62,29 @@ std::string cpu_string(unsigned int cpu_usage_delay, unsigned int graph_lines, percentage = cpu_percentage( cpu_usage_delay ); if( use_colors ) - oss << cpu_percentage_lut[static_cast( percentage )]; + { + oss << cpu_percentage_lut[static_cast( percentage )]; + } - if( graph_lines > 0) { - oss << "["; - oss << getGraphByPercentage( unsigned(percentage), graph_lines ); - oss << "]"; + if( graph_lines > 0) + { + oss << "["; + oss << get_graph_by_percentage( unsigned( percentage ), graph_lines ); + oss << "]"; } oss.width( 5 ); oss << percentage; oss << "%"; if( use_colors ) - oss << "#[fg=default,bg=default]"; + { + oss << "#[fg=default,bg=default]"; + } return oss.str(); } -int main(int argc, char** argv) { +int main( int argc, char** argv ) +{ using namespace ArgvParse; unsigned cpu_usage_delay = 990000; @@ -89,53 +96,59 @@ int main(int argc, char** argv) { // ugly, I know std::string intro = "tmux-mem-cpu-load v"; - intro += std::to_string(VERSION_MAJOR) + "." + std::to_string(VERSION_MINOR); - intro += "." + std::to_string(VERSION_PATCH) + "\n"; + intro += std::to_string( VERSION_MAJOR ) + "."; + intro += std::to_string( VERSION_MINOR ) + "."; + intro += std::to_string( VERSION_PATCH ) + "\n"; intro += "Usage: tmux-mem-cpu-load [OPTIONS]"; - arg.setIntroduction(intro); + arg.setIntroduction( intro ); - arg.setHelpOption("h", "help", "Prints this help message"); + arg.setHelpOption( "h", "help", "Prints this help message" ); // define actual options - arg.defineOption("colors", "Use tmux colors in output", - ArgvParser::NoAttribute); - arg.defineOption("i", "interval", "set tmux status refresh interval in " - "seconds. Default: 1 second", ArgvParser::RequiresValue); - arg.defineOption("g", "graph-lines", "Set how many lines should be drawn in " - "a graph. Default: 10", ArgvParser::RequiresValue); + arg.defineOption( "colors", "Use tmux colors in output", + ArgvParser::NoAttribute ); + arg.defineOption( "i", "interval", "set tmux status refresh interval in " + "seconds. Default: 1 second", ArgvParser::RequiresValue ); + arg.defineOption( "g", "graph-lines", "Set how many lines should be drawn in " + "a graph. Default: 10", ArgvParser::RequiresValue ); - int result = arg.parse(argc, argv); + int result = arg.parse( argc, argv ); - if (result != ArgvParser::Success) { - std::cerr << arg.parseErrorDescription(result); - return EXIT_FAILURE; + if( result != ArgvParser::Success ) + { + std::cerr << arg.parseErrorDescription( result ); + return EXIT_FAILURE; } // mangle arguments - if (arg.foundOption("colors")) - use_colors = true; + if( arg.foundOption( "colors" ) ) + use_colors = true; - if (arg.foundOption("interval")) { - int delay = std::stoi(arg.optionValue("interval")); - if (delay < 1) { - std::cerr << "Status interval argument must be one or greater.\n"; - return EXIT_FAILURE; - } - cpu_usage_delay = delay * 1000000 - 10000; + if( arg.foundOption( "interval" ) ) + { + int delay = std::stoi( arg.optionValue( "interval" ) ); + if( delay < 1 ) + { + std::cerr << "Status interval argument must be one or greater.\n"; + return EXIT_FAILURE; + } + cpu_usage_delay = delay * 1000000 - 10000; } - if (arg.foundOption("graph-lines")) { - graph_lines = std::stoi(arg.optionValue("graph-lines")); - if( graph_lines < 0 ) { - std::cerr << "Graph lines argument must be zero or greater.\n"; - return EXIT_FAILURE; - } + if( arg.foundOption( "graph-lines" ) ) + { + graph_lines = std::stoi( arg.optionValue( "graph-lines" ) ); + if( graph_lines < 0 ) + { + std::cerr << "Graph lines argument must be zero or greater.\n"; + return EXIT_FAILURE; + } } std::cout << mem_string( use_colors ) << ' ' - << cpu_string( cpu_usage_delay, graph_lines, use_colors ) << ' ' - << load_string( use_colors ); + << cpu_string( cpu_usage_delay, graph_lines, use_colors ) << ' ' + << load_string( use_colors ); return EXIT_SUCCESS; } diff --git a/version.h.in b/version.h.in index 8bbfddb..81a4c45 100644 --- a/version.h.in +++ b/version.h.in @@ -1,3 +1,21 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // the configured options and settings for sysstat #define VERSION_MAJOR @VERSION_MAJOR@ #define VERSION_MINOR @VERSION_MINOR@ From 89a4b0c0482764f17f679ef54f4128e9ba04ad78 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 14:51:27 +0100 Subject: [PATCH 68/80] version defines prefixed with name, full version now the version variables will be prefixed with 'tmux-mem-cpu-load'. This way we won't clash with any future dependency that might redefine those variables. This is exactly how CMake does it in their code, see: https://github.com/Kitware/CMake/blob/f3e92d281682ee482b1425675b9fccd372cd01f3/Source/CMakeVersion.cmake https://github.com/Kitware/CMake/blob/6ae98ee18f6c35b93556a66dc0ce909d84aec18b/Source/cmVersionConfig.h.in https://github.com/Kitware/CMake/blob/6ae98ee18f6c35b93556a66dc0ce909d84aec18b/Source/CMakeVersionCompute.cmake the only difference is that they have functions that return the versions and I use those variables directly. https://github.com/Kitware/CMake/blob/6ae98ee18f6c35b93556a66dc0ce909d84aec18b/Source/cmVersion.cxx Since the partial version variables are not used anywhere in the code we might as well remove them from version.h.in. I've deciced to leave them for now, since we might need them in the future. --- CMakeLists.txt | 9 ++++++--- tmux-mem-cpu-load.cpp | 6 ++---- version.h.in | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 69478ff..75079e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,9 +24,12 @@ endif(COMMAND cmake_policy) ### General Package stuff project( tmux-mem-cpu-load ) -set(VERSION_MAJOR 2) -set(VERSION_MINOR 3) -set(VERSION_PATCH 0) +set(tmux-mem-cpu-load_VERSION_MAJOR 2) +set(tmux-mem-cpu-load_VERSION_MINOR 3) +set(tmux-mem-cpu-load_VERSION_PATCH 0) +#Compute full version string +set(tmux-mem-cpu-load_VERSION + ${tmux-mem-cpu-load_VERSION_MAJOR}.${tmux-mem-cpu-load_VERSION_MINOR}.${tmux-mem-cpu-load_VERSION_PATCH}) # generate header file to handle version configure_file( diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index a859889..15d090f 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -96,10 +96,8 @@ int main( int argc, char** argv ) // ugly, I know std::string intro = "tmux-mem-cpu-load v"; - intro += std::to_string( VERSION_MAJOR ) + "."; - intro += std::to_string( VERSION_MINOR ) + "."; - intro += std::to_string( VERSION_PATCH ) + "\n"; - intro += "Usage: tmux-mem-cpu-load [OPTIONS]"; + intro += tmux_mem_cpu_load_VERSION; + intro += "\nUsage: tmux-mem-cpu-load [OPTIONS]"; arg.setIntroduction( intro ); diff --git a/version.h.in b/version.h.in index 81a4c45..c46dd04 100644 --- a/version.h.in +++ b/version.h.in @@ -17,7 +17,7 @@ */ // the configured options and settings for sysstat -#define VERSION_MAJOR @VERSION_MAJOR@ -#define VERSION_MINOR @VERSION_MINOR@ -#define VERSION_PATCH @VERSION_PATCH@ - +#define tmux_mem_cpu_load_VERSION_MAJOR @tmux-mem-cpu-load_VERSION_MAJOR@ +#define tmux_mem_cpu_load_VERSION_MINOR @tmux-mem-cpu-load_VERSION_MINOR@ +#define tmux_mem_cpu_load_VERSION_PATCH @tmux-mem-cpu-load_VERSION_PATCH@ +#define tmux_mem_cpu_load_VERSION "@tmux-mem-cpu-load_VERSION@" From ae4e160ede7754e50741c1fa5233c48d9e076b81 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 15:07:11 +0100 Subject: [PATCH 69/80] added test case for graph_lines = 0 --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75079e6..92b9e59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,9 @@ if( BUILD_TESTING ) add_test( NAME custom_interval COMMAND tmux-mem-cpu-load -i 3 ) + add_test( NAME no_cpu_graph + COMMAND tmux-mem-cpu-load -g 0 ) + add_test( NAME colors COMMAND tmux-mem-cpu-load --colors ) From b2084ea3b35bfc72d3b13aa616222ca381e74c36 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 16:59:19 +0100 Subject: [PATCH 70/80] better c++11 detection https://github.com/l0ner/tmux-mem-cpu-load/commit/2cc9efb1873e9103f21255e13edcd19cae9dc94f#commitcomment-9327965 Instead of checking for compiler version or whether it supports c++ features through target_compile_features test whether compiler supports one of the c++11 flags (-std=c++11 or -std=c++0x). Cleaner and simplier code. And we can make it fail loudly if comiler does not support c++11 --- CMakeLists.txt | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 92b9e59..9a229c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,6 @@ if(COMMAND cmake_policy) endif(COMMAND cmake_policy) ### General Package stuff - project( tmux-mem-cpu-load ) set(tmux-mem-cpu-load_VERSION_MAJOR 2) set(tmux-mem-cpu-load_VERSION_MINOR 3) @@ -31,10 +30,23 @@ set(tmux-mem-cpu-load_VERSION_PATCH 0) set(tmux-mem-cpu-load_VERSION ${tmux-mem-cpu-load_VERSION_MAJOR}.${tmux-mem-cpu-load_VERSION_MINOR}.${tmux-mem-cpu-load_VERSION_PATCH}) +# Check whether we have support for c++11 in compiler and fail if we don't +include(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) +CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) + +if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +elseif(COMPILER_SUPPORTS_CXX0X) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +else() + message(FATAL_ERROR " +Compiler ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} has no C++11 support.") +endif() + # generate header file to handle version configure_file( - "${PROJECT_SOURCE_DIR}/version.h.in" - "${PROJECT_SOURCE_DIR}/version.h" + "${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h" ) # set buold type @@ -70,33 +82,11 @@ endif() # set common source files SET( COMMON_SOURCES "tmux-mem-cpu-load.cpp" "graph.cc" "argParse/argParse.cc" ) -# compiler flags -if (CMAKE_COMPILER_IS_GNUCC) - execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion - OUTPUT_VARIABLE GCC_VERSION) - if (GCC_VERSION VERSION_EQUAL 4.6) - set( GCC_COVERAGE_COMPILE_FLAGS "-std=c++0x " ) - elseif (GCC_VERSION GREATER 4.6) - set( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) - else() - message( FATAL_ERROR "You need gcc version >= 4.6") - endif() -elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - set( GCC_COVERAGE_COMPILE_FLAGS "-std=c++11 " ) -else() - message( WARNING "Untested compiler detected. You may need to set c++11 - support manually through CMakeList.txt file") - set( GCC_COVERAGE_COMPILE_FLAGS "" ) -endif() -set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) - # add binary tree so we find version.h include_directories("${PROJECT_BINARY_DIR}" ) add_executable(tmux-mem-cpu-load ${COMMON_SOURCES} ${METER_SOURCES}) -install(TARGETS tmux-mem-cpu-load - RUNTIME DESTINATION bin - ) +install(TARGETS tmux-mem-cpu-load RUNTIME DESTINATION bin) include( CTest ) if( BUILD_TESTING ) From d3eb9e3187b53c6304904f8ff71113d9b8875ece Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 17:21:19 +0100 Subject: [PATCH 71/80] use macros from config.h to calculate megabyes instead of using hard coded divisions to calculate ram stats it's better to use macros defined in config.h. BSD port was doing this already, using macros defined in it's common.h header. I pulled those macros out and applied them to all platforms. File version.h.in got renamed into config.h.in since it doesn't caontain only the version anymore. --- CMakeLists.txt | 2 +- bsd/common.h | 5 ----- bsd/memory_freebsd.cc | 1 + bsd/memory_openbsd.cc | 1 + version.h.in => config.h.in | 5 +++++ linux/memory.cc | 9 +++++---- osx/memory.cc | 7 ++----- tmux-mem-cpu-load.cpp | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) rename version.h.in => config.h.in (88%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a229c2..4e42569 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,7 @@ endif() # generate header file to handle version configure_file( - "${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h" + "${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_SOURCE_DIR}/config.h" ) # set buold type diff --git a/bsd/common.h b/bsd/common.h index fb0ff7f..58f6860 100644 --- a/bsd/common.h +++ b/bsd/common.h @@ -27,11 +27,6 @@ #include #include -// Memory Sizes -#define KILOBYTES(x) ((x)/1024) -#define MEGABYTES(x) (KILOBYTES((x))/1024) -#define GIGABYTES(x) (MEGABYTES((x))/1024) - // CPU percentages stuff #define CP_USER 0 #define CP_NICE 1 diff --git a/bsd/memory_freebsd.cc b/bsd/memory_freebsd.cc index 50d3e11..d37f8b4 100644 --- a/bsd/memory_freebsd.cc +++ b/bsd/memory_freebsd.cc @@ -26,6 +26,7 @@ #include "common.h" #include "memory.h" #include "../luts.h" +#include "../config.h" std::string mem_string( bool use_colors = false ) { diff --git a/bsd/memory_openbsd.cc b/bsd/memory_openbsd.cc index 84e29b8..ba00c6b 100644 --- a/bsd/memory_openbsd.cc +++ b/bsd/memory_openbsd.cc @@ -29,6 +29,7 @@ #include "common.h" #include "memory.h" #include "../luts.h" +#include "../config.h" std::string mem_string( bool use_colors = false ) { diff --git a/version.h.in b/config.h.in similarity index 88% rename from version.h.in rename to config.h.in index c46dd04..10a77b9 100644 --- a/version.h.in +++ b/config.h.in @@ -21,3 +21,8 @@ #define tmux_mem_cpu_load_VERSION_MINOR @tmux-mem-cpu-load_VERSION_MINOR@ #define tmux_mem_cpu_load_VERSION_PATCH @tmux-mem-cpu-load_VERSION_PATCH@ #define tmux_mem_cpu_load_VERSION "@tmux-mem-cpu-load_VERSION@" + +// Memory Sizes +#define KILOBYTES(x) ((x)/1024) +#define MEGABYTES(x) (KILOBYTES((x))/1024) +#define GIGABYTES(x) (MEGABYTES((x))/1024) diff --git a/linux/memory.cc b/linux/memory.cc index 42580a5..7254c5b 100644 --- a/linux/memory.cc +++ b/linux/memory.cc @@ -21,6 +21,7 @@ #include "memory.h" #include "../luts.h" +#include "../config.h" std::string mem_string( bool use_colors = false ) { @@ -29,17 +30,17 @@ std::string mem_string( bool use_colors = false ) struct sysinfo sinfo; sysinfo(&sinfo); - unsigned int total_mem = sinfo.totalram / 1014; - unsigned int used_mem = total_mem - sinfo.freeram / 1024; + unsigned int total_mem = MEGABYTES(sinfo.totalram); + unsigned int used_mem = total_mem - MEGABYTES(sinfo.freeram); // we don't need this for now - //unsigned int unused_mem = sinfo.freeram / 1024; + //unsigned int unused_mem = MEGABYTES(sinfo.freeram); if( use_colors ) { oss << mem_lut[(100 * used_mem) / total_mem]; } - oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; + oss << used_mem << '/' << total_mem << "MB"; if( use_colors ) { diff --git a/osx/memory.cc b/osx/memory.cc index d83e5be..f9ac677 100644 --- a/osx/memory.cc +++ b/osx/memory.cc @@ -23,6 +23,7 @@ #include "memory.h" #include "../luts.h" +#include "../config.h" std::string mem_string( bool use_colors ) { @@ -58,16 +59,12 @@ std::string mem_string( bool use_colors ) ) * ( int64_t )page_size; } - // To kilobytes - used_mem /= 1024; - total_mem /= 1024; - if( use_colors ) { oss << mem_lut[( 100 * used_mem ) / total_mem]; } - oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; + oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; if( use_colors ) { diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 15d090f..7f8f312 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -23,7 +23,7 @@ #include // EXIT_SUCCESS #include "argParse/argParse.h" -#include "version.h" +#include "config.h" #include "graph.h" // Tmux color lookup tables for the different metrics. From a53bbddef8adea531976687d9db6db6da9b9fdbc Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 17:24:17 +0100 Subject: [PATCH 72/80] added cmake generated config.h file to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3f51360..bfe3068 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ cmake_install.cmake CMakeCache.txt install_manifest.txt version.h +config.h CTestTestfile.cmake DartConfiguration.tcl From ed8ed793bf6935d4b7e0914704d40937a873e868 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 17:27:08 +0100 Subject: [PATCH 73/80] renamed bsd/common.h to getsysctl.h to better reflect it's function --- bsd/cpu.cc | 2 +- bsd/{common.h => getsysctl.h} | 0 bsd/load.cc | 2 +- bsd/memory_freebsd.cc | 2 +- bsd/memory_openbsd.cc | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename bsd/{common.h => getsysctl.h} (100%) diff --git a/bsd/cpu.cc b/bsd/cpu.cc index 9235ed1..70e3560 100644 --- a/bsd/cpu.cc +++ b/bsd/cpu.cc @@ -23,7 +23,7 @@ #include #include // usleep -#include "common.h" +#include "getsysctl.h" #include "cpu.h" float cpu_percentage( unsigned int cpu_usage_delay ) diff --git a/bsd/common.h b/bsd/getsysctl.h similarity index 100% rename from bsd/common.h rename to bsd/getsysctl.h diff --git a/bsd/load.cc b/bsd/load.cc index 8b05ba4..1ae14cc 100644 --- a/bsd/load.cc +++ b/bsd/load.cc @@ -26,7 +26,7 @@ #include // floorf() #include -#include "common.h" +#include "getsysctl.h" #include "load.h" #include "../luts.h" diff --git a/bsd/memory_freebsd.cc b/bsd/memory_freebsd.cc index d37f8b4..cf86e96 100644 --- a/bsd/memory_freebsd.cc +++ b/bsd/memory_freebsd.cc @@ -23,7 +23,7 @@ #include #include -#include "common.h" +#include "getsysctl.h" #include "memory.h" #include "../luts.h" #include "../config.h" diff --git a/bsd/memory_openbsd.cc b/bsd/memory_openbsd.cc index ba00c6b..5de361e 100644 --- a/bsd/memory_openbsd.cc +++ b/bsd/memory_openbsd.cc @@ -26,7 +26,7 @@ #include #include -#include "common.h" +#include "getsysctl.h" #include "memory.h" #include "../luts.h" #include "../config.h" From 7c883b924a4cb7868394f6ff4b8e9defc061f149 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 19:20:55 +0100 Subject: [PATCH 74/80] restore parsing of /proc/meminfo to get memory usage See issue: https://github.com/l0ner/tmux-mem-cpu-load/commit/e7f2dd25e82c6ec6fc596e686c2f835f51e22eef#commitcomment-9327932 Unfortunately we can't pull info about cached memory from sysinfo. Thus we need stick to /proc/meminfo parsing. See code for more comments. --- linux/memory.cc | 66 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/linux/memory.cc b/linux/memory.cc index 7254c5b..591310b 100644 --- a/linux/memory.cc +++ b/linux/memory.cc @@ -17,6 +17,7 @@ */ #include +#include #include #include "memory.h" @@ -25,22 +26,73 @@ std::string mem_string( bool use_colors = false ) { + using std::string; + using std::ifstream; + using std::stoi; + std::ostringstream oss; - struct sysinfo sinfo; - sysinfo(&sinfo); + string line, substr; + size_t substr_start; + size_t substr_len; - unsigned int total_mem = MEGABYTES(sinfo.totalram); - unsigned int used_mem = total_mem - MEGABYTES(sinfo.freeram); - // we don't need this for now - //unsigned int unused_mem = MEGABYTES(sinfo.freeram); + unsigned int total_mem, used_mem; + + /* Since linux uses some RAM for disk caching, the actuall used ram is lower + * than what sysinfo(), top or free reports. htop reports the usage in a + * correct way. The memory used for caching doesn't count as used, since it + * can be freed in any moment. Usually it hapens automatically, when an + * application requests memory. + * In order to calculate the ram that's actually used we need to use the + * following formula: + * total_ram - free_ram - buffered_ram - cached_ram + * + * example data, junk removed, with comments added: + * + * MemTotal: 61768 kB old + * MemFree: 1436 kB old + * MemAvailable ????? kB ?? + * MemShared: 0 kB old (now always zero; not calculated) + * Buffers: 1312 kB old + * Cached: 20932 kB old + * SwapTotal: 122580 kB old + * SwapFree: 60352 kB old + */ + + ifstream memory_info("/proc/meminfo"); + + while( getline( memory_info, line ) ) + { + substr_start = 0; + substr_len = line.find_first_of( ':' ); + substr = line.substr( substr_start, substr_len ); + substr_start = line.find_first_not_of( " ", substr_len + 1 ); + substr_len = line.find_first_of( 'k' ) - substr_start; + if( substr.compare( "MemTotal" ) == 0 ) + { + // get total memory + total_mem = stoi( line.substr( substr_start, substr_len ) ); + } + else if( substr.compare( "MemFree" ) == 0 ) + { + used_mem = total_mem - stoi( line.substr( substr_start, substr_len ) ); + } + else if( substr.compare( "Buffers" ) == 0 || + substr.compare( "Cached" ) == 0 ) + { + used_mem -= stoi( line.substr( substr_start, substr_len ) ); + } + } if( use_colors ) { oss << mem_lut[(100 * used_mem) / total_mem]; } - oss << used_mem << '/' << total_mem << "MB"; + // we want megabytes on output, but since the values already come as + // kilobytes we need to divide them by 1024 only once, thus we use + // KILOBYTES + oss << KILOBYTES(used_mem) << '/' << KILOBYTES(total_mem) << "MB"; if( use_colors ) { From 2fb24571efe05e4609de8778756995b967cebe4c Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 20:02:46 +0100 Subject: [PATCH 75/80] use inline function for unit conversion instead of macros --- bsd/memory_freebsd.cc | 5 +++-- bsd/memory_openbsd.cc | 5 +++-- config.h.in | 4 ---- conversions.h | 35 +++++++++++++++++++++++++++++++++++ linux/memory.cc | 5 +++-- osx/memory.cc | 5 +++-- 6 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 conversions.h diff --git a/bsd/memory_freebsd.cc b/bsd/memory_freebsd.cc index cf86e96..23fe67f 100644 --- a/bsd/memory_freebsd.cc +++ b/bsd/memory_freebsd.cc @@ -26,7 +26,7 @@ #include "getsysctl.h" #include "memory.h" #include "../luts.h" -#include "../config.h" +#include "../conversions.h" std::string mem_string( bool use_colors = false ) { @@ -63,7 +63,8 @@ std::string mem_string( bool use_colors = false ) oss << mem_lut[( 100 * used_mem ) / total_mem]; } - oss << MEGABYTES( used_mem ) << '/' << MEGABYTES( total_mem ) << "MB"; + oss << convert_unit( used_mem, MEGABYTES ) << '/' + << convert_unit( total_mem, MEGABYTES ) << "MB"; if( use_colors ) { diff --git a/bsd/memory_openbsd.cc b/bsd/memory_openbsd.cc index 5de361e..69bdd03 100644 --- a/bsd/memory_openbsd.cc +++ b/bsd/memory_openbsd.cc @@ -29,7 +29,7 @@ #include "getsysctl.h" #include "memory.h" #include "../luts.h" -#include "../config.h" +#include "../conversions.h" std::string mem_string( bool use_colors = false ) { @@ -65,7 +65,8 @@ std::string mem_string( bool use_colors = false ) oss << mem_lut[( 100 * used_mem ) / total_mem]; } - oss << MEGABYTES( used_mem ) << '/' << MEGABYTES( total_mem ) << "MB"; + oss << convert_unit( used_mem, MEGABYTES ) << '/' + << convert_unit( total_mem, MEGABYTES ) << "MB"; if( use_colors ) { diff --git a/config.h.in b/config.h.in index 10a77b9..5268d15 100644 --- a/config.h.in +++ b/config.h.in @@ -22,7 +22,3 @@ #define tmux_mem_cpu_load_VERSION_PATCH @tmux-mem-cpu-load_VERSION_PATCH@ #define tmux_mem_cpu_load_VERSION "@tmux-mem-cpu-load_VERSION@" -// Memory Sizes -#define KILOBYTES(x) ((x)/1024) -#define MEGABYTES(x) (KILOBYTES((x))/1024) -#define GIGABYTES(x) (MEGABYTES((x))/1024) diff --git a/conversions.h b/conversions.h new file mode 100644 index 0000000..701f177 --- /dev/null +++ b/conversions.h @@ -0,0 +1,35 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +enum +{ + BYTES = 0, + KILOBYTES = 1, + MEGABYTES = 2, + GIGABYTES = 3 +}; + +template +inline T convert_unit( T num, int to, int from = BYTES) +{ + for(from; from < to; from++) + { + num /= 1024; + } + return num; +} diff --git a/linux/memory.cc b/linux/memory.cc index 591310b..9f96b0d 100644 --- a/linux/memory.cc +++ b/linux/memory.cc @@ -22,7 +22,7 @@ #include "memory.h" #include "../luts.h" -#include "../config.h" +#include "../conversions.h" std::string mem_string( bool use_colors = false ) { @@ -92,7 +92,8 @@ std::string mem_string( bool use_colors = false ) // we want megabytes on output, but since the values already come as // kilobytes we need to divide them by 1024 only once, thus we use // KILOBYTES - oss << KILOBYTES(used_mem) << '/' << KILOBYTES(total_mem) << "MB"; + oss << convert_unit(used_mem, MEGABYTES, KILOBYTES) << '/' + << convert_unit(total_mem, MEGABYTES, KILOBYTES) << "MB"; if( use_colors ) { diff --git a/osx/memory.cc b/osx/memory.cc index f9ac677..bacad9d 100644 --- a/osx/memory.cc +++ b/osx/memory.cc @@ -23,7 +23,7 @@ #include "memory.h" #include "../luts.h" -#include "../config.h" +#include "../conversions.h" std::string mem_string( bool use_colors ) { @@ -64,7 +64,8 @@ std::string mem_string( bool use_colors ) oss << mem_lut[( 100 * used_mem ) / total_mem]; } - oss << MEGABYTES(used_mem) << '/' << MEGABYTES(total_mem) << "MB"; + oss << convert_unit( used_mem, MEGABYTES ) << '/' + << convert_unit( total_mem, MEGABYTES ) << "MB"; if( use_colors ) { From eb338d92c5588bf94e5eb802d3d8d54e2511fd3c Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Sun, 18 Jan 2015 20:04:28 +0100 Subject: [PATCH 76/80] rename config.h back to version.h since it contains only version after last commit --- CMakeLists.txt | 4 ++-- tmux-mem-cpu-load.cpp | 2 +- config.h.in => version.h.in | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename config.h.in => version.h.in (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e42569..dc77596 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,10 +46,10 @@ endif() # generate header file to handle version configure_file( - "${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_SOURCE_DIR}/config.h" + "${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h" ) -# set buold type +# set build type if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 7f8f312..15d090f 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -23,7 +23,7 @@ #include // EXIT_SUCCESS #include "argParse/argParse.h" -#include "config.h" +#include "version.h" #include "graph.h" // Tmux color lookup tables for the different metrics. diff --git a/config.h.in b/version.h.in similarity index 100% rename from config.h.in rename to version.h.in From 08bc9b7ecfe17324584b201671b3108435c290a7 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Mon, 19 Jan 2015 17:17:38 +0100 Subject: [PATCH 77/80] replaced argParser with getopt_long based one Solves issue: https://github.com/l0ner/tmux-mem-cpu-load/commit/28040b61dad99cb9cb4cfc604a5d38123b4ac66e#commitcomment-9327906 No GPL2-based code anymore in the codebase. --- argParse/argParse.cc | 817 ------------------------------------------ argParse/argParse.h | 337 ----------------- tmux-mem-cpu-load.cpp | 116 +++--- 3 files changed, 66 insertions(+), 1204 deletions(-) delete mode 100644 argParse/argParse.cc delete mode 100644 argParse/argParse.h diff --git a/argParse/argParse.cc b/argParse/argParse.cc deleted file mode 100644 index 7dbece6..0000000 --- a/argParse/argParse.cc +++ /dev/null @@ -1,817 +0,0 @@ -/* - * C++ command line argument parser - * - * Copyright (C) 2005 by - * Michael Hanke michael.hanke@gmail.com - * - * Minor adjustements: 2015 Pawel 'l0ner' Soltys - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include -#include -#include "argParse.h" - -using namespace std; -using namespace ArgvParse; - -ArgvParser::ArgvParser() - : max_key(1), - help_option(0) // must be smaller than max_key initially - -{ - // nothing -} - -ArgvParser::~ArgvParser() -{ - // nothing -} - -void ArgvParser::reset() -{ - max_key = 1; - option2key.clear(); - option2attribute.clear(); - option2descr.clear(); - option2value.clear(); - errorcode2descr.clear(); - argument_container.clear(); - intro_description.clear(); - error_option.clear(); - help_option = 0; -} - -int ArgvParser::optionKey( const string& _name ) const -{ - String2KeyMap::const_iterator it = option2key.find(_name); - - // if not found - if (it == option2key.end()) - return(-1); - - return(it->second); -} - -bool ArgvParser::isDefinedOption( const string& _name ) const -{ - return(option2key.find(_name) != option2key.end()); -} - -bool ArgvParser::foundOption( const string & _name ) const -{ - int key = optionKey(_name); - - // not defined -> cannot by found - if (key == -1) - return(false); - - // return whether the key of the given option name is in the hash of the - // parsed options. - return(option2value.find(key) != option2value.end()); -} - -string ArgvParser::optionValue(const string& _option) const -{ - int key = optionKey(_option); - - // not defined -> cannot by found - if (key == -1) - { - cerr << "ArgvParser::optionValue(): Requested value of an option the" - "parser did not find or does not know." << endl; - return(""); - } - - return(option2value.find(key)->second); -} - -ArgvParser::ParserResults -ArgvParser::parse(int _argc, char ** _argv) -{ - bool finished_options = false; // flag whether an argument was found - // (options are passed) - - // loop over all command line arguments - int i = 1; // argument counter - while( i< _argc ) - { - string argument = _argv[i]; - unsigned int key = 0; - string option; // option name - string value; // option value - - // if argument is an option - if (!isValidOptionString(argument)) - { - // string is a real argument since values are processed elsewhere - finished_options=true; - argument_container.push_back(argument); - } - else // can be a long or multiple short options at this point - { - // check whether we already found an argument - if (finished_options) - { - error_option = argument; - return(OptionAfterArgument); // return error code - } - // check for long options - if (isValidLongOptionString(argument)) - { - // handle long options - - // remove trailing '--' - argument = argument.substr(2); - // check for option value assignment 'option=value' - splitOptionAndValue(argument, option, value); - - if (!isDefinedOption(option)) // is this a known option - { - error_option = option; // store the option that caused the error - return(UnknownOption); // return error code if not - } - - // get the key of this option - now that we know that it is defined - key = option2key.find(option)->second; - if (key == help_option) // if help is requested return error code - return(HelpRequested); - - // do we need to extract a value - // AND a value is not already assigned from the previous step - if ((option2attribute.find(key)->second & RequiresValue) && value.empty()) - { - if (i+1 >= _argc) // are there arguments left? - { - error_option = option; // store the option that caused the error - return(MissingValue); // the was no argument left although we need a value - } - - string temp = _argv[i+1]; // get the next element - ++i; // increase counter now that we moved forward - - if (isValidOptionString(temp)) - { - error_option = option; // store the option that caused the error - return(MissingValue); // missing option value - } - value = temp; // assign value - } - // add option-value map entry - option2value[key] = value; - } - else // handle short options - { - argument = argument.substr(1); // remove trailing '-' - - // check for option value assignment 'option=value' - if (splitOptionAndValue(argument, option, value)) - { - // there was an option <- value assignment - if (option.length() > 1) - { - error_option = option; // store the option that caused the error - return(MalformedMultipleShortOption); // return error code if option has more than one character - } - - if (!isDefinedOption(option)) // is this a known option - { - error_option = option; // store the option that caused the error - return(UnknownOption); // return error code if not - } - key = option2key.find(option)->second; // get the key for the extracted option name - - if (key == help_option) // if help is requested return error code - return(HelpRequested); - - // if value is still empty for some reason: we have an error - if ((option2attribute.find(key)->second & RequiresValue) && value.empty()) - { - error_option = option; // store the option that caused the error - return(MissingValue); // missing option value - } - else - // add option-value map entry - option2value[key] = value; - } - else // no '=' assignment: can be either multiple short options or - // something like '-s 4' - { - // handle short options with value like '-s 4' - option.clear(); - value.clear(); - - if (argument.length() == 1) // if a single short option - { - if (!isDefinedOption(argument)) // is this a known option - { - error_option = argument; // store the option that caused the error - return(UnknownOption); // return error code if not - } - key = option2key.find(argument)->second; // get the key for the extracted option name - - if (key == help_option) // if help is requested return error code - return(HelpRequested); - - // check if option needs a value and next arg is not an option - if ((option2attribute.find(key)->second & RequiresValue)) - { - if (i+1 >= _argc) // are there arguments left? - { - error_option = argument; // store the option that caused the error - return(MissingValue); // the was no argument left although we need a value - } - string temp = _argv[i+1]; // get the next element - ++i; // increase counter now that we moved forward - - if (isValidOptionString(temp)) - { - error_option = argument; // store the option that caused the error - return(MissingValue); // missing option value - } - // add option-value map entry - option2value[key] = temp; - - } - else // no value needed - { - option2value[key] = ""; // assign value - } - } - else // handle multiple short option like '-svxgh' - { - unsigned int short_option_counter = 0; // position in the multiple short option string - while( short_option_counter < argument.length() ) // parse the whole string - { - option = argument[short_option_counter]; // get the option character - - if (!isDefinedOption(option)) // is this a known option - { - error_option = option; // store the option that caused the error - return(UnknownOption); // return error code if not - } - key = option2key.find(option)->second; // get the key for the extracted option name - - if (key == help_option) // if help is requested return error code - return(HelpRequested); - - option2value[key] = value; - - ++short_option_counter; // advance one character forward - } - } - } - } - } - ++i; - } - - map::iterator it; - for( it = option2attribute.begin(); it != option2attribute.end(); it++ ) - { - // if the current option is required look if we got it - if (it->second & Required) - { - // is the object missing - if (option2value.find(it->first) == option2value.end()) - { - // get the list of alternative names for this option - list alternatives = getAllOptionAlternatives(it->first); - - unsigned int count = 0; - for( list::const_iterator alt = alternatives.begin(); - alt != alternatives.end(); - ++alt ) - { - ++count; - // additional '-' for long options - if (alt->length() > 1) - error_option += "-"; - - error_option += "-" + *alt; - - // alternatives to come? - if (count < alternatives.size()) - error_option += ", "; // add separator - } - return(RequiredOptionMissing); - } - } - } - - return(Success); // everthing went fine -> sucess -} - -unsigned int ArgvParser::arguments() const -{ - return(argument_container.size()); -} - -string ArgvParser::argument(unsigned int _id) const -{ - if (_id >= arguments()) - { - cerr << "ArgvParser::argument(): Request for non-existing argument.\n"; - return (""); - } - else - return(argument_container[_id]); -} - -const vector& ArgvParser::allArguments() const -{ - return(argument_container); -} - -string ArgvParser::usageDescription(unsigned int _width) const -{ - string usage; // the usage description text - - if (intro_description.length()) - usage += formatString(intro_description, _width) + "\n\n"; - - if (max_key>1) // if we have some options - usage += formatString("Available options:",_width) + "\n"; - - // loop over all option attribute entries (which equals looping over all - // different options (not option names) - for (Key2AttributeMap::const_iterator it = option2attribute.begin(); - it != option2attribute.end(); - ++it) - { - string os; // temp string for the option - - // get the list of alternative names for this option - list alternatives = getAllOptionAlternatives(it->first); - - unsigned int count = 0; - for( list::const_iterator alt = alternatives.begin(); - alt != alternatives.end(); - ++alt ) - { - ++count; - // additional '-' for long options - if (alt->length() > 1) - os += "-"; - - os += "-" + *alt; - - // note if the option requires a value - if (option2attribute.find(it->first)->second & RequiresValue) - os += " "; - - // alternatives to come? - if (count < alternatives.size()) - os += ", "; // add separator - } - - // note if the option is required - if (option2attribute.find(it->first)->second & Required) - os += " [required]"; - - usage += formatString(os, _width) + "\n"; - - if (option2descr.find(it->first) != option2descr.end()) - usage += formatString(option2descr.find(it->first)->second, _width, 4); - else - usage += formatString("(no description)", _width, 4); - - // finally a little gap - usage += "\n"; - } - usage += "\n"; - - if (!errorcode2descr.size()) // if have no errorcodes - return(usage); - - usage += formatString("Return codes", _width) + "\n"; - - // map::const_iterator eit; - for( std::map::const_iterator alt = errorcode2descr.begin(); - alt != errorcode2descr.end(); - ++alt ) - { - ostringstream code; - code << alt->first; - string label = formatString(code.str(), _width, 4); - string descr = formatString(alt->second, _width, 10); - usage += label + descr.substr(label.length()) + "\n"; - } - - return(usage); -} - -const string& ArgvParser::errorOption( ) const -{ - return(error_option); -} - -std::string ArgvParser::parseErrorDescription( ParserResults _error_code ) const -{ - string descr; - - switch (_error_code) - { - case ArgvParser::Success: - // no error -> nothing to do - break; - case ArgvParser::UnknownOption: - descr = "Unknown option: '" + errorOption() + "'\n"; - break; - case ArgvParser::MissingValue: - descr = "Missing required value for option: '" + errorOption()+ "'\n"; - break; - case ArgvParser::OptionAfterArgument: - descr = "Misplaced option '" + errorOption() + - "' detected. All option have to be BEFORE the first argument\n"; - break; - case ArgvParser::MalformedMultipleShortOption: - descr = "Malformed short-options: '" + errorOption() + "'\n"; - break; - case ArgvParser::ArgvParser::RequiredOptionMissing: - descr = "Required option missing: '" + errorOption() + "'\n"; - break; - case ArgvParser::HelpRequested: // help - descr = usageDescription(); - break; - default: - cerr << "ArgvParser::documentParserErrors(): Unknown error code\n"; - } - - return(descr); -} - -bool ArgvParser::defineOption( const string & _name, - const string& _descr, - OptionAttributes _attrs) -{ - // do nothing if there already is an option of this name - if (isDefinedOption(_name)) - { - cerr << "ArgvParser::defineOption(): The option label equals an already defined option." << endl; - return(false); - } - - // no digits as short options allowed - if (_name.length() == 1 && isDigit(_name[0])) - { - cerr << "ArgvParser::defineOption(): Digits as short option labels are not allowd." << endl; - return(false); - } - - option2key[_name] = max_key; // give the option a unique key - - // store the option attributes - option2attribute[max_key] = _attrs; - - // store the option description if there is one - if (_descr.length()) - option2descr[max_key] = _descr; - - // inc the key counter - ++max_key; - - return(true); -} - -bool ArgvParser::defineOptionAlternative( const string & _original, - const string & _alternative ) -{ - // do nothing if there already is no option of this name - if (!isDefinedOption(_original)) - { - cerr << "ArgvParser::defineOptionAlternative(): Original option label is not a defined option." << endl; - return(false); - } - - // AND no digits as short options allowed - if (_alternative.length() == 1 && isDigit(_alternative[0])) - { - cerr << "ArgvParser::defineOptionAlternative(): Digits as short option labels are not allowd." << endl; - return(false); - } - - // AND do nothing if there already is an option with the alternativ name - if (isDefinedOption(_alternative)) - { - cerr << "ArgvParser::defineOptionAlternative(): The alternative option label equals an already defined option." << endl; - return(false); - } - - option2key[_alternative] = optionKey(_original); - - return(true); -} - -bool ArgvParser::defineOption( const string & _shortname, - const string & _name, - const string& _descr, - OptionAttributes _attrs) -{ - - defineOption( _name, _descr, _attrs); - defineOptionAlternative( _name, _shortname ); - - return(true); - -} - - -bool ArgvParser::setHelpOption(const string& _shortname, - const string& _longname, - const string& _descr) -{ - // do nothing if any name is already in use - if (isDefinedOption(_shortname) || isDefinedOption(_longname)) - { - cerr << "ArgvParser::setHelpOption(): Short or long help option label equals an already defined option." << endl; - return(false); - } - - // define the help option's short name and the alternative - // longname - defineOption(_shortname, _descr, NoAttribute); - defineOptionAlternative(_shortname, _longname); - - help_option = max_key-1; // store the key in a special member - - return(true); -} - -void ArgvParser::addErrorCode(int _code, const string& _descr) -{ - errorcode2descr[_code] = _descr; -} - -void ArgvParser::setIntroduction(const string& _descr) -{ - intro_description = _descr; -} - -list ArgvParser::getAllOptionAlternatives( unsigned int _key ) const -{ - // keys go here - list keys; - // for all container elements - for( map::const_iterator it = option2key.begin(); - it != option2key.end(); - ++it ) - { - if (it->second == _key) - keys.push_back(it->first); - } - return(keys); -} - -bool ArgvParse::isDigit(const char& _char) -{ - if (_char == '0' || _char == '1' || _char == '2' || _char == '3' - || _char == '4' || _char == '5' || _char == '6' || _char == '7' - || _char == '8' || _char == '9') - return(true); - else - return(false); -} - -bool ArgvParse::isValidOptionString(const string& _string) -{ - // minimal short option length is 2 - if (_string.length() < 2) - return(false); - - // is it an option (check for '-' as first character) - if (_string.compare(0, 1, "-")) - return(false); - - // not an option if just '--' - if (_string.length() == 2 && _string == "--") - return(false); - - // it might still be a negative number - // (but not if there is no digit afterwards) - if (isDigit(_string[1])) - return(false); - - // let's consider this an option - return(true); -} - -bool ArgvParse::isValidLongOptionString(const string& _string) -{ - if (_string.length() < 4) // must be at least '--??' - return(false); - - // is it an option (check for '--') - if (_string.compare(0, 2, "--")) - return(false); - else - return(true); -} - -bool ArgvParse::splitOptionAndValue(const string& _string, - string& _option, string& _value) -{ - // string token container - std::vector tokens; - - // split string by '=' delimiter - splitString(tokens, _string, "="); - - // check for option value assignment 'option=value' - if (tokens.size() < 2) - { - _option = _string; // the option is the whole string - return(false); - } - - // separate option and value - _option = tokens[0]; - - // concat all remaining tokens to the value string - for (unsigned int i=1; i & _expanded ) -{ - list tokens; - // split string by delimiter - splitString(tokens, _string, ","); - - // loop over all entries - for(list::const_iterator it = tokens.begin(); it != tokens.end(); it++) - { - const string& entry = *it; // convenience reference - -#ifdef ARGVPARSER_DEBUG - - cout << "TOKEN: " << entry << endl; -#endif - - // if range was given - if (entry.find("-") != string::npos) - { - // split into upper and lower border - list range_borders; - splitString(range_borders, entry, "-"); - - // fail if insane range spec - if (range_borders.size() != 2) - return(false); - - int first = atoi(range_borders.begin()->c_str()); - int second = atoi((++range_borders.begin())->c_str()); - - // write id in increasing order - if (first <= second) - - { - for (int j=first; j<=second; ++j) - { - _expanded.push_back(j); - } - } - else // write id in decreasing order - { - for (int k=first; k>=second; k--) - { - _expanded.push_back(k); - } - } - } - else // single number was given - _expanded.push_back(atoi(entry.c_str())); // store id - } - - return(true); -} - -std::string ArgvParse::formatString(const std::string& _string, - unsigned int _width, - unsigned int _indent) -{ - // if insane parameters do nothing - if (_indent >= _width) - return(_string); - - // list of lines of the formated string - list lines; - - // current position in the string - unsigned int pos = 0; - - // till the end of the string - while (pos < _string.length()) - { - // get the next line of the string - string line = _string.substr(pos, _width - _indent ); - -#ifdef ARGVPARSER_DEBUG - - cout << "EXTRACT: '" << line << "'" << endl; -#endif - - // check for newlines in the line and break line at first occurence (if any) - string::size_type first_newline = line.find_first_of("\n"); - if (first_newline != string::npos) - { - line = line.substr(0, first_newline); - } - - // we need to check for possible breaks within words only if the extracted - // line spans the whole allowed width - bool check_truncation = true; - if (line.length() < _width - _indent) - check_truncation = false; - - // remove unecessary whitespace at front and back - line = trimmedString(line); - -#ifdef ARGVPARSER_DEBUG - - cout << "TRIMMED: '" << line << "'" << endl; -#endif - - // only perform truncation if there was enough data for a full line - if (!check_truncation) - pos += line.length() + 1; - else - { - // look for the last whitespace character - string::size_type last_white_space = line.find_last_of(" \a\b\f\n\r\t\v"); - - if (last_white_space != string::npos) // whitespace found! - { - // truncated the line at the last whitespace - line = string(line, 0, last_white_space); - pos += last_white_space + 1; - } - else // no whitespace found - // rude break! we can leave the line in its current state - pos += _width - _indent; - } - - if (!line.empty()) - { -#ifdef ARGVPARSER_DEBUG - cout << "UNINDEN: '" << line << "'" << endl; -#endif - - if (_indent) - line.insert(0, _indent, ' '); - -#ifdef ARGVPARSER_DEBUG - - cout << "INDENT: '" << line << "'" << endl; -#endif - - lines.push_back(line); - } - } - - // concat the formated string - string formated; - bool first = true; - // for all lines - for (list::iterator it = lines.begin(); it != lines.end(); ++it) - { - // prefix with newline if not first - if (!first) - formated += "\n"; - else - first = false; - - formated += *it; - } - return(formated); -} - diff --git a/argParse/argParse.h b/argParse/argParse.h deleted file mode 100644 index 6b8ae27..0000000 --- a/argParse/argParse.h +++ /dev/null @@ -1,337 +0,0 @@ -/* - * C++ command line argument parser - * - * Copyright (C) 2005 by - * Michael Hanke michael.hanke@gmail.com - * - * Minor adjustements: 2015 Pawel 'l0ner' Soltys - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef __ARGVPARSER_H -#define __ARGVPARSER_H - -#include -#include -#include -#include - -namespace ArgvParse -{ - -/** Provides parsing and storage of POSIX-like command line arguments (argc, argv). -* To use this class for CLI-option parsing, first define a set of valid options using -* the defineOption() method. An option can have several attributes: it can be required -* itself (its missing is considered as an error) and/or it can require a value. -* Options with optional values can be realized by defining the option to not need a -* value and use the syntax '--option=value' or '-o=value' on the command line. -* Every option can have different alternative labels; see defineOptionAlternative(). -* A usage description (see usageDescription()) can be generated from the set of defined options (also see the -* addErrorCode(), setIntroductoryDescription() and setHelpOption() methods). -* \note The implemented parsing algorithm requires that all options have to be given at -* the beginning of the command line. Everything on the commandline after the first -* non-option (or option value) is considered as an argument. -* \attention Short option labels (single letter options) must not be digits -* (the option string itself not a possible value). -* Valid syntaxes are: -* \li program --long-option value -sdfgh -u=5 -i 7 --last=val arg1 arg2 arg3 -* Here is a small code example: -* \code -* #include -* ArgvParser cmd; // the command line parser -* -* // init -* cmd.setIntroductoryDescription("This is foo written by bar."); -* -* //define error codes -* cmd.addErrorCode(0, "Success"); -* cmd.addErrorCode(1, "Error"); -* -* cmd.setHelpOption("h", "help", "Print this help"); -* -* cmd.defineOption("version", ArgvParser::NoOptionAttribute, "Be verbose"); -* cmd.defineOptionAlternative("verbose","v"); -* -* cmd.defineOption("foo", ArgvParser::OptionRequiresValue, "Fooishness. Default value: 0"); -* -* // finally parse and handle return codes (display help etc...) -* int result = cmd.parse(argc, argv); -* -* if (result != ArgvParser::NoParserError) -* cout << cmd.parseErrorDescription(results); -* exit(1); -* \endcode -* -* \author Michael Hanke -*/ -class ArgvParser -{ -public: - typedef int OptionAttributes; - typedef int ParserResults; - typedef std::map String2KeyMap; - typedef std::map Key2AttributeMap; - typedef std::map Key2StringMap; - typedef std::vector ArgumentContainer; - - ArgvParser(); - ~ArgvParser(); - - /** Attributes for options. */ - enum - { - NoAttribute = 0x00, - RequiresValue = 0x01, - Required = 0x02 - }; - /** Return values of the parser. */ - enum - { - Success = 0x00, - UnknownOption = 0x01, - MissingValue = 0x02, - OptionAfterArgument = 0x04, - MalformedMultipleShortOption = 0x08, - RequiredOptionMissing = 0x16, - HelpRequested = 0x32 - }; - - bool defineOption(const std::string& _name, - const std::string& _description = std::string(), - OptionAttributes _attributes = NoAttribute); - - bool defineOption(const std::string& _shortname, - const std::string& _name, - const std::string& _description = std::string(), - OptionAttributes _attributes = NoAttribute); - /** Defines an option with optional attributes (required, ...) and an - * additional (also optional) description. The description becomes part of the - * generated usage help that can be requested by calling the usageDescription() - * method. - * \return Returns FALSE if there already is an option with this name - * OR if a short option string (length == 1) is a digit. In that case no - * action is peformed. - */ - bool defineOptionAlternative(const std::string& _original, - const std::string& _alternative); - /** Define an alternative name for an option that was previously defined by - * defineOption(). - * \return Returns FALSE if there already is an option with the alternative - * name or no option with the original name OR if a short option string - * (length == 1) is a digit. In that case no action is performed. - */ - bool isDefinedOption(const std::string& _name) const; - /** Returns whether _name is a defined option. */ - bool foundOption(const std::string& _name) const; - /** Returns whether _name is an option that was found while parsing - * the command line arguments with the parse() method. In other word: This - * method returns true if the string is an option AND it was given on the - * parsed command line. - */ - bool setHelpOption(const std::string& _longname = "h", - const std::string& _shortname = "help", - const std::string& _descr = ""); - /** Define a help option. If this option is found a special error code is - * returned by the parse method. - * \attention If this method is called twice without an intermediate call - * to the reset() method the previously set help option will remain a valid - * option but is not detected as the special help option and will therefore - * not cause the parse() method to return the special help error code. - * \return Returns FALSE if there already is an option defined that equals - * the short or long name. - */ - unsigned int arguments() const; - /** Returns the number of read arguments. Arguments are efined as beeing - * neither options nor option values and are specified at the end of the - * command line after all options and their values. */ - std::string argument(unsigned int _number) const; - /** Returns the Nth argument. See arguments(). - * \return Argument string or an empty string if there was no argument of - * that id. - */ - const std::vector& allArguments() const; - /** Get the complete argument vector. The order of the arguments in the - * vector is the same as on the commandline. - */ - void addErrorCode(int _code, const std::string& _descr = ""); - /** Add an error code and its description to the command line parser. - * This will do nothing more than adding an entry to the usage description. - */ - void setIntroduction(const std::string& _descr); - /** Set some string as a general description, that will be printed before - * the list of available options. - */ - ParserResults parse(int _argc, char ** _argv); - /** Parse the command line arguments for all known options and arguments. - * \return Error code with parsing result. - * \retval NoParserError Everything went fine. - * \retval ParserUnknownOption Unknown option was found. - * \retval ParserMissingValue A value to a given option is missing. - * \retval ParserOptionAfterArgument Option after an argument detected. All - * options have to given before the first argument. - * \retval ParserMalformedMultipleShortOption Malformed short option string. - * \retval ParserRequiredOptionMissing Required option is missing. - * \retval ParserHelpRequested Help option detected. - */ - std::string optionValue(const std::string& _option) const; - /** Return the value of an option. - * \return Value of a commandline options given by the name of the option or - * an empty string if there was no such option or the option required no - * value. - */ - void reset(); - /** Reset the parser. Call this function if you want to parse another set of - * command line arguments with the same parser object. - */ - const std::string& errorOption() const; - /** Returns the name of the option that was responsible for a parser error. - * An empty string is returned if no error occured at all. - */ - std::string parseErrorDescription(ParserResults _error_code) const; - /** This method can be used to evaluate parser error codes and generate a - * human-readable description. In case of a help request error code the - * usage description as returned by usageDescription() is printed. - */ - std::string usageDescription(unsigned int _width = 80) const; - /** Returns a string with the usage descriptions for all options. The - * description string is formated to fit into a terminal of width _width.*/ - -private: - int optionKey( const std::string& _name ) const; - /** Returns the key of a defined option with name _name or -1 if such option - * is not defined. */ - std::list getAllOptionAlternatives(unsigned int _key) const; - /** Returns a list of option names that are all alternative names associated - * with a single key value. - */ - - /** The current maximum key value for an option. */ - unsigned int max_key; - - /** Map option names to a numeric key. */ - String2KeyMap option2key; - - /** Map option key to option attributes. */ - Key2AttributeMap option2attribute; - - /** Map option key to option description. */ - Key2StringMap option2descr; - - /** Map option key to option value. */ - Key2StringMap option2value; - - /** Map error code to its description. */ - std::map errorcode2descr; - - /** Vector of command line arguments. */ - ArgumentContainer argument_container; - - /** General description to be returned as first part of the generated help page. */ - std::string intro_description; - - /** Holds the key for the help option. */ - unsigned int help_option; - - /** Holds the name of the option that was responsible for a parser error. - */ - std::string error_option; -}; // class ArgvParser - - -// Auxillary functions - -bool isValidOptionString(const std::string& _string); -/** Returns whether the given string is a valid (correct syntax) option string. - * It has to fullfill the following criteria: - * 1. minimum length is 2 characters - * 2. Start with '-' - * 3. if if minimal length -> must not be '--' - * 4. first short option character must not be a digit (to distinguish negative numbers) - */ - -bool isValidLongOptionString(const std::string& _string); -/** Returns whether the given string is a valid (correct syntax) long option string. - * It has to fullfill the following criteria: - * 1. minimum length is 4 characters - * 2. Start with '--' - */ - -bool splitOptionAndValue(const std::string& _string, std::string& _option, - std::string& _value); -/** Splits option and value string if they are given in the form 'option=value'. -* \return Returns TRUE if a value was found. -*/ - -template -void splitString(Container& _container, const std::string& _in, - const char* const _delimiters = " \t\n") -{ -/** String tokenizer using standard C++ functions. Taken from here: - * http://gcc.gnu.org/onlinedocs/libstdc++/21_strings/howto.html#3 - * Splits the string _in by _delimiters and store the tokens in _container. - */ - const std::string::size_type len = _in.length(); - std::string::size_type i = 0; - - while ( i < len ) - { - // eat leading whitespace - i = _in.find_first_not_of (_delimiters, i); - if (i == std::string::npos) - return; // nothing left but white space - - // find the end of the token - std::string::size_type j = _in.find_first_of (_delimiters, i); - - // push token - if (j == std::string::npos) - { - _container.push_back (_in.substr(i)); - return; - } - else - _container.push_back (_in.substr(i, j-i)); - - // set up for next loop - i = j + 1; - } -} - -bool isDigit(const char& _char); -/** Returns true if the character is a digit (what else?). */ - -bool expandRangeStringToUInt(const std::string& _string, - std::vector& _expanded); -/** Build a vector of integers from a string of the form: -* '1,3-5,14,25-20'. This string will be expanded to a list of positive -* integers with the following elements: 1,3,4,5,14,25,24,23,22,21,20. -* All of the expanded elements will be added to the provided list. -* \return Returns FALSE if there was any syntax error in the given string -* In that case the function stops at the point where the error occured. -* Only elements processed up to that point will be added to the expanded -* list. -* \attention This function can only handle unsigned integers! -*/ - -std::string trimmedString(const std::string& _str); -/** Returns a copy of _str with whitespace removed from front and back. */ - -std::string formatString(const std::string& _string, - unsigned int _width, - unsigned int _indent = 0); -/** Formats a string of an arbitrary length to fit a terminal of width -* _width and to be indented by _indent columns. -*/ - -} -; // namespace CommandLineProcessing - -#endif // __CMDLINEPARSER_H diff --git a/tmux-mem-cpu-load.cpp b/tmux-mem-cpu-load.cpp index 15d090f..11180c2 100644 --- a/tmux-mem-cpu-load.cpp +++ b/tmux-mem-cpu-load.cpp @@ -20,9 +20,9 @@ #include #include #include -#include // EXIT_SUCCESS +#include // EXIT_SUCCESS, atoi() +#include // getopt_long -#include "argParse/argParse.h" #include "version.h" #include "graph.h" @@ -83,64 +83,80 @@ std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines, return oss.str(); } +void print_help() +{ + using std::cout; + using std::endl; + + cout << "tmux-mem-cpu-load v" << tmux_mem_cpu_load_VERSION << endl + << "Usage: tmux-mem-cpu-load [OPTIONS]\n\n" + << "Available options:\n" + << "-h, --help\n" + << "\t Prints this help message\n" + << "--colors\n" + << "\tUse tmux colors in output\n" + << "-i , --interval \n" + << "\tSet tmux status refresh interval in seconds. Default: 1 second\n" + << "-g , --graph-lines \n" + << "\tSet how many lines should be drawn in a graph. Default: 10\n" + << endl; +} + int main( int argc, char** argv ) { - using namespace ArgvParse; - unsigned cpu_usage_delay = 990000; short graph_lines = 10; // max 32767 should be enough bool use_colors = false; - // Argv parser - ArgvParser arg; - - // ugly, I know - std::string intro = "tmux-mem-cpu-load v"; - intro += tmux_mem_cpu_load_VERSION; - intro += "\nUsage: tmux-mem-cpu-load [OPTIONS]"; - - arg.setIntroduction( intro ); - - arg.setHelpOption( "h", "help", "Prints this help message" ); - - // define actual options - arg.defineOption( "colors", "Use tmux colors in output", - ArgvParser::NoAttribute ); - arg.defineOption( "i", "interval", "set tmux status refresh interval in " - "seconds. Default: 1 second", ArgvParser::RequiresValue ); - arg.defineOption( "g", "graph-lines", "Set how many lines should be drawn in " - "a graph. Default: 10", ArgvParser::RequiresValue ); - - int result = arg.parse( argc, argv ); - - if( result != ArgvParser::Success ) + static struct option long_options[] = { - std::cerr << arg.parseErrorDescription( result ); - return EXIT_FAILURE; - } + // Struct is a s follows: + // const char * name, int has_arg, int *flag, int val + // if *flag is null, val is option identifier to use in switch() + // otherwise it's a value to set the variable *flag points to + { "help", no_argument, NULL, 'h' }, + { "colors", no_argument, NULL, 'c' }, + { "interval", required_argument, NULL, 'i' }, + { "graph-lines", required_argument, NULL, 'g' }, + { 0, 0, 0, 0 } // used to handle unknown long options + }; - // mangle arguments - if( arg.foundOption( "colors" ) ) - use_colors = true; - - if( arg.foundOption( "interval" ) ) + int c; + // while c != -1 + while( (c = getopt_long( argc, argv, "hi:g:", long_options, NULL) ) != -1 ) { - int delay = std::stoi( arg.optionValue( "interval" ) ); - if( delay < 1 ) + switch( c ) { - std::cerr << "Status interval argument must be one or greater.\n"; - return EXIT_FAILURE; - } - cpu_usage_delay = delay * 1000000 - 10000; - } - - if( arg.foundOption( "graph-lines" ) ) - { - graph_lines = std::stoi( arg.optionValue( "graph-lines" ) ); - if( graph_lines < 0 ) - { - std::cerr << "Graph lines argument must be zero or greater.\n"; - return EXIT_FAILURE; + case 'h': // --help, -h + print_help(); + return EXIT_FAILURE; + break; + case 'c': // --colors + use_colors = true; + break; + case 'i': // --interval, -i + if( atoi( optarg ) < 1 ) + { + std::cerr << "Status interval argument must be one or greater.\n"; + return EXIT_FAILURE; + } + cpu_usage_delay = atoi( optarg ) * 1000000 - 10000; + break; + case 'g': // --graph-lines, -g + if( atoi( optarg ) < 0 ) + { + std::cerr << "Graph lines argument must be zero or greater.\n"; + return EXIT_FAILURE; + } + graph_lines = atoi( optarg ); + break; + case '?': + // getopt_long prints error message automatically + return EXIT_FAILURE; + break; + default: + std::cout << "?? getopt returned character code 0 " << c << std::endl; + return EXIT_FAILURE; } } From dd8253e6df60da5168ad5c10ebba6ce486b073e7 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Mon, 19 Jan 2015 17:51:40 +0100 Subject: [PATCH 78/80] added CONTRIBUTING file with instructions for eventual contributors --- CONTRIBUTING | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 CONTRIBUTING diff --git a/CONTRIBUTING b/CONTRIBUTING new file mode 100644 index 0000000..e337702 --- /dev/null +++ b/CONTRIBUTING @@ -0,0 +1,51 @@ +============ +Contributing +============ + +Want to improve the quality of tmux-mem-cpu-load code? Great! Here's a quick +guide: + +1. Fork, then clone the repo: + + git clone git@github.com:your-username/tmux-mem-cpu-load + +2. Make your change. Add tests for your change. +3. See if it compiles and runs like it should. +4. Run tests to check if you didn't break anything: + + make test + +Push to your fork and `submit a pull request`_. + +At this point you're waiting on us. We'll review your changes as soon as we can. +Before merging your changes we may request you to make some changes or +corrections. + +Style guidelines +---------------- + +You'll need to follow the subsequent rules in order to get your code merged: + +* Use Allman_ style for block braces. +* No space before `(` +* Add space after each `(` and before each `)` +* Use braces single line statements +* Don't use mixed case naming style, use underscores instead. + Bad example: + + int myAwesomeVariable = 0; + doSomething( myAwesomeVariable ); + + Good example: + + int my_awesome_variable = 0; + do_something( my_awesome_variable ); + +* Don't vertically align tokens on consecutive lines. +* If you break up an argument list, align the line to opening brace +* Use 2 space indentation (no tabs) +* Use spaces around operators, except for unary operators, such as `!`. +* Add LICENSE header in new files you create. + +.. _`submit a pull request`: https://github.com/thewtex/tmux-mem-cpu-load/compare/ +.. _Allman: http://en.wikipedia.org/wiki/Indent_style#Allman_style From ec6b1c6cc7b2bee885d0c63e12869246009b7ee3 Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Mon, 19 Jan 2015 17:55:29 +0100 Subject: [PATCH 79/80] remove leftover argParse.cc reference from CMakeList.txt --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc77596..86336e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,8 +32,8 @@ set(tmux-mem-cpu-load_VERSION # Check whether we have support for c++11 in compiler and fail if we don't include(CheckCXXCompilerFlag) -CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) -CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +check_cxx_compiler_flag("-std=c++11" COMPILER_SUPPORTS_CXX11) +check_cxx_compiler_flag("-std=c++0x" COMPILER_SUPPORTS_CXX0X) if(COMPILER_SUPPORTS_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") @@ -80,7 +80,7 @@ else() endif() # set common source files -SET( COMMON_SOURCES "tmux-mem-cpu-load.cpp" "graph.cc" "argParse/argParse.cc" ) +set( COMMON_SOURCES "tmux-mem-cpu-load.cpp" "graph.cc" ) # add binary tree so we find version.h include_directories("${PROJECT_BINARY_DIR}" ) From e459d40228eca42bc2bc84ae72f9dfaf7472cc6f Mon Sep 17 00:00:00 2001 From: "Pawel \"l0ner\" Soltys" Date: Mon, 19 Jan 2015 18:01:53 +0100 Subject: [PATCH 80/80] note about vim modelines and lower-case in CMake files --- CONTRIBUTING | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING b/CONTRIBUTING index e337702..86b8ed0 100644 --- a/CONTRIBUTING +++ b/CONTRIBUTING @@ -46,6 +46,8 @@ You'll need to follow the subsequent rules in order to get your code merged: * Use 2 space indentation (no tabs) * Use spaces around operators, except for unary operators, such as `!`. * Add LICENSE header in new files you create. +* Put vim modeline as the first line of file header +* Use the lower-case for CMake commands .. _`submit a pull request`: https://github.com/thewtex/tmux-mem-cpu-load/compare/ .. _Allman: http://en.wikipedia.org/wiki/Indent_style#Allman_style