初始化内容
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include <cstring>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
|
||||
// https://github.com/karelzak/util-linux/blob/master/sys-utils/lscpu.c
|
||||
iware::cpu::architecture_t iware::cpu::architecture() noexcept {
|
||||
utsname buf;
|
||||
|
||||
if(uname(&buf) == -1)
|
||||
return iware::cpu::architecture_t::unknown;
|
||||
|
||||
if(!strcmp(buf.machine, "x86_64"))
|
||||
return iware::cpu::architecture_t::x64;
|
||||
else if(strstr(buf.machine, "arm") == buf.machine)
|
||||
return iware::cpu::architecture_t::arm;
|
||||
else if(!strcmp(buf.machine, "ia64") || !strcmp(buf.machine, "IA64"))
|
||||
return iware::cpu::architecture_t::itanium;
|
||||
else if(!strcmp(buf.machine, "i686"))
|
||||
return iware::cpu::architecture_t::x86;
|
||||
else
|
||||
return iware::cpu::architecture_t::unknown;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724958(v=vs.85).aspx
|
||||
iware::cpu::architecture_t iware::cpu::architecture() noexcept {
|
||||
SYSTEM_INFO sysinfo;
|
||||
GetSystemInfo(&sysinfo);
|
||||
|
||||
switch(sysinfo.wProcessorArchitecture) {
|
||||
case PROCESSOR_ARCHITECTURE_AMD64:
|
||||
return iware::cpu::architecture_t::x64;
|
||||
case PROCESSOR_ARCHITECTURE_ARM:
|
||||
return iware::cpu::architecture_t::arm;
|
||||
case PROCESSOR_ARCHITECTURE_IA64:
|
||||
return iware::cpu::architecture_t::itanium;
|
||||
case PROCESSOR_ARCHITECTURE_INTEL:
|
||||
return iware::cpu::architecture_t::x86;
|
||||
default:
|
||||
return iware::cpu::architecture_t::unknown;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
iware::cpu::endianness_t iware::cpu::endianness() noexcept {
|
||||
const std::uint16_t test = 0xFF00;
|
||||
const auto result = *static_cast<const std::uint8_t*>(static_cast<const void*>(&test));
|
||||
|
||||
if(result == 0xFF)
|
||||
return iware::cpu::endianness_t::big;
|
||||
else
|
||||
return iware::cpu::endianness_t::little;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include "infoware/detail/sysctl.hpp"
|
||||
|
||||
|
||||
std::uint64_t iware::cpu::frequency() noexcept {
|
||||
const auto ctl_data = iware::detail::sysctl("hw.cpufrequency");
|
||||
if(ctl_data.empty())
|
||||
return 0;
|
||||
|
||||
const auto data = iware::detail::deconstruct_sysctl_int(ctl_data);
|
||||
if(!data.first)
|
||||
return 0;
|
||||
|
||||
return data.second;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
|
||||
std::uint64_t iware::cpu::frequency() noexcept {
|
||||
std::ifstream cpuinfo("/proc/cpuinfo");
|
||||
|
||||
if(!cpuinfo.is_open() || !cpuinfo)
|
||||
return 0;
|
||||
|
||||
for(std::string line; std::getline(cpuinfo, line);)
|
||||
if(line.find("cpu MHz") == 0) {
|
||||
const auto colon_id = line.find_first_of(':');
|
||||
return static_cast<std::uint64_t>(std::strtod(line.c_str() + colon_id + 1, nullptr) * 1'000'000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
std::uint64_t iware::cpu::frequency() noexcept {
|
||||
HKEY hkey;
|
||||
if(RegOpenKeyExA(HKEY_LOCAL_MACHINE, R"(HARDWARE\DESCRIPTION\System\CentralProcessor\0)", 0, KEY_READ, &hkey)) {
|
||||
// Fallback
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
return freq.QuadPart * 1'000;
|
||||
}
|
||||
|
||||
DWORD freq_mhz;
|
||||
DWORD freq_mhz_len = sizeof(freq_mhz);
|
||||
if(RegQueryValueExA(hkey, "~MHz", nullptr, nullptr, static_cast<LPBYTE>(static_cast<void*>(&freq_mhz)), &freq_mhz_len))
|
||||
return {};
|
||||
|
||||
return freq_mhz * 1'000'000;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,136 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include "infoware/detail/cpuid.hpp"
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#define INFOWARE_XCR_XFEATURE_ENABLED_MASK _XCR_XFEATURE_ENABLED_MASK
|
||||
#else
|
||||
#define INFOWARE_XCR_XFEATURE_ENABLED_MASK 0
|
||||
#endif // Is MSVC
|
||||
|
||||
|
||||
static bool has_os_avx() {
|
||||
bool avxsupport = false;
|
||||
|
||||
std::int32_t cpuinfo[4];
|
||||
iware::detail::cpuid(cpuinfo, 1);
|
||||
|
||||
bool osusesxsave_restore = (cpuinfo[2] & (1 << 27)) != 0;
|
||||
bool cpusupportsavx = (cpuinfo[2] & (1 << 28)) != 0;
|
||||
|
||||
if(osusesxsave_restore && cpusupportsavx) {
|
||||
const auto xcrFeatureMask = iware::detail::xgetbv(INFOWARE_XCR_XFEATURE_ENABLED_MASK);
|
||||
avxsupport = (xcrFeatureMask & 0x06) == 0x06;
|
||||
}
|
||||
|
||||
return avxsupport;
|
||||
}
|
||||
|
||||
static bool has_os_avx_512() {
|
||||
if(!has_os_avx())
|
||||
return false;
|
||||
|
||||
const auto xcrFeatureMask = iware::detail::xgetbv(INFOWARE_XCR_XFEATURE_ENABLED_MASK);
|
||||
return (xcrFeatureMask & 0xE6) == 0xE6;
|
||||
}
|
||||
|
||||
|
||||
std::vector<iware::cpu::instruction_set_t> iware::cpu::supported_instruction_sets() {
|
||||
std::int32_t info[4];
|
||||
iware::detail::cpuid(info, 0);
|
||||
const auto idinfo = info[0];
|
||||
|
||||
iware::detail::cpuid(info, 0x80000000);
|
||||
const std::uint32_t extendedidinfo = info[0];
|
||||
|
||||
std::vector<iware::cpu::instruction_set_t> supported;
|
||||
supported.reserve(64);
|
||||
|
||||
|
||||
#define ADD_SET_IF(infoindex, bitindex, name) \
|
||||
if((info[(infoindex)] & (1 << (bitindex))) != 0) \
|
||||
supported.push_back(iware::cpu::instruction_set_t::name);
|
||||
|
||||
|
||||
if(idinfo >= 0x00000001) {
|
||||
iware::detail::cpuid(info, 0x00000001);
|
||||
|
||||
ADD_SET_IF(3, 22, mmx_extended);
|
||||
ADD_SET_IF(3, 23, mmx);
|
||||
ADD_SET_IF(3, 25, sse);
|
||||
ADD_SET_IF(3, 26, sse2);
|
||||
|
||||
ADD_SET_IF(2, 0, sse3);
|
||||
ADD_SET_IF(2, 9, ssse3);
|
||||
ADD_SET_IF(2, 19, sse41);
|
||||
ADD_SET_IF(2, 20, sse42);
|
||||
ADD_SET_IF(2, 25, aes);
|
||||
ADD_SET_IF(2, 28, fma3);
|
||||
ADD_SET_IF(2, 12, rd_rand);
|
||||
}
|
||||
|
||||
if(idinfo >= 0x00000007) {
|
||||
iware::detail::cpuid(info, 0x00000007);
|
||||
|
||||
if(has_os_avx()) {
|
||||
// Both must be present to have AVX
|
||||
ADD_SET_IF(1, 5, avx2);
|
||||
}
|
||||
ADD_SET_IF(1, 4, hle);
|
||||
|
||||
ADD_SET_IF(1, 3, bmi1);
|
||||
ADD_SET_IF(1, 8, bmi2);
|
||||
ADD_SET_IF(1, 19, adx);
|
||||
ADD_SET_IF(1, 14, mpx);
|
||||
ADD_SET_IF(1, 29, sha);
|
||||
|
||||
if(has_os_avx_512()) {
|
||||
supported.push_back(iware::cpu::instruction_set_t::avx_512);
|
||||
|
||||
ADD_SET_IF(1, 16, avx_512_f);
|
||||
ADD_SET_IF(1, 28, avx_512_cd);
|
||||
ADD_SET_IF(1, 26, avx_512_pf);
|
||||
ADD_SET_IF(1, 27, avx_512_er);
|
||||
ADD_SET_IF(1, 31, avx_512_vl);
|
||||
ADD_SET_IF(1, 30, avx_512_bw);
|
||||
ADD_SET_IF(1, 17, avx_512_dq);
|
||||
ADD_SET_IF(1, 21, avx_512_ifma);
|
||||
ADD_SET_IF(2, 1, avx_512_vbmi);
|
||||
}
|
||||
|
||||
ADD_SET_IF(2, 0, prefetch_wt1);
|
||||
}
|
||||
|
||||
if(extendedidinfo >= 0x80000001) {
|
||||
iware::detail::cpuid(info, 0x80000001);
|
||||
|
||||
ADD_SET_IF(3, 29, x64);
|
||||
ADD_SET_IF(3, 0, x87_fpu);
|
||||
ADD_SET_IF(3, 30, s3d_now);
|
||||
ADD_SET_IF(3, 31, s3d_now_extended);
|
||||
ADD_SET_IF(3, 29, x64);
|
||||
ADD_SET_IF(2, 5, bmi1);
|
||||
ADD_SET_IF(2, 6, bmi2);
|
||||
ADD_SET_IF(2, 16, adx);
|
||||
ADD_SET_IF(2, 11, mpx);
|
||||
}
|
||||
|
||||
|
||||
#undef ADD_SET_IF
|
||||
|
||||
|
||||
return supported;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include "infoware/detail/sysctl.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
|
||||
static std::pair<const char* const*, const char* const*> instruction_set_to_names(iware::cpu::instruction_set_t set) {
|
||||
static const char* mmx[] = {"MMX"};
|
||||
static const char* threednow[] = {"3DNOW", "3DNOWEXT"};
|
||||
static const char* sse[] = {"SSE"};
|
||||
static const char* sse2[] = {"SSE2"};
|
||||
static const char* sse3[] = {"SSSE3", "SSE3"};
|
||||
static const char* avx[] = {"AVX"};
|
||||
|
||||
|
||||
#define HANDLED_CASE(iset, variable) \
|
||||
case iware::cpu::instruction_set_t::iset: \
|
||||
return {variable, variable + (sizeof(variable) / sizeof(*variable))};
|
||||
|
||||
switch(set) {
|
||||
HANDLED_CASE(s3d_now, threednow)
|
||||
HANDLED_CASE(mmx, mmx)
|
||||
HANDLED_CASE(sse, sse)
|
||||
HANDLED_CASE(sse2, sse2)
|
||||
HANDLED_CASE(sse3, sse3)
|
||||
HANDLED_CASE(avx, avx)
|
||||
|
||||
default:
|
||||
return {nullptr, nullptr};
|
||||
}
|
||||
|
||||
#undef HANDLED_CASE
|
||||
}
|
||||
|
||||
|
||||
bool iware::cpu::instruction_set_supported(iware::cpu::instruction_set_t set) {
|
||||
const auto ises = supported_instruction_sets();
|
||||
if(std::find(ises.begin(), ises.end(), set) != ises.cend())
|
||||
return true;
|
||||
|
||||
const auto set_names = instruction_set_to_names(set);
|
||||
if(!set_names.first)
|
||||
return false;
|
||||
|
||||
auto ctl_data = iware::detail::sysctl("machdep.cpu.features");
|
||||
if(ctl_data.empty())
|
||||
return 0;
|
||||
|
||||
for(auto cur_name = std::strtok(ctl_data.data(), " \t\n"); cur_name; cur_name = std::strtok(nullptr, " \t\n"))
|
||||
if(std::any_of(set_names.first, set_names.second, [&](auto name) { return name == cur_name; }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
|
||||
static std::pair<const char* const*, const char* const*> instruction_set_to_names(iware::cpu::instruction_set_t set) {
|
||||
static const char* mmx[] = {"mmx"};
|
||||
static const char* threednow[] = {"3dnow", "3dnowext"};
|
||||
static const char* sse[] = {"sse"};
|
||||
static const char* sse2[] = {"sse2"};
|
||||
static const char* sse3[] = {"ssse3", "sse3"};
|
||||
static const char* avx[] = {"avx"};
|
||||
|
||||
|
||||
#define HANDLED_CASE(iset, variable) \
|
||||
case iware::cpu::instruction_set_t::iset: \
|
||||
return {variable, variable + (sizeof(variable) / sizeof(*variable))};
|
||||
|
||||
switch(set) {
|
||||
HANDLED_CASE(s3d_now, threednow)
|
||||
HANDLED_CASE(mmx, mmx)
|
||||
HANDLED_CASE(sse, sse)
|
||||
HANDLED_CASE(sse2, sse2)
|
||||
HANDLED_CASE(sse3, sse3)
|
||||
HANDLED_CASE(avx, avx)
|
||||
|
||||
default:
|
||||
return {nullptr, nullptr};
|
||||
}
|
||||
|
||||
#undef HANDLED_CASE
|
||||
}
|
||||
|
||||
|
||||
bool iware::cpu::instruction_set_supported(iware::cpu::instruction_set_t set) {
|
||||
const auto ises = supported_instruction_sets();
|
||||
if(std::find(ises.begin(), ises.end(), set) != ises.cend())
|
||||
return true;
|
||||
|
||||
const auto set_names = instruction_set_to_names(set);
|
||||
if(!set_names.first)
|
||||
return false;
|
||||
|
||||
std::ifstream cpuinfo("/proc/cpuinfo");
|
||||
|
||||
if(!cpuinfo.is_open() || !cpuinfo)
|
||||
return false;
|
||||
|
||||
for(std::string tmp; std::getline(cpuinfo, tmp);)
|
||||
if(tmp.find("flags") == 0) {
|
||||
const auto colon_id = tmp.find_first_of(':');
|
||||
std::istringstream is(tmp.c_str() + colon_id + 1);
|
||||
while(is >> tmp)
|
||||
if(std::any_of(set_names.first, set_names.second, [&](auto name) { return tmp == name; }))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include <algorithm>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
bool iware::cpu::instruction_set_supported(iware::cpu::instruction_set_t set) {
|
||||
std::vector<iware::cpu::instruction_set_t> ises = supported_instruction_sets();
|
||||
if(std::find(ises.cbegin(), ises.cend(), set) != ises.cend())
|
||||
return true;
|
||||
|
||||
// TODO: is this necessary if we detect things with xgetbv and cpuid?
|
||||
// That is, AVX usually needs to have both OS support alongside
|
||||
DWORD feature;
|
||||
switch(set) {
|
||||
case iware::cpu::instruction_set_t::s3d_now:
|
||||
feature = PF_3DNOW_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
case iware::cpu::instruction_set_t::mmx:
|
||||
feature = PF_MMX_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
case iware::cpu::instruction_set_t::sse:
|
||||
feature = PF_XMMI_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
case iware::cpu::instruction_set_t::sse2:
|
||||
feature = PF_XMMI64_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
case iware::cpu::instruction_set_t::sse3:
|
||||
feature = PF_SSE3_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
case iware::cpu::instruction_set_t::avx:
|
||||
feature = PF_XMMI64_INSTRUCTIONS_AVAILABLE;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsProcessorFeaturePresent(feature) != 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,84 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include "infoware/detail/sysctl.hpp"
|
||||
|
||||
|
||||
// https://github.com/ThePhD/infoware/issues/12#issuecomment-495291650
|
||||
iware::cpu::quantities_t iware::cpu::quantities() {
|
||||
iware::cpu::quantities_t ret{};
|
||||
|
||||
const auto ctl_thread_data = iware::detail::sysctl("machdep.cpu.thread_count");
|
||||
if(!ctl_thread_data.empty()) {
|
||||
const auto thread_data = iware::detail::deconstruct_sysctl_int(ctl_thread_data);
|
||||
if(thread_data.first)
|
||||
ret.logical = thread_data.second;
|
||||
}
|
||||
|
||||
const auto ctl_core_data = iware::detail::sysctl("machdep.cpu.core_count");
|
||||
if(!ctl_core_data.empty()) {
|
||||
const auto core_data = iware::detail::deconstruct_sysctl_int(ctl_core_data);
|
||||
if(core_data.first)
|
||||
ret.physical = core_data.second;
|
||||
}
|
||||
|
||||
const auto ctl_packages_data = iware::detail::sysctl("hw.packages");
|
||||
if(!ctl_packages_data.empty()) {
|
||||
const auto packages_data = iware::detail::deconstruct_sysctl_int(ctl_packages_data);
|
||||
if(packages_data.first)
|
||||
ret.packages = packages_data.second;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// This is hell
|
||||
//
|
||||
// https://github.com/ThePhD/infoware/issues/12#issuecomment-495782115
|
||||
//
|
||||
// TODO: couldn't find a good way to get the associativity (default 0) or the type (default unified)
|
||||
iware::cpu::cache_t iware::cpu::cache(unsigned int level) {
|
||||
// Unspecified keys default to nullptr
|
||||
static const char* size_keys[][3]{{}, {"hw.l1icachesize", "hw.l1dcachesize", "hw.l1cachesize"}, {"hw.l2cachesize"}, {"hw.l3cachesize"}};
|
||||
|
||||
|
||||
iware::cpu::cache_t ret{};
|
||||
|
||||
const auto ctl_cachelinesize_data = iware::detail::sysctl("hw.cachelinesize");
|
||||
if(!ctl_cachelinesize_data.empty()) {
|
||||
const auto cachelinesize_data = iware::detail::deconstruct_sysctl_int(ctl_cachelinesize_data);
|
||||
if(cachelinesize_data.first)
|
||||
ret.line_size = cachelinesize_data.second;
|
||||
}
|
||||
|
||||
if(level < sizeof(size_keys) / sizeof(*size_keys))
|
||||
for(auto key : size_keys[level]) {
|
||||
if(!key)
|
||||
break;
|
||||
|
||||
const auto ctl_cachesize_data = iware::detail::sysctl(key);
|
||||
if(!ctl_cachesize_data.empty()) {
|
||||
const auto cachesize_data = iware::detail::deconstruct_sysctl_int(ctl_cachesize_data);
|
||||
if(cachesize_data.first)
|
||||
ret.size += cachesize_data.second;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
// http://stackoverflow.com/a/150971/2851815
|
||||
// https://github.com/karelzak/util-linux/blob/25b7045e5db032df5354c0749cb454a20b89c522/sys-utils/lscpu.c#L1119
|
||||
iware::cpu::quantities_t iware::cpu::quantities() {
|
||||
iware::cpu::quantities_t ret{};
|
||||
ret.logical = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
|
||||
std::ifstream cpuinfo("/proc/cpuinfo");
|
||||
|
||||
if(!cpuinfo.is_open() || !cpuinfo)
|
||||
return ret;
|
||||
|
||||
std::vector<unsigned int> package_ids;
|
||||
for(std::string line; std::getline(cpuinfo, line);)
|
||||
if(line.find("physical id") == 0) {
|
||||
const auto physical_id = std::strtoul(line.c_str() + line.find_first_of("1234567890"), nullptr, 10);
|
||||
if(std::find(package_ids.begin(), package_ids.end(), physical_id) == package_ids.end())
|
||||
package_ids.emplace_back(physical_id);
|
||||
}
|
||||
|
||||
ret.packages = package_ids.size();
|
||||
ret.physical = ret.logical / ret.packages;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// http://superuser.com/a/203481
|
||||
iware::cpu::cache_t iware::cpu::cache(unsigned int level) {
|
||||
std::string prefix("/sys/devices/system/cpu/cpu0/cache/index" + std::to_string(level) + '/');
|
||||
iware::cpu::cache_t ret{};
|
||||
|
||||
{
|
||||
std::ifstream size(prefix + "size");
|
||||
if(size.is_open() && size) {
|
||||
char suffix;
|
||||
size >> ret.size >> suffix;
|
||||
switch(suffix) {
|
||||
case 'G':
|
||||
ret.size *= 1024;
|
||||
[[fallthrough]];
|
||||
case 'M':
|
||||
ret.size *= 1024;
|
||||
[[fallthrough]];
|
||||
case 'K':
|
||||
ret.size *= 1024;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::ifstream line_size(prefix + "coherency_line_size");
|
||||
if(line_size.is_open() && line_size)
|
||||
line_size >> ret.line_size;
|
||||
}
|
||||
|
||||
{
|
||||
std::ifstream associativity(prefix + "associativity");
|
||||
if(associativity.is_open() && associativity) {
|
||||
unsigned int tmp;
|
||||
associativity >> tmp;
|
||||
ret.associativity = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::ifstream type(prefix + "type");
|
||||
if(type.is_open() && type) {
|
||||
std::string tmp;
|
||||
type >> tmp;
|
||||
if(tmp.find("nified") == 1)
|
||||
ret.type = iware::cpu::cache_type_t::unified;
|
||||
else if(tmp.find("nstruction") == 1)
|
||||
ret.type = iware::cpu::cache_type_t::instruction;
|
||||
else if(tmp.find("ata") == 1)
|
||||
ret.type = iware::cpu::cache_type_t::data;
|
||||
else if(tmp.find("race") == 1)
|
||||
ret.type = iware::cpu::cache_type_t::trace;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include <bitset>
|
||||
#include <vector>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
static std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> cpuinfo_buffer() {
|
||||
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer;
|
||||
|
||||
DWORD byte_count = 0;
|
||||
GetLogicalProcessorInformation(nullptr, &byte_count);
|
||||
buffer.resize(byte_count / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
|
||||
GetLogicalProcessorInformation(buffer.data(), &byte_count);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
// C++ified http://stackoverflow.com/a/28894219/2851815
|
||||
iware::cpu::quantities_t iware::cpu::quantities() {
|
||||
iware::cpu::quantities_t ret{};
|
||||
for(auto&& info : cpuinfo_buffer())
|
||||
switch(info.Relationship) {
|
||||
case RelationProcessorCore:
|
||||
++ret.physical;
|
||||
// A hyperthreaded core supplies more than one logical processor.
|
||||
ret.logical += static_cast<std::uint32_t>(std::bitset<sizeof(ULONG_PTR) * 8>(static_cast<std::uintptr_t>(info.ProcessorMask)).count());
|
||||
break;
|
||||
|
||||
case RelationProcessorPackage:
|
||||
// Logical processors share a physical package.
|
||||
++ret.packages;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
iware::cpu::cache_t iware::cpu::cache(unsigned int level) {
|
||||
for(auto&& info : cpuinfo_buffer())
|
||||
if(info.Relationship == RelationCache)
|
||||
// Cache data is in ptr->Cache, one CACHE_DESCRIPTOR structure for each cache.
|
||||
if(info.Cache.Level == level) {
|
||||
iware::cpu::cache_type_t type{};
|
||||
switch(info.Cache.Type) {
|
||||
case CacheUnified:
|
||||
type = iware::cpu::cache_type_t::unified;
|
||||
break;
|
||||
case CacheInstruction:
|
||||
type = iware::cpu::cache_type_t::instruction;
|
||||
break;
|
||||
case CacheData:
|
||||
type = iware::cpu::cache_type_t::data;
|
||||
break;
|
||||
case CacheTrace:
|
||||
type = iware::cpu::cache_type_t::trace;
|
||||
break;
|
||||
}
|
||||
return {info.Cache.Size, info.Cache.LineSize, info.Cache.Associativity, type};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include <infoware/cpu.hpp>
|
||||
#include <infoware/detail/cpuid.hpp>
|
||||
|
||||
|
||||
std::string iware::cpu::vendor_id() {
|
||||
std::int32_t info[4];
|
||||
char name[13];
|
||||
|
||||
iware::detail::cpuid(info, 0);
|
||||
std::memcpy(name + 0, &info[1], 4);
|
||||
std::memcpy(name + 4, &info[3], 4);
|
||||
std::memcpy(name + 8, &info[2], 4);
|
||||
name[12] = '\0';
|
||||
|
||||
return name;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include "infoware/detail/sysctl.hpp"
|
||||
#include <string>
|
||||
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
|
||||
static std::string sysctl_value(const char* subkey) {
|
||||
auto ctl_data = iware::detail::sysctl(("machdep.cpu."s + subkey).c_str());
|
||||
if(ctl_data.empty())
|
||||
return {};
|
||||
else
|
||||
return ctl_data.data();
|
||||
}
|
||||
|
||||
|
||||
std::string iware::cpu::vendor() {
|
||||
return sysctl_value("vendor");
|
||||
}
|
||||
|
||||
std::string iware::cpu::model_name() {
|
||||
return sysctl_value("brand_string");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
|
||||
static std::string cpuinfo_value(const char* key) {
|
||||
std::ifstream cpuinfo("/proc/cpuinfo");
|
||||
|
||||
if(!cpuinfo.is_open() || !cpuinfo)
|
||||
return {};
|
||||
|
||||
for(std::string line; std::getline(cpuinfo, line);)
|
||||
if(line.find(key) == 0) {
|
||||
const auto colon_id = line.find_first_of(':');
|
||||
const auto nonspace_id = line.find_first_not_of(" \t", colon_id + 1);
|
||||
return line.c_str() + nonspace_id;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
std::string iware::cpu::vendor() {
|
||||
return cpuinfo_value("vendor");
|
||||
}
|
||||
|
||||
std::string iware::cpu::model_name() {
|
||||
return cpuinfo_value("model name");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/cpu.hpp"
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
template <unsigned int IdentLen>
|
||||
static std::string central_processor_subkey(const char* key) {
|
||||
HKEY hkey;
|
||||
if(RegOpenKeyExA(HKEY_LOCAL_MACHINE, R"(HARDWARE\DESCRIPTION\System\CentralProcessor\0)", 0, KEY_READ, &hkey))
|
||||
return {};
|
||||
|
||||
char identifier[IdentLen];
|
||||
DWORD identifier_len = sizeof(identifier);
|
||||
LPBYTE lpdata = static_cast<LPBYTE>(static_cast<void*>(&identifier[0]));
|
||||
if(RegQueryValueExA(hkey, key, nullptr, nullptr, lpdata, &identifier_len))
|
||||
return {};
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
||||
std::string iware::cpu::vendor() {
|
||||
return central_processor_subkey<12 + 1>("VendorIdentifier");
|
||||
}
|
||||
|
||||
std::string iware::cpu::model_name() {
|
||||
return central_processor_subkey<64 + 1>("ProcessorNameString");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
|
||||
#include "infoware/detail/cpuid.hpp"
|
||||
#include <cpuid.h>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
void iware::detail::cpuid(std::int32_t (&out)[4], std::int32_t x) {
|
||||
__cpuid_count(x, 0, out[0], out[1], out[2], out[3]);
|
||||
}
|
||||
|
||||
std::uint64_t iware::detail::xgetbv(std::uint32_t index) {
|
||||
std::uint32_t eax, edx;
|
||||
__asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));
|
||||
return ((uint64_t)edx << 32) | eax;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/detail/cpuid.hpp"
|
||||
#include <cstdint>
|
||||
#include <intrin.h>
|
||||
|
||||
|
||||
void iware::detail::cpuid(std::int32_t (&out)[4], std::int32_t x) {
|
||||
__cpuidex(out, x, 0);
|
||||
}
|
||||
|
||||
std::uint64_t iware::detail::xgetbv(std::uint32_t x) {
|
||||
return _xgetbv(x);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#include "infoware/detail/scope.hpp"
|
||||
|
||||
|
||||
iware::detail::quickscope_wrapper::~quickscope_wrapper() {
|
||||
if(func)
|
||||
func();
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/detail/sysctl.hpp"
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
// Requires data.size() >= sizeof(T)
|
||||
template <class T>
|
||||
static std::pair<bool, T> deconstruct_specific_int(const std::vector<char>& data) {
|
||||
std::pair<bool, T> out{true, {}};
|
||||
std::memcpy(&out.second, data.data(), sizeof(out.second));
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
#define SYSCTL_IMPL(fname, ...) \
|
||||
std::size_t len{}; \
|
||||
if(fname(__VA_ARGS__, nullptr, &len, nullptr, 0)) \
|
||||
return {}; \
|
||||
\
|
||||
std::vector<char> ret(len); \
|
||||
if(fname(__VA_ARGS__, ret.data(), &len, nullptr, 0)) \
|
||||
return {}; \
|
||||
\
|
||||
return ret
|
||||
|
||||
std::vector<char> iware::detail::sysctl(const char* name) {
|
||||
SYSCTL_IMPL(::sysctlbyname, name);
|
||||
}
|
||||
|
||||
std::vector<char> iware::detail::sysctl(int mib_0, int mib_1) {
|
||||
int name[2]{mib_0, mib_1};
|
||||
|
||||
SYSCTL_IMPL(::sysctl, name, sizeof(name) / sizeof(*name));
|
||||
}
|
||||
|
||||
|
||||
std::pair<bool, std::uint64_t> iware::detail::deconstruct_sysctl_int(const std::vector<char>& data) {
|
||||
switch(data.size()) {
|
||||
case sizeof(std::uint16_t):
|
||||
return deconstruct_specific_int<std::uint16_t>(data);
|
||||
|
||||
case sizeof(std::uint32_t):
|
||||
return deconstruct_specific_int<std::uint32_t>(data);
|
||||
|
||||
case sizeof(std::uint64_t):
|
||||
return deconstruct_specific_int<std::uint64_t>(data);
|
||||
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/detail/sysctl.hpp"
|
||||
|
||||
|
||||
std::vector<char> iware::detail::sysctl(const char*) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<char> iware::detail::sysctl(int, int) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<bool, std::uint64_t> iware::detail::deconstruct_sysctl_int(const std::vector<char>&) {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
|
||||
#include "infoware/detail/winstring.hpp"
|
||||
|
||||
|
||||
std::string iware::detail::narrowen_winstring(const wchar_t*) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string iware::detail::narrowen_bstring(const wchar_t*) {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/detail/winstring.hpp"
|
||||
#include <cwchar>
|
||||
#include <string>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <wbemidl.h>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
static std::string transcode_from_wide(const wchar_t* wstr, std::size_t wstr_size) {
|
||||
std::string ret;
|
||||
// convert even embedded NUL
|
||||
if(const auto len = WideCharToMultiByte(CP_UTF8, 0, wstr, static_cast<int>(wstr_size), NULL, 0, 0, 0)) {
|
||||
ret.resize(len, '\0');
|
||||
if(!WideCharToMultiByte(CP_UTF8, 0, wstr, static_cast<int>(wstr_size), &ret[0], len, 0, 0))
|
||||
ret.clear();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string iware::detail::narrowen_winstring(const wchar_t* wstr) {
|
||||
if(!wstr)
|
||||
return {};
|
||||
|
||||
return transcode_from_wide(wstr, std::wcslen(wstr));
|
||||
}
|
||||
|
||||
std::string iware::detail::narrowen_bstring(const wchar_t* bstr) {
|
||||
if(!bstr)
|
||||
return {};
|
||||
|
||||
return transcode_from_wide(bstr, SysStringLen(const_cast<BSTR>(bstr)));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Vendored
+74
@@ -0,0 +1,74 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef INFOWARE_USE_D3D
|
||||
#ifdef INFOWARE_USE_OPENCL
|
||||
|
||||
#include "infoware/gpu.hpp"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#ifdef __APPLE__
|
||||
#include <OpenCL/opencl.h>
|
||||
#else
|
||||
#include <CL/cl.h>
|
||||
#endif
|
||||
|
||||
|
||||
static iware::gpu::vendor_t parse_vendor(const char* name) {
|
||||
if(!std::strcmp(name, "Intel(R) Corporation") || !std::strcmp(name, "Intel"))
|
||||
return iware::gpu::vendor_t::intel;
|
||||
else if(!std::strcmp(name, "Advanced Micro Devices, Inc.") || !std::strcmp(name, "AMD"))
|
||||
return iware::gpu::vendor_t::amd;
|
||||
else if(!std::strcmp(name, "NVIDIA Corporation"))
|
||||
return iware::gpu::vendor_t::nvidia;
|
||||
else if(!std::strcmp(name, "Apple"))
|
||||
return iware::gpu::vendor_t::apple;
|
||||
else
|
||||
return iware::gpu::vendor_t::unknown;
|
||||
}
|
||||
|
||||
|
||||
/// See https://github.com/Oblomov/clinfo/blob/bfc628e74d4cdbf5c5adca169e8bae540fca92ef/src/clinfo.c#L2104 for other available props
|
||||
std::vector<iware::gpu::device_properties_t> iware::gpu::device_properties() {
|
||||
cl_platform_id platforms[64];
|
||||
cl_uint platforms_used;
|
||||
clGetPlatformIDs(sizeof(platforms) / sizeof(*platforms), platforms, &platforms_used);
|
||||
|
||||
std::vector<iware::gpu::device_properties_t> ret;
|
||||
for(auto i = 0u; i < platforms_used; ++i) {
|
||||
cl_device_id devices[64];
|
||||
cl_uint devices_used;
|
||||
clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_GPU, sizeof(devices) / sizeof(*devices), devices, &devices_used);
|
||||
|
||||
for(auto j = 0u; j < devices_used; ++j) {
|
||||
char name[256];
|
||||
char vendorname[256];
|
||||
cl_ulong cache;
|
||||
cl_ulong memory;
|
||||
cl_uint max_frequency;
|
||||
|
||||
clGetDeviceInfo(devices[j], CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, sizeof(cache), &cache, nullptr);
|
||||
clGetDeviceInfo(devices[j], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(max_frequency), &max_frequency, nullptr);
|
||||
clGetDeviceInfo(devices[j], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(memory), &memory, nullptr);
|
||||
clGetDeviceInfo(devices[j], CL_DEVICE_VENDOR, sizeof(vendorname) / sizeof(*vendorname), &vendorname, nullptr);
|
||||
clGetDeviceInfo(devices[j], CL_DEVICE_NAME, sizeof(name) / sizeof(*name), &name, nullptr);
|
||||
|
||||
ret.push_back({parse_vendor(vendorname), name, memory, cache, max_frequency * 1'000'000});
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Vendored
+65
@@ -0,0 +1,65 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef INFOWARE_USE_D3D
|
||||
#ifndef INFOWARE_USE_OPENCL
|
||||
#ifdef INFOWARE_USE_OPENGL
|
||||
|
||||
|
||||
// OpenGL is literaly hitler to initialise a windowless context for, so no game.
|
||||
// Leave it for someone smarter than me :G
|
||||
//
|
||||
// Here is guidance I received from my Graphics Lord, Elim Garak, on Discord:
|
||||
// [5:44 PM] 🕴: Elim, my lord, plz tell me the simplest way of setting up a dummy OGL ctx so I can glGetString()
|
||||
// [5:46 PM] Elim | iscicadabannedyet.com: You know how to acquire your function pointers, rite? For WGL, EGL, XGL shit etc(edited)
|
||||
// [5:46 PM] Borgleader: glLoadGen >>>>> acquiring pointers manually
|
||||
// [5:46 PM] Elim | iscicadabannedyet.com: or that
|
||||
// [5:46 PM] 🕴: not really, no
|
||||
// [5:46 PM] Elim | iscicadabannedyet.com: You just want to know how to get the dummy?
|
||||
// [5:46 PM] Elim | iscicadabannedyet.com: oh
|
||||
// [5:47 PM] 🕴: from what I've read it's impl-def land
|
||||
// [5:47 PM] 🕴: OGL land is so fucking alien to me
|
||||
// [5:48 PM] 🕴: from what I read I assume you use like WGL or some shit to make a ctx which allows you to call OGL-proper functions
|
||||
// [5:48 PM] Elim | iscicadabannedyet.com: Basically, on Windows it's as trivial as wglCreateContext(GetDC(your_window_handle)
|
||||
// [5:48 PM] Elim | iscicadabannedyet.com: WGL is the glue between the Windows window system and OGL
|
||||
// [5:49 PM] 🕴: Can I use a dummy window for that?
|
||||
// [5:49 PM] Elim | iscicadabannedyet.com: yes
|
||||
// [5:49 PM] 🕴: cool
|
||||
// [5:49 PM] 🕴: And what on non-Windows?
|
||||
// [5:50 PM] Elim | iscicadabannedyet.com: On OS X, one doesn't need to jump through such hoops because the Apple lords integrated OpenGL 4.1 and below inside
|
||||
// of their system SDK
|
||||
// [5:50 PM] Elim | iscicadabannedyet.com: As for lunix, it's EGL over there
|
||||
// [5:50 PM] Elim | iscicadabannedyet.com: https://www.khronos.org/registry/egl/sdk/docs/man/html/eglCreateContext.xhtml
|
||||
// [5:50 PM] 🕴: So I don't need to set up anything on OSX, it will work OOTB?(edited)
|
||||
// [5:50 PM] Borgleader: except their drivers are shit so theres no point inusing it 😛
|
||||
// [5:51 PM] Elim | iscicadabannedyet.com: It will work in the sense that you can get any core profile out of the box, yeah
|
||||
// [5:51 PM] Elim | iscicadabannedyet.com: will it work practically as borgleader mentions
|
||||
// [5:51 PM] Elim | iscicadabannedyet.com: hehehe, fun times ahead 😛(edited)
|
||||
// [5:51 PM] 🕴: right, so a raw call on OSX, WGL wglCreateContext() w/dummy window on Windooze and EGL on Linux
|
||||
// [5:52 PM] Elim | iscicadabannedyet.com: yeah, on lunix eglCreateContext attaches to the display
|
||||
// [5:52 PM] 🕴: Elim is the greatest man of all time
|
||||
// [5:52 PM] Elim | iscicadabannedyet.com: bby, write code and be quiet 😛
|
||||
// [5:53 PM] Elim | iscicadabannedyet.com: but yeah, it's p retarded
|
||||
|
||||
|
||||
#include "infoware/gpu.hpp"
|
||||
#include <vector>
|
||||
|
||||
|
||||
std::vector<iware::gpu::device_properties_t> iware::gpu::device_properties() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef INFOWARE_USE_OPENGL
|
||||
#ifndef INFOWARE_USE_OPENCL
|
||||
#ifndef INFOWARE_USE_D3D
|
||||
|
||||
|
||||
#include "infoware/gpu.hpp"
|
||||
|
||||
|
||||
std::vector<iware::gpu::device_properties_t> iware::gpu::device_properties() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
Vendored
+69
@@ -0,0 +1,69 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef INFOWARE_USE_D3D
|
||||
|
||||
|
||||
#include "infoware/detail/memory.hpp"
|
||||
#include "infoware/detail/winstring.hpp"
|
||||
#include "infoware/gpu.hpp"
|
||||
#include "infoware/pci.hpp"
|
||||
#include <d3d11.h>
|
||||
#include <memory>
|
||||
|
||||
|
||||
static iware::gpu::vendor_t vendor_from_name(const std::string& v) {
|
||||
if(v.find("NVidia") != std::string::npos || v.find("NVIDIA") != std::string::npos)
|
||||
return iware::gpu::vendor_t::nvidia;
|
||||
else if(v.find("AMD") != std::string::npos || v.find("ATi") != std::string::npos || v.find("Advanced Micro Devices") != std::string::npos)
|
||||
return iware::gpu::vendor_t::amd;
|
||||
else if(v.find("Intel") != std::string::npos)
|
||||
return iware::gpu::vendor_t::intel;
|
||||
else if(v.find("Microsoft") != std::string::npos)
|
||||
return iware::gpu::vendor_t::microsoft;
|
||||
else if(v.find("Qualcomm") != std::string::npos)
|
||||
return iware::gpu::vendor_t::qualcomm;
|
||||
else
|
||||
return iware::gpu::vendor_t::unknown;
|
||||
}
|
||||
|
||||
|
||||
std::vector<iware::gpu::device_properties_t> iware::gpu::device_properties() {
|
||||
IDXGIFactory* factory_raw;
|
||||
if(CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&factory_raw)) != S_OK)
|
||||
return {};
|
||||
std::unique_ptr<IDXGIFactory, iware::detail::release_deleter> factory(factory_raw);
|
||||
|
||||
std::vector<iware::gpu::device_properties_t> devices{};
|
||||
for(auto aid = 0u;; ++aid) {
|
||||
IDXGIAdapter* adapter_raw;
|
||||
const auto adapter_result = factory->EnumAdapters(aid, &adapter_raw);
|
||||
if(adapter_result != S_OK || adapter_result == DXGI_ERROR_NOT_FOUND)
|
||||
break;
|
||||
std::unique_ptr<IDXGIAdapter, iware::detail::release_deleter> adapter(adapter_raw);
|
||||
|
||||
DXGI_ADAPTER_DESC adapterdesc;
|
||||
adapter->GetDesc(&adapterdesc);
|
||||
|
||||
const auto device = iware::pci::identify_device(adapterdesc.VendorId, adapterdesc.DeviceId);
|
||||
std::string device_name = device.device_name ? device.device_name : iware::detail::narrowen_winstring(adapterdesc.Description);
|
||||
|
||||
devices.push_back({vendor_from_name(device.vendor_name), device_name, adapterdesc.DedicatedVideoMemory, adapterdesc.SharedSystemMemory,
|
||||
// TODO: there's purportedly (https://en.wikipedia.org/wiki/Windows_Display_Driver_Model#WDDM_2.3)
|
||||
// a Windows API for getting the max clock, but I haven't been able to find it or use it
|
||||
0});
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Vendored
+72
@@ -0,0 +1,72 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#include "infoware/pci.hpp"
|
||||
#include "infoware_generated/pci_data.hpp"
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
|
||||
namespace {
|
||||
struct id_pair_t {
|
||||
std::uint64_t id;
|
||||
std::size_t index;
|
||||
};
|
||||
|
||||
struct pci_vendor_info_t {
|
||||
std::uint64_t pci_id;
|
||||
const char* name;
|
||||
std::initializer_list<const std::uint64_t> device_indices;
|
||||
};
|
||||
|
||||
struct pci_device_info_t {
|
||||
std::uint64_t pci_id;
|
||||
const char* name;
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
static const id_pair_t indices[]{INFOWARE_GENERATED_PCI_INDICES};
|
||||
static const pci_vendor_info_t vendors[]{INFOWARE_GENERATED_PCI_VENDORS};
|
||||
static const pci_device_info_t devices[]{INFOWARE_GENERATED_PCI_DEVICES};
|
||||
|
||||
|
||||
static const pci_vendor_info_t* find_vendor(std::uint64_t vendor_id) noexcept {
|
||||
const auto idx_itr = std::lower_bound(std::begin(indices), std::end(indices), vendor_id, [](auto&& left, auto right) { return left.id < right; });
|
||||
if(idx_itr != std::end(indices) && idx_itr->id == vendor_id)
|
||||
return &vendors[idx_itr->index];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
iware::pci::device iware::pci::identify_device(std::uint64_t vendor_id, std::uint64_t device_id) noexcept {
|
||||
const auto vendor = find_vendor(vendor_id);
|
||||
if(!vendor)
|
||||
return {nullptr, nullptr};
|
||||
|
||||
const auto device_itr = std::lower_bound(std::begin(vendor->device_indices), std::end(vendor->device_indices), device_id,
|
||||
[](auto left, auto right) { return devices[left].pci_id < right; });
|
||||
if(device_itr == std::end(vendor->device_indices) || devices[*device_itr].pci_id != device_id)
|
||||
return {vendor->name, nullptr};
|
||||
|
||||
const auto& device = devices[*device_itr];
|
||||
return {vendor->name, device.name};
|
||||
}
|
||||
|
||||
|
||||
const char* iware::pci::identify_vendor(std::uint64_t pci_id) noexcept {
|
||||
if(const auto vendor = find_vendor(pci_id))
|
||||
return vendor->name;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/detail/sysctl.hpp"
|
||||
#include "infoware/system.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
iware::system::OS_info_t iware::system::OS_info() {
|
||||
auto ctl_ostype_data = iware::detail::sysctl("kern.ostype");
|
||||
auto ctl_version_data = iware::detail::sysctl("kern.version");
|
||||
|
||||
auto ctl_osrelease_data = iware::detail::sysctl("kern.osrelease");
|
||||
char buf{};
|
||||
char* osrelease_marker = ctl_osrelease_data.empty() ? &buf : ctl_osrelease_data.data();
|
||||
|
||||
const auto ctl_osrevision_data = iware::detail::sysctl("kern.osrevision");
|
||||
unsigned int build_number{};
|
||||
if(!ctl_osrevision_data.empty()) {
|
||||
const auto osrevision_data = iware::detail::deconstruct_sysctl_int(ctl_osrevision_data);
|
||||
if(osrevision_data.first)
|
||||
build_number = osrevision_data.second;
|
||||
}
|
||||
|
||||
return {ctl_ostype_data.empty() ? "" : ctl_ostype_data.data(), //
|
||||
ctl_version_data.empty() ? "" : ctl_version_data.data(), //
|
||||
static_cast<unsigned int>(std::strtoul(osrelease_marker, &osrelease_marker, 10)), //
|
||||
static_cast<unsigned int>(std::strtoul(osrelease_marker + 1, &osrelease_marker, 10)), //
|
||||
static_cast<unsigned int>(std::strtoul(osrelease_marker + 1, nullptr, 10)), //
|
||||
build_number};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/system.hpp"
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
static iware::system::OS_info_t lsb_release(std::ifstream& release) {
|
||||
iware::system::OS_info_t ret{};
|
||||
|
||||
for(std::string line; std::getline(release, line);)
|
||||
if(line.find("DISTRIB_ID") == 0)
|
||||
ret.name = line.substr(line.find('=') + 1);
|
||||
else if(line.find("DISTRIB_RELEASE") == 0) {
|
||||
char* marker = &line[line.find('=') + 1];
|
||||
ret.major = std::strtoul(marker, &marker, 10);
|
||||
ret.minor = std::strtoul(marker + 1, &marker, 10);
|
||||
ret.patch = std::strtoul(marker + 1, &marker, 10);
|
||||
ret.build_number = std::strtoul(marker + 1, nullptr, 10);
|
||||
} else if(line.find("DISTRIB_DESCRIPTION") == 0) {
|
||||
const auto start_idx = line.find('"') + 1;
|
||||
const auto end_idx = line.size() - 1;
|
||||
ret.full_name = line.substr(start_idx, end_idx - start_idx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void trim_quotes(std::string& in) {
|
||||
if(in.empty())
|
||||
return;
|
||||
|
||||
if(in.back() == '"')
|
||||
in.pop_back();
|
||||
|
||||
if(in.front() == '"')
|
||||
in.erase(in.begin());
|
||||
}
|
||||
|
||||
|
||||
// https://www.linux.org/docs/man5/os-release.html
|
||||
iware::system::OS_info_t iware::system::OS_info() {
|
||||
std::ifstream release("/etc/os-release");
|
||||
|
||||
if(!release.is_open() || !release) {
|
||||
release.open("/usr/lib/os-release", std::ios::in);
|
||||
if(!release.is_open() || !release) {
|
||||
release.open("/etc/lsb-release", std::ios::in);
|
||||
if(!release.is_open() || !release)
|
||||
return {};
|
||||
else
|
||||
return lsb_release(release);
|
||||
}
|
||||
}
|
||||
|
||||
iware::system::OS_info_t ret{};
|
||||
|
||||
for(std::string line; std::getline(release, line);)
|
||||
if(line.find("NAME") == 0)
|
||||
ret.name = line.substr(line.find('=') + 1);
|
||||
else if(line.find("PRETTY_NAME") == 0)
|
||||
ret.full_name = line.substr(line.find('=') + 1);
|
||||
else if(line.find("VERSION_ID") == 0) {
|
||||
char* marker = &line[line.find('=') + 1];
|
||||
if(marker[0] == '"')
|
||||
++marker;
|
||||
ret.major = std::strtoul(marker, &marker, 10);
|
||||
if(marker[0] && marker[0] != '"')
|
||||
ret.minor = std::strtoul(marker + 1, &marker, 10);
|
||||
if(marker[0] && marker[0] != '"')
|
||||
ret.patch = std::strtoul(marker + 1, &marker, 10);
|
||||
if(marker[0] && marker[0] != '"')
|
||||
ret.build_number = std::strtoul(marker + 1, nullptr, 10);
|
||||
}
|
||||
|
||||
trim_quotes(ret.name);
|
||||
trim_quotes(ret.full_name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/detail/memory.hpp"
|
||||
#include "infoware/detail/scope.hpp"
|
||||
#include "infoware/detail/winstring.hpp"
|
||||
#include "infoware/system.hpp"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <wbemidl.h>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
// Use WIM to acquire Win32_OperatingSystem.Name
|
||||
// https://msdn.microsoft.com/en-us/library/aa390423(v=vs.85).aspx
|
||||
static std::string version_name() {
|
||||
auto err = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
if(FAILED(err) && err != RPC_E_CHANGED_MODE)
|
||||
return {};
|
||||
iware::detail::quickscope_wrapper com_uninitialiser{CoUninitialize};
|
||||
|
||||
const auto init_result =
|
||||
CoInitializeSecurity(nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE, nullptr);
|
||||
if(FAILED(init_result) && init_result != RPC_E_TOO_LATE)
|
||||
return {};
|
||||
|
||||
IWbemLocator* wbem_loc_raw;
|
||||
if(FAILED(CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, reinterpret_cast<void**>(&wbem_loc_raw))))
|
||||
return {};
|
||||
std::unique_ptr<IWbemLocator, iware::detail::release_deleter> wbem_loc(wbem_loc_raw);
|
||||
|
||||
IWbemServices* wbem_services_raw;
|
||||
wchar_t network_resource[] = LR"(ROOT\CIMV2)";
|
||||
if(FAILED(wbem_loc->ConnectServer(network_resource, nullptr, nullptr, 0, 0, 0, 0, &wbem_services_raw)))
|
||||
return {};
|
||||
std::unique_ptr<IWbemServices, iware::detail::release_deleter> wbem_services(wbem_services_raw);
|
||||
|
||||
if(FAILED(CoSetProxyBlanket(wbem_services.get(), RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr,
|
||||
EOAC_NONE)))
|
||||
return {};
|
||||
|
||||
IEnumWbemClassObject* query_iterator_raw;
|
||||
wchar_t query_lang[] = L"WQL";
|
||||
wchar_t query[] = L"SELECT Name FROM Win32_OperatingSystem";
|
||||
if(FAILED(wbem_services->ExecQuery(query_lang, query, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, &query_iterator_raw)))
|
||||
return {};
|
||||
std::unique_ptr<IEnumWbemClassObject, iware::detail::release_deleter> query_iterator(query_iterator_raw);
|
||||
|
||||
std::string ret;
|
||||
while(query_iterator) {
|
||||
IWbemClassObject* value_raw;
|
||||
unsigned long iter_result;
|
||||
|
||||
query_iterator->Next(static_cast<LONG>(WBEM_INFINITE), 1, &value_raw, &iter_result);
|
||||
if(!iter_result)
|
||||
break;
|
||||
std::unique_ptr<IWbemClassObject, iware::detail::release_deleter> value(value_raw);
|
||||
|
||||
VARIANT val;
|
||||
value->Get(L"Name", 0, &val, 0, 0);
|
||||
iware::detail::quickscope_wrapper val_destructor{[&] { VariantClear(&val); }};
|
||||
|
||||
ret = iware::detail::narrowen_bstring(val.bstrVal);
|
||||
}
|
||||
return ret.substr(0, ret.find('|'));
|
||||
}
|
||||
|
||||
|
||||
iware::system::OS_info_t iware::system::OS_info() {
|
||||
const auto kernel_version = iware::system::kernel_info();
|
||||
return {"Windows NT", version_name(), kernel_version.major, kernel_version.minor, kernel_version.patch, kernel_version.build_number};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
|
||||
#include "infoware/detail/scope.hpp"
|
||||
#include "infoware/system.hpp"
|
||||
#include <cstring>
|
||||
#include <wordexp.h>
|
||||
|
||||
|
||||
// http://man7.org/linux/man-pages/man3/wordexp.3.html
|
||||
static std::size_t count_expansions(const char* of) noexcept {
|
||||
wordexp_t exp{};
|
||||
iware::detail::quickscope_wrapper exp_deleter{[&]() { wordfree(&exp); }};
|
||||
|
||||
if(wordexp(of, &exp, 0))
|
||||
return 0;
|
||||
|
||||
// If nothing is expanded wordexp() returns the original string
|
||||
if(exp.we_wordc == 1 && std::strcmp(exp.we_wordv[0], of) == 0)
|
||||
return 0;
|
||||
else
|
||||
return exp.we_wordc;
|
||||
}
|
||||
|
||||
|
||||
// http://unix.stackexchange.com/questions/25601/how-do-mouse-events-work-in-linux
|
||||
// https://www.kernel.org/doc/Documentation/input/input.txt section 3.2.2
|
||||
std::size_t iware::system::mouse_amount() noexcept {
|
||||
return count_expansions("/dev/input/mouse*");
|
||||
}
|
||||
|
||||
// https://www.kernel.org/doc/Documentation/input/input.txt section 3.2.1
|
||||
// Doesn't specify that and there doesn't seem to be a way to get it
|
||||
std::size_t iware::system::keyboard_amount() noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t iware::system::other_HID_amount() noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/system.hpp"
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <algorithm>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms645598(v=vs.85).aspx
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms645568(v=vs.85).aspx
|
||||
static std::size_t device_amount(unsigned int device_type) noexcept {
|
||||
// Assuming 64 is enough for anyone
|
||||
RAWINPUTDEVICELIST input_devices[64];
|
||||
unsigned int input_devices_n = sizeof(input_devices) / sizeof(RAWINPUTDEVICELIST);
|
||||
const auto amt = GetRawInputDeviceList(input_devices, &input_devices_n, sizeof(RAWINPUTDEVICELIST));
|
||||
|
||||
return std::count_if(input_devices, input_devices + amt, [&](auto&& device) { return device.dwType == device_type; });
|
||||
}
|
||||
|
||||
|
||||
std::size_t iware::system::mouse_amount() noexcept {
|
||||
return device_amount(RIM_TYPEMOUSE);
|
||||
}
|
||||
|
||||
std::size_t iware::system::keyboard_amount() noexcept {
|
||||
return device_amount(RIM_TYPEKEYBOARD);
|
||||
}
|
||||
|
||||
std::size_t iware::system::other_HID_amount() noexcept {
|
||||
return device_amount(RIM_TYPEHID);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
//
|
||||
//
|
||||
// Darwin support via Carbon API originally by Arthur Biancarelli – https://github.com/ThePhD/infoware/issues/17#issuecomment-538789869
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/detail/scope.hpp"
|
||||
#include "infoware/system.hpp"
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
template <class T, class F>
|
||||
static std::vector<T> enumerate_displays(F&& cbk) {
|
||||
std::uint32_t num_displays;
|
||||
if(CGGetActiveDisplayList(0, nullptr, &num_displays) != kCGErrorSuccess)
|
||||
return {};
|
||||
|
||||
std::vector<CGDirectDisplayID> display_ids(num_displays);
|
||||
if(CGGetActiveDisplayList(num_displays, display_ids.data(), &num_displays) != kCGErrorSuccess)
|
||||
return {};
|
||||
|
||||
|
||||
std::vector<T> ret;
|
||||
ret.reserve(num_displays);
|
||||
|
||||
for(std::size_t i = 0; i < num_displays; ++i)
|
||||
ret.emplace_back(std::move(cbk(display_ids[i])));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::vector<iware::system::display_t> iware::system::displays() {
|
||||
return enumerate_displays<iware::system::display_t>([](auto display_id) {
|
||||
const std::uint32_t width = CGDisplayPixelsWide(display_id);
|
||||
// 25.4 millimeters per inch
|
||||
const std::uint32_t dpi = 25.4 * CGDisplayScreenSize(display_id).width / width;
|
||||
|
||||
auto display_mode = CGDisplayCopyDisplayMode(display_id);
|
||||
iware::detail::quickscope_wrapper display_mode_deleter{[&]() { CGDisplayModeRelease(display_mode); }};
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
// A string in the form --------RRRRRRRRGGGGGGGGBBBBBBBB
|
||||
auto pixel_encoding_raw = CGDisplayModeCopyPixelEncoding(display_mode);
|
||||
iware::detail::quickscope_wrapper pixel_encoding_raw_deleter{[&]() { CFRelease(pixel_encoding_raw); }};
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// Count the number of occurences of R/G/B pixels
|
||||
std::uint32_t bpp{};
|
||||
if(const auto pixel_encoding = CFStringGetCStringPtr(pixel_encoding_raw, kCFStringEncodingUTF8))
|
||||
bpp = std::count_if(pixel_encoding, pixel_encoding + std::strlen(pixel_encoding), [](auto c) { return c == 'R' || c == 'G' || c == 'B'; });
|
||||
|
||||
|
||||
return iware::system::display_t{width, static_cast<std::uint32_t>(CGDisplayPixelsHigh(display_id)), dpi, bpp,
|
||||
// The refresh rate, in hertz, of the specified display mode for a CRT display.
|
||||
// Some displays may not use conventional video vertical and horizontal sweep in painting the screen;
|
||||
// for these displays, the return value is 0.
|
||||
//
|
||||
// Tested to return 0 for Retina displays
|
||||
CGDisplayModeGetRefreshRate(display_mode)};
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::vector<iware::system::display_config_t>> iware::system::available_display_configurations() {
|
||||
return enumerate_displays<std::vector<iware::system::display_config_t>>([](auto display_id) {
|
||||
auto modes = CGDisplayCopyAllDisplayModes(display_id, nullptr);
|
||||
if(!modes)
|
||||
return std::vector<iware::system::display_config_t>{};
|
||||
iware::detail::quickscope_wrapper modes_deleter{[&]() { CFRelease(modes); }};
|
||||
|
||||
const auto modes_len = CFArrayGetCount(modes);
|
||||
std::vector<iware::system::display_config_t> ret;
|
||||
ret.reserve(modes_len);
|
||||
|
||||
for(auto i = 0l; i < modes_len; ++i) {
|
||||
auto mode = static_cast<CGDisplayModeRef>(const_cast<void*>(CFArrayGetValueAtIndex(modes, i)));
|
||||
|
||||
ret.emplace_back(iware::system::display_config_t{static_cast<std::uint32_t>(CGDisplayModeGetWidth(mode)),
|
||||
static_cast<std::uint32_t>(CGDisplayModeGetHeight(mode)),
|
||||
{CGDisplayModeGetRefreshRate(mode)}});
|
||||
}
|
||||
|
||||
return ret;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef __APPLE__
|
||||
#ifndef INFOWARE_USE_X11
|
||||
|
||||
|
||||
#include "infoware/system.hpp"
|
||||
|
||||
|
||||
std::vector<iware::system::display_t> iware::system::displays() {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::vector<iware::system::display_config_t>> iware::system::available_display_configurations() {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,97 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/system.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
std::vector<iware::system::display_t> iware::system::displays() {
|
||||
std::vector<iware::system::display_t> ret;
|
||||
|
||||
EnumDisplayMonitors(
|
||||
nullptr, nullptr,
|
||||
[](auto, auto hdc, auto rect, auto userdata) {
|
||||
static const auto desktop_dc = GetDC(nullptr);
|
||||
static const unsigned int desktop_dpi = GetDeviceCaps(desktop_dc, LOGPIXELSX);
|
||||
// https://blogs.msdn.microsoft.com/oldnewthing/20101013-00/?p=12543
|
||||
static const unsigned int desktop_bpp = GetDeviceCaps(desktop_dc, BITSPIXEL) * GetDeviceCaps(desktop_dc, PLANES);
|
||||
static const double desktop_refresh_rate = GetDeviceCaps(desktop_dc, VREFRESH);
|
||||
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510(v=vs.85).aspx
|
||||
// Doesn't work, can't link to shcore
|
||||
//
|
||||
// unsigned int dpi_x;
|
||||
// unsigned int dpi_y;
|
||||
// GetDpiForMonitor(monitor /* arg #1 */, MDT_DEFAULT, &dpi_x, &dpi_y);
|
||||
|
||||
// Sometimes returns 0 for some reason?
|
||||
// Fall back to the desktop's globals if so.
|
||||
const unsigned int monitor_dpi = GetDeviceCaps(hdc, LOGPIXELSX);
|
||||
const unsigned int monitor_bpp = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
|
||||
const double monitor_refresh_rate = GetDeviceCaps(hdc, VREFRESH);
|
||||
|
||||
const unsigned int width = std::abs(rect->right - rect->left);
|
||||
const unsigned int height = std::abs(rect->bottom - rect->top);
|
||||
|
||||
auto& ret = *reinterpret_cast<std::vector<iware::system::display_t>*>(userdata);
|
||||
// See http://stackoverflow.com/a/12654433/2851815 and up for DPI. In short: can't be done too too well, go with best solution.
|
||||
ret.push_back({width, height, monitor_dpi ? monitor_dpi : desktop_dpi, monitor_bpp ? monitor_bpp : desktop_bpp,
|
||||
monitor_refresh_rate ? monitor_refresh_rate : desktop_refresh_rate});
|
||||
|
||||
return 1;
|
||||
},
|
||||
reinterpret_cast<LPARAM>(&ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::vector<iware::system::display_config_t>> iware::system::available_display_configurations() {
|
||||
std::vector<std::vector<iware::system::display_config_t>> ret;
|
||||
|
||||
DISPLAY_DEVICE dev;
|
||||
dev.cb = sizeof(dev);
|
||||
|
||||
for(DWORD dev_i = 0; EnumDisplayDevices(nullptr, dev_i, &dev, EDD_GET_DEVICE_INTERFACE_NAME); ++dev_i) {
|
||||
std::vector<iware::system::display_config_t> configs;
|
||||
const auto add_config = [&](auto&& mode) {
|
||||
configs.emplace_back(iware::system::display_config_t{mode.dmPelsWidth, mode.dmPelsHeight, {static_cast<double>(mode.dmDisplayFrequency)}});
|
||||
};
|
||||
|
||||
DEVMODE mode{};
|
||||
for(DWORD mode_i = 0; EnumDisplaySettings(dev.DeviceName, mode_i, &mode); ++mode_i)
|
||||
if(configs.empty())
|
||||
add_config(mode);
|
||||
else {
|
||||
auto&& last = configs.back();
|
||||
if(last.width == mode.dmPelsWidth && last.height == mode.dmPelsHeight) {
|
||||
if(std::find(last.refresh_rates.begin(), last.refresh_rates.end(), mode.dmDisplayFrequency) == last.refresh_rates.end())
|
||||
last.refresh_rates.emplace_back(mode.dmDisplayFrequency);
|
||||
} else
|
||||
add_config(mode);
|
||||
}
|
||||
|
||||
if(!configs.empty())
|
||||
ret.emplace_back(std::move(configs));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,91 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef __APPLE__
|
||||
#ifdef INFOWARE_USE_X11
|
||||
|
||||
|
||||
#include "infoware/detail/scope.hpp"
|
||||
#include "infoware/system.hpp"
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
template <class T, class F>
|
||||
static std::vector<T> enumerate_screens(F&& cbk) {
|
||||
const auto display_name = std::getenv("DISPLAY");
|
||||
if(!display_name)
|
||||
return {};
|
||||
|
||||
auto display = XOpenDisplay(display_name);
|
||||
if(!display)
|
||||
return {};
|
||||
iware::detail::quickscope_wrapper display_deleter{[&]() { XCloseDisplay(display); }};
|
||||
|
||||
const auto screen_count = ScreenCount(display);
|
||||
std::vector<T> ret;
|
||||
ret.reserve(screen_count);
|
||||
|
||||
for(auto i = 0; i < screen_count; ++i) {
|
||||
const auto root = RootWindow(display, i);
|
||||
auto config = XRRGetScreenInfo(display, root);
|
||||
if(!config)
|
||||
continue;
|
||||
iware::detail::quickscope_wrapper config_deleter{[&]() { XRRFreeScreenConfigInfo(config); }};
|
||||
|
||||
ret.emplace_back(std::move(cbk(display, i, config)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::vector<iware::system::display_t> iware::system::displays() {
|
||||
return enumerate_screens<iware::system::display_t>([](auto display, auto screen_number, auto screen_config) {
|
||||
const std::uint32_t width = DisplayWidth(display, screen_number);
|
||||
return iware::system::display_t{
|
||||
width,
|
||||
static_cast<std::uint32_t>(DisplayHeight(display, screen_number)),
|
||||
// 25.4 millimeters per inch
|
||||
static_cast<std::uint32_t>(25.4 * DisplayWidthMM(display, screen_number) / width),
|
||||
static_cast<std::uint32_t>(DefaultDepth(display, screen_number)),
|
||||
static_cast<double>(XRRConfigCurrentRate(screen_config)),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::vector<iware::system::display_config_t>> iware::system::available_display_configurations() {
|
||||
return enumerate_screens<std::vector<iware::system::display_config_t>>([](auto, auto, auto screen_config) {
|
||||
int size_count;
|
||||
const auto sizes = XRRConfigSizes(screen_config, &size_count);
|
||||
|
||||
std::vector<iware::system::display_config_t> configs;
|
||||
configs.reserve(size_count);
|
||||
|
||||
for(auto i = 0; i < size_count; i++) {
|
||||
int rate_count;
|
||||
const auto rates = XRRConfigRates(screen_config, i, &rate_count);
|
||||
|
||||
configs.emplace_back(iware::system::display_config_t{
|
||||
static_cast<std::uint32_t>(sizes[i].width), static_cast<std::uint32_t>(sizes[i].height), {rates, rates + rate_count}});
|
||||
}
|
||||
|
||||
return configs;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
|
||||
#include "infoware/system.hpp"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
|
||||
iware::system::kernel_info_t iware::system::kernel_info() {
|
||||
utsname uts;
|
||||
uname(&uts);
|
||||
|
||||
char* marker = uts.release;
|
||||
const std::uint32_t major = std::strtoul(marker, &marker, 10);
|
||||
const std::uint32_t minor = std::strtoul(marker + 1, &marker, 10);
|
||||
const std::uint32_t patch = std::strtoul(marker + 1, &marker, 10);
|
||||
const std::uint32_t build_number = std::strtoul(marker + 1, nullptr, 10);
|
||||
|
||||
auto kernel = iware::system::kernel_t::unknown;
|
||||
if(!std::strcmp(uts.sysname, "Linux"))
|
||||
kernel = iware::system::kernel_t::linux;
|
||||
else if(!std::strcmp(uts.sysname, "Darwin"))
|
||||
kernel = iware::system::kernel_t::darwin;
|
||||
|
||||
return {kernel, major, minor, patch, build_number};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/detail/scope.hpp"
|
||||
#include "infoware/system.hpp"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
// Get OS (platform) version from kernel32.dll because GetVersion is deprecated in Win8+
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
|
||||
iware::system::kernel_info_t iware::system::kernel_info() {
|
||||
std::string path;
|
||||
path.resize(GetSystemDirectoryA(nullptr, 0) - 1);
|
||||
GetSystemDirectoryA(&path[0], static_cast<UINT>(path.size() + 1));
|
||||
path += "\\kernel32.dll";
|
||||
|
||||
const auto ver_info_len = GetFileVersionInfoSizeA(path.c_str(), nullptr);
|
||||
auto ver_info = std::make_unique<std::uint8_t[]>(ver_info_len);
|
||||
GetFileVersionInfoA(path.c_str(), 0, ver_info_len, ver_info.get());
|
||||
|
||||
VS_FIXEDFILEINFO* file_version;
|
||||
unsigned int file_version_len;
|
||||
VerQueryValueA(ver_info.get(), "", reinterpret_cast<void**>(&file_version), &file_version_len);
|
||||
|
||||
return {iware::system::kernel_t::windows_nt, HIWORD(file_version->dwProductVersionMS), LOWORD(file_version->dwProductVersionMS),
|
||||
HIWORD(file_version->dwProductVersionLS), LOWORD(file_version->dwProductVersionLS)};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/detail/sysctl.hpp"
|
||||
#include "infoware/system.hpp"
|
||||
#include <cstdint>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/vm_statistics.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/// Adapted from https://stackoverflow.com/q/14789672/2851815
|
||||
iware::system::memory_t iware::system::memory() noexcept {
|
||||
iware::system::memory_t ret{};
|
||||
|
||||
const auto host = mach_host_self();
|
||||
|
||||
const auto ctl_ram = iware::detail::sysctl(CTL_HW, HW_MEMSIZE);
|
||||
if(!ctl_ram.empty()) {
|
||||
const auto ram = iware::detail::deconstruct_sysctl_int(ctl_ram);
|
||||
if(ram.first)
|
||||
ret.virtual_total = ram.second;
|
||||
}
|
||||
|
||||
vm_statistics64 stats;
|
||||
natural_t count = HOST_VM_INFO64_COUNT;
|
||||
if(host_statistics64(host, HOST_VM_INFO64, reinterpret_cast<host_info64_t>(&stats), &count) == KERN_SUCCESS)
|
||||
ret.virtual_available = stats.free_count * getpagesize();
|
||||
|
||||
ret.physical_total = ret.virtual_total;
|
||||
ret.physical_available = ret.virtual_available;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef __APPLE__
|
||||
|
||||
|
||||
#include "infoware/system.hpp"
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
|
||||
iware::system::memory_t iware::system::memory() noexcept {
|
||||
std::ifstream meminfo("/proc/meminfo");
|
||||
|
||||
if(!meminfo.is_open() || !meminfo)
|
||||
return {};
|
||||
|
||||
iware::system::memory_t ret;
|
||||
for(std::string line; std::getline(meminfo, line);) {
|
||||
const auto colon_id = line.find_first_of(':');
|
||||
const auto value = std::strtoul(line.c_str() + colon_id + 1, nullptr, 10) * 1024;
|
||||
|
||||
if(line.find("MemTotal") == 0)
|
||||
ret.physical_total = value;
|
||||
else if(line.find("MemAvailable") == 0)
|
||||
ret.physical_available = value;
|
||||
else if(line.find("VmallocTotal") == 0)
|
||||
ret.virtual_total = value;
|
||||
else if(line.find("VmallocUsed") == 0)
|
||||
ret.virtual_available = ret.virtual_total - value;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include "infoware/system.hpp"
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
iware::system::memory_t iware::system::memory() noexcept {
|
||||
MEMORYSTATUSEX mem;
|
||||
mem.dwLength = sizeof(mem);
|
||||
if(!GlobalMemoryStatusEx(&mem))
|
||||
return {};
|
||||
|
||||
return {mem.ullAvailPhys, mem.ullTotalPhys, mem.ullAvailVirtual, mem.ullTotalVirtual};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
// infoware - C++ System information Library
|
||||
//
|
||||
// Written in 2016-2020 by nabijaczleweli <nabijaczleweli@gmail.com> and ThePhD <phdofthehouse@gmail.com>
|
||||
//
|
||||
// To the extent possible under law, the author(s) have dedicated all copyright and related
|
||||
// and neighboring rights to this software to the public domain worldwide. This software is
|
||||
// distributed without any warranty.
|
||||
//
|
||||
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
|
||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
|
||||
#include "infoware/version.hpp"
|
||||
|
||||
|
||||
const char* const iware::version = INFOWARE_VERSION;
|
||||
Reference in New Issue
Block a user