/*
system.cpp
Copyright 2006-2007 John Poole.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "system.h"
#include "basesystem.h"
#include "platform.h"
#include <iomanip>
#include <sstream>
#include <map>
typedef uint64 (BaseSystem::*I)(void) ;
typedef std::string (BaseSystem::*S)(void) ;
struct SystemMeta {
SystemMetricType id;
SystemMetricTypeType type;
std::string name;
I imethod;
S smethod;
};
struct MetricValue {
std::string name;
std::string svalue;
uint64 ivalue;
};
static std::map< SystemMetricType, MetricValue > s_systemInformation;
static bool s_systemInformationInitialized = false;
static SystemMeta s_systemMeta[] = {
{ kSystemMetricPlatform, kSystemMetricTypeString, "Platform", NULL, &BaseSystem::platform },
{ kSystemMetricCompiler, kSystemMetricTypeString, "Compiler", NULL, &BaseSystem::compiler },
{ kSystemMetricOS, kSystemMetricTypeString, "Operating System", NULL, &BaseSystem::os },
{ kSystemMetricModel, kSystemMetricTypeString, "Model", NULL, &BaseSystem::model },
{ kSystemMetricMotherboard, kSystemMetricTypeString, "Motherboard", NULL, &BaseSystem::motherboard },
{ kSystemMetricCPU, kSystemMetricTypeString, "Processor", NULL, &BaseSystem::cpu },
{ kSystemMetricCPUID, kSystemMetricTypeString, "Processor ID", NULL, &BaseSystem::cpuid },
{ kSystemMetricCPULogicalCount, kSystemMetricTypeCount, "Logical Processors", &BaseSystem::cpuLogicalCount, NULL },
{ kSystemMetricCPUPhysicalCount, kSystemMetricTypeCount, "Physical Processors", &BaseSystem::cpuPhysicalCount, NULL },
{ kSystemMetricCPUFrequency, kSystemMetricTypeHertz, "Processor Frequency", &BaseSystem::cpuFrequency, NULL },
{ kSystemMetricCPUL1ICache, kSystemMetricTypeBytes, "L1 Instruction Cache", &BaseSystem::cpuL1ICache, NULL },
{ kSystemMetricCPUL1DCache, kSystemMetricTypeBytes, "L1 Data Cache", &BaseSystem::cpuL1DCache, NULL },
{ kSystemMetricCPUL2Cache, kSystemMetricTypeBytes, "L2 Cache", &BaseSystem::cpuL2Cache, NULL },
{ kSystemMetricCPUL3Cache, kSystemMetricTypeBytes, "L3 Cache", &BaseSystem::cpuL3Cache, NULL },
{ kSystemMetricBusFrequency, kSystemMetricTypeHertz, "Bus Frequency", &BaseSystem::busFrequency, NULL },
{ kSystemMetricMemorySize, kSystemMetricTypeBytes, "Memory", &BaseSystem::memorySize, NULL },
{ kSystemMetricMemoryType, kSystemMetricTypeString, "Memory Type", NULL, &BaseSystem::memoryType },
{ kSystemMetricFreeMemory, kSystemMetricTypeBytes, "Free Memory", &BaseSystem::freeMemory, NULL },
{ kSystemMetricDisplay, kSystemMetricTypeString, "Display", NULL, &BaseSystem::display },
{ kSystemMetricSIMD, kSystemMetricTypeCount, "SIMD", &BaseSystem::simd, NULL },
{ kSystemMetricNone, }
};
static std::string formatMetric( uint64 value, SystemMetricTypeType type )
{
std::ostringstream s;
double divisor;
static char * prefixString[] = { "", "K", "M", "G", "T", "P", "E", "Z", "Y" };
unsigned int prefix;
double result = value;
switch( type ) {
case kSystemMetricTypeCount:
s << value;
break;
default:
switch( type ) {
case kSystemMetricTypeBytes:
divisor = 1024.0;
break;
default:
divisor = 1000.0;
break;
}
for( prefix = 0; prefix < ( sizeof( prefixString ) / sizeof( prefixString[0] ) ); prefix++ ) {
if( result < divisor ) {
break;
}
result /= divisor;
}
s.setf( std::ios::fixed );
if( result > 100.0 ) {
s << std::setprecision( 0 );
} else if( result > 10.0 ) {
s << std::setprecision( 1 );
} else {
s << std::setprecision( 2 );
}
s << result << " " << prefixString[ prefix ];
switch( type ) {
case kSystemMetricTypeHertz:
s << "Hz";
break;
case kSystemMetricTypeBytes:
s << "B";
break;
default:
break;
}
break;
}
return s.str();
}
static void initializeSystemInformation()
{
BaseSystem * baseSystem = systemFactory();
MetricValue value;
for( int i = 0; s_systemMeta[i].id != kSystemMetricNone; i++ ) {
value.name = s_systemMeta[i].name;
switch( s_systemMeta[i].type ) {
case kSystemMetricTypeString:
value.svalue = (baseSystem->*(s_systemMeta[i].smethod))();
value.ivalue = 0;
break;
case kSystemMetricTypeCount:
case kSystemMetricTypeHertz:
case kSystemMetricTypeBytes:
value.ivalue = (baseSystem->*(s_systemMeta[i].imethod))();
value.svalue = formatMetric( value.ivalue, s_systemMeta[i].type );
break;
}
s_systemInformation[ s_systemMeta[i].id ] = value;
}
s_systemInformationInitialized = true;
delete baseSystem;
}
std::string systemMetric( SystemMetricType metric )
{
if( !s_systemInformationInitialized ) {
initializeSystemInformation();
}
return s_systemInformation[ metric ].svalue;
}
uint64 systemMetricInteger( SystemMetricType metric )
{
if( !s_systemInformationInitialized ) {
initializeSystemInformation();
}
return s_systemInformation[ metric ].ivalue;
}
std::string systemMetricName( SystemMetricType metric )
{
if( !s_systemInformationInitialized ) {
initializeSystemInformation();
}
return s_systemInformation[ metric ].name;
}