Converting DriverVersion to Human readable format - c++

I have searched high and low for it, could not find any documentation, I am able to get the DriverVersion as described Here. Creating and enumerating the device drives is working so there is no need to look there. The DriverVersion is a type of "DWORDLONG". I need to convert this to Human readable format like 20.xx.xx.xx. There ain't any documentation on MSDN, or anywhere I have searched.
Any help will be appreciated.
Example value of "DriverVersion" : 1688863374327808
Code snippet, if at all its required,
SP_DEVINFO_DATA devInfo;
devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiEnumDeviceInfo(handle, 0, &devInfo))
{
if(SetupDiBuildDriverInfoList(handle,&devInfo,SPDIT_COMPATDRIVER))
{
SP_DRVINFO_DATA drvInfo;
drvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
int i=0;
while(1)
{
try
{
if (SetupDiEnumDriverInfo(handle, &devInfo, SPDIT_COMPATDRIVER, i++, &drvInfo))
{
cout<<"Version :"<<drvInfo.DriverVersion<<endl; // Need Human Readable version here.
}
else
break;
}
catch(std::exception ex)
{
break;
}
}
}
}

You could use a ULARGE_INTEGER union, the HIWORD/LOWORD macros and string formatting utils like boost::format to do the following (untested code):
SP_DRVINFO_DATA driverInfoData;
ULARGE_INTEGER version;
version.QuadPart = driverInfoData.DriverVersion;
std::string versionStr = (boost::format("%s.%s.%s.%s")
% HIWORD(version.HighPart)
% LOWORD(version.HighPart)
% HIWORD(version.LowPart)
% LOWORD(version.LowPart)).str();
Following your code and to get rid of boost simply do:
std::cout << "Version: "
<< std::to_string(HIWORD(version.HighPart)) << "."
<< std::to_string(LOWORD(version.HighPart)) << "."
<< std::to_string(HIWORD(version.LowPart)) << "."
<< std::to_string(LOWORD(version.LowPart)) << std::endl;

Related

Cant Use Ranges on VkLayerProperties?

I was trying out C++20 ranges while working on my Vulkan project, I decided I wanted to try to check if a layer was available before the client added it in my builder object.
I set up my layer properties vector like so:
//...
vkEnumerateInstanceLayerProperties(&amount_of_layers, nullptr);
std::vector<VkLayerProperties> layer_properties(amount_of_layers);
vkEnumerateInstanceLayerProperties(&amount_of_layers, layer_properties.data());
//...
If I print them out like so, it works just fine:
for(auto& current_properties : layer_properties)
std::cout << current_properties.layerName << "\n";
The problem comes when I tried to use ranges to filter them, this is not the original filter I tried to apply, but this has similar problems:
auto available_layers = layer_properties | std::views::filter(
[&](auto current_layer_properties) {
return std::string{current_layer_properties.layerName}.size() % 2 == 0;
}
);
I just need a count at this point, not to iterate so I just store it in available_layers.
However if I try to print out current_layer_properties.layerName I get the first few layer names, and then what looks like a bunch of data that is from the data segment of the Vulkan library binaries, it looks like JSON.
VK_LAYER_MESA_device_select
VK_LAYER_INTEL_nullhw
VK_LAYER_MESA_overlay
VK_LAYER_LUNARG_monitor
VK_LAYER_KHRONOS_synchronization2
VK_LAYER_LUNARG_api_dump
E_CREATE_NEW",
"label": "Log File Overwrite",
"description": "Specifies that log file initialization should overwrite an existing file when true, or append to an existing file when false.",
"type": "BOOL",
"default": true
}
]
}
]
}
]
}
//...
Same happens if I try to apply std::views::transform and turn layer_properties into a container/view of std::string the same thing happens.
Sometimes depending on my filter (I use a find to find a string in it, then omit the element if its not found) it goes on forever.
Am I doing something wrong with ranges? Or does this have something to do with Vulkan?
Does it have something to do with some sort of side effect these LunarG .gfxr/gfxrecon_capture log files I am seeing(the erroneous output looks related, but could be totally random)?
UPDATE[ 0 ]:
Someone in the comments requested I show how I print things, it has changed as I have debugged, but I will put it here (it also crashes without printing)
In the lambda for std::filter and/or std::transform I have put variations of the following:
std::cout << current_layer_properties.layerName << "\n";
std::cout << current_layer_properties << "\n"; //When I apply std::transform and turn it into a std::string or std::string_view
log<LogType::Debug>(std::cout, current_layer_properties);
Here is my log function
template<typename LogParameterType>
void log(
LogParameterType& log,
const std::string_view message,
const std::source_location location =
std::source_location::current()
)
{
if constexpr(DebugParameterConstant == true
&& LogParameterConstant == LogType::Debug)
return;
log << to_string(LogParameterConstant) << "::"
<< location.file_name() << "("
<< location.line() << ":"
<< location.column() << ")::"
<< location.function_name() << ": "
<< message << "\n";
}
My debug layer is not working but here is the function it is suppose to run:
//If anyone can think of a better way to do this please let me know :)
void vulkan_log(
VkDebugUtilsMessageSeverityFlagBitsEXT vulkan_log_type,
VkDebugUtilsMessageTypeFlagsEXT message_type,
const VkDebugUtilsMessengerCallbackDataEXT* callback_data
)
{
LogType log_type = LogType::Unkown;
std::string message_type_string = to_string(message_type);
switch(vulkan_log_type)
{
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
{
std::cerr << message_type_string;
log<LogType::Diagnostic>(std::cerr, callback_data->pMessage);
break;
}
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
{
std::cerr << message_type_string;
log<LogType::Error>(std::cerr, callback_data->pMessage);
break;
}
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
{
std::cerr << message_type_string;
log<LogType::Warning>(std::cerr, callback_data->pMessage);
break;
}
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
{
std::cout << message_type_string;
log<LogType::Note>(std::cout, callback_data->pMessage);
break;
}
default:
break;
}
}
Thanks!
TFB

Tesseract - getting alternative results with confidence level

I'm trying to use tesseract to recognize numbers. It works pretty well but sometimes I get wrong results (8 instead of 9 etc). I know how to improve accuracy with some non-ocr methods but I need other results with confidence levels. I found out that I get the best choices using a ChoiceIterator for each ResultIterator:
tesseract::TessBaseAPI tess;
tess.SetPageSegMode(tesseract::PSM_SINGLE_CHAR);
tess.SetVariable("save_best_choices", "T");
[setting input image here]
tess.Recognize(NULL);
tesseract::ResultIterator* ri = tess.GetIterator();
tesseract::ChoiceIterator* ci;
if(ri != 0)
{
char* symbol = ri->GetUTF8Text(tesseract::RIL_SYMBOL);
if(symbol != 0)
{
float conf = ri->Confidence(tesseract::RIL_SYMBOL);
cout << symbol << "\tconf: " << conf << "\n";
const tesseract::ResultIterator itr = *ri;
ci = new tesseract::ChoiceIterator(itr);
do {
const char* choice = ci->GetUTF8Text();
if (choice) {
std::cout << "\t" << choice << " conf: " << ci->Confidence() << "\n";
}
} while(ci->Next());
// delete[] symbol;
}
}
But the problem is that ci->GetUTF8Text() always returns a null pointer.
I'm using tesseract 3.02 as DLL, compiled under MSVC2010 express.
From limited research earlier today, I think the answer might be setting the variable SaveBlobChoices versus SaveBestChoices. I still need to test this myself.

Has anyone been able to use libsensors properly?

Long story short I am trying to write an application that can check cpu temperatures. Using the libsensors(3) man pages I've been able to at least get the libsensors_version number. As of now, here is my code:
#include <sensors/sensors.h>
#include "SensorData.h"
#include <string>
#include <sstream>
using namespace std;
SensorData::SensorData()
{
sensors_init(NULL);
}
SensorData::~SensorData()
{
sensors_cleanup();
}
string SensorData::GetVersion()
{
ostringstream Converter;
Converter<<"Version: "<<libsensors_version;
return Converter.str();
}
void SensorData::FetchTemp()
{
//sensors_get_value()
}
With the man pages I know that sensors_get_value expects
const sensors_chip_name *name
int subfeat_nr
double *value
to be passed to it. The problem is I have no idea what those are exactly. Just about every function in the documentation has this problem. They all expect vague things I don't know how to supply.
So here is the bulk of the question: Does anyone have any working examples of this library I could look at? Or at the very least does anyone know how to give these functions the values they need?
EDIT:
Since no one seems to know much about this library, does anyone know of a different way to get temperatures?
You can find out how to use the API by browsing the source code. The code for the sensors program isn't too complex to follow.
To get you started, here's a quick function that:
enumerates all the chips
enumerates all their features
prints the values of their readable subfeatures
You can just add it to your existing skeleton class as-is.
(This code is for demo purposes only, not tested thoroughly at all.)
void SensorData::FetchTemp()
{
sensors_chip_name const * cn;
int c = 0;
while ((cn = sensors_get_detected_chips(0, &c)) != 0) {
std::cout << "Chip: " << cn->prefix << "/" << cn->path << std::endl;
sensors_feature const *feat;
int f = 0;
while ((feat = sensors_get_features(cn, &f)) != 0) {
std::cout << f << ": " << feat->name << std::endl;
sensors_subfeature const *subf;
int s = 0;
while ((subf = sensors_get_all_subfeatures(cn, feat, &s)) != 0) {
std::cout << f << ":" << s << ":" << subf->name
<< "/" << subf->number << " = ";
double val;
if (subf->flags & SENSORS_MODE_R) {
int rc = sensors_get_value(cn, subf->number, &val);
if (rc < 0) {
std::cout << "err: " << rc;
} else {
std::cout << val;
}
}
std::cout << std::endl;
}
}
}
}
The Gnome panel Sensors applet works with libsensors (and other backends); the full sources are available from Sourceforge, here: http://sensors-applet.sourceforge.net/index.php?content=source
… in particular, the libsensors plug-in looks fairly legible… I believe this should be a usable gitweb link straight to that code: http://sensors-applet.git.sourceforge.net/git/gitweb.cgi?p=sensors-applet/sensors-applet;a=blob;f=plugins/libsensors/libsensors-plugin.c;h=960c19f4c36902dee4e20b690f2e3dfe6c715279;hb=HEAD
Your code should looks like this:
/* Read /etc/sensors.d to get the names or use code in above post */
std::string chip_name = "CHIP_NAME-*";
/* Here you get the path to the chip you want to read */
int rc;
sensors_chip_name name;
rc = sensors_parse_chip_name(chip_name.c_str(), &name);
/* Check rc != 0 */
/* Here you get the internal structure */
int nr = 0; //Here I silently assume you have only one chip to read
const sensors_chip_name* p_chip;
p_chip = sensors_get_detected_chips(&name, &nr);
/* Check p_chip != 0 */
/* Now you read the value - this you can repeat in some for/while cycle */
double val;
/* Replace the "1" with the feature you want to read */
rc = sensors_get_value(p_chip, 1, &val);
std::cout << "Now I can use sensors library " << val << std::endl;
Hope it helps despite the fact it is not copy/paste solution.
You can obtain the const sensors_chip_name* p_chip; from the code above post as well.
I believe the problem is in fact the const sensors_chip_name MUST be returned and filled by sensors library.

how to get a value from a char[]

however,thanks everyone who help me.
I want to get the VmRSS value from /proc/pid/status,below is the code
int main()
{
const int PROCESS_MEMORY_FILE_LEN = 500;
FILE *file;
std::string path("/proc/4378/status");
//path += boost::lexical_cast<std::string>( pid );
//path += "/status";
if(!(file = fopen(path.c_str(),"r")))
{
std::cout <<"open " << path<<"is failed " << std::endl;
return float(-1);
}
char fileBuffer[PROCESS_MEMORY_FILE_LEN];
memset(fileBuffer, 0, PROCESS_MEMORY_FILE_LEN);
if(fread(fileBuffer, 1, PROCESS_MEMORY_FILE_LEN - 1, file) != (PROCESS_MEMORY_FILE_LEN - 1))
{
std::cout <<"fread /proc/pid/status is failed"<< std::endl;
return float(-1);
}
fclose(file);
unsigned long long memoryUsage = 0;
int a = sscanf(fileBuffer,"VmRSS: %llu", &memoryUsage);
std::cout << a << std::endl;
std::cout << memoryUsage << std::endl;
}
at last,thanks
Based on your comments: To find VmRSS within your char array use C++ algorithms in combination with the C++ string library. Then you'll get the position of VmRSS and all you'll have to do is to retrieve the wanted result. With a little knowledge of the structure of these entries, this should be an easy task.
In addition to that it might be better to use fstream for reading directly into a string.

Unexplained out_of_range in string::substr

I have been getting a really annoying error about an std::out_of_range when calling substr. The exact error is
terminate called after throwing an
instance of 'std::out_of_range'
what(): basic_string::substr
I'm absolutely sure that tmp_request has a length greater then 1. No matter what I pass to substr—1, 2, or bodypos—it always throws that error. I'm using g++ on Unix.
Only interesting thing I can include is the string has multiple "\r\n", including one "\r\n\r\n".
In one cpp file:
std::string tmp_request, outRequest;
tmp_request = SS_Twitter->readData();
outRequest = SS_Twitter->parse(tmp_request);
In another:
std::string parse(const std::string &request)
{
std::map<std::string,std::string> keyval;
std::string outRequest;
if(request[0]=='P')
{
if(request.find("register")!=std::string::npos)
{ //we have a register request
size_t bodypos = request.find("username");
if(bodypos==std::string::npos)
{
HttpError(400,"Malformed HTTP POST request. Could not find key username.",request);
}
else
{
std::string body = request.substr(bodypos);
StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
}
}
Update:
std::string request2("P\r\nregister\r\nusername=hello\r\n\r\n");
std::string body = request2.substr(4);
That throws the same error. Now I know this is perfectly valid and correct code, but it's still throwing the error.
//removed source link
I modified your sample slightly to decrease amount of indentation used.
There are 5 "test cases" and none causes any problem. Could you please provide a sample request to reproduce the problem you're having.
EDIT: Forgot to mention: if this sample as it is (with commented-out bits) doesn't produce that error, your best bet is that you have a bug in your StringExplode function. You could post its source, to get a more helpful advice.
EDIT2:
In your StringExplode, change results[tmpKey] = tmpKey.substr(found+1); to results[tmpKey] = tmpResult[i].substr(found+1);. Change int found to size_t found, and remove all of if (found > 0), that will fix your mysterious out_of_range. You were substr-ing a wrong string. Just in case, here's the code with a fix:
void StringExplode(std::string str, std::string objseparator, std::string keyseperator,
std::map <std::string, std::string> &results)
{
size_t found;
std::vector<std::string> tmpResult;
found = str.find_first_of(objseparator);
while(found != std::string::npos)
{
tmpResult.push_back(str.substr(0,found));
str = str.substr(found+1);
found = str.find_first_of(objseparator);
}
if(str.length() > 0)
{
tmpResult.push_back(str);
}
for(size_t i = 0; i < tmpResult.size(); i++)
{
found = tmpResult[i].find_first_of(keyseperator);
while(found != std::string::npos)
{
std::string tmpKey = tmpResult[i].substr(0, found);
results[tmpKey] = tmpResult[i].substr(found+1);
found = tmpResult[i].find_first_of(keyseperator, found + results[tmpKey].size());
}
}
}
Initial test code:
#include <iostream>
#include <map>
#include <string>
std::string parse(const std::string &request)
{
std::map<std::string,std::string> keyval;
std::string outRequest;
if(request[0] != 'P')
return outRequest;
if(request.find("register") == std::string::npos)
return outRequest;
//we have a register request
size_t bodypos = request.find("username");
if(bodypos==std::string::npos)
{
// HttpError(400,"Malformed HTTP POST request. Could not find key username.",request);
// you said HttpError returns, so here's a return
return outRequest;
}
std::string body = request.substr(bodypos);
// StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
return outRequest;
}
int main()
{
std::string request("P\r\nregister\r\nusername=hello\r\n\r\n");
std::cout << "[" << parse(request) << "]\n";
request = "Pregisternusername=hello\r\n\r\n";
std::cout << "[" << parse(request) << "]\n";
request = "Pregisternusername=hello";
std::cout << "[" << parse(request) << "]\n";
request = "registernusername=hello";
std::cout << "[" << parse(request) << "]\n";
request = "";
std::cout << "[" << parse(request) << "]\n";
return 0;
}
This outputs, predictably:
[doing stuff]
[doing stuff]
[doing stuff]
[]
[]
Are you sure that it's failing on that substr and not on a substr call within the HttpError or StringExplode functions? If you haven't already, you should run this through a debugger so that you can see exactly where it's throwing the exception. Alternatively, you could add a:
std::cout << "calling substr" << std::endl;
line immediately before you call substr, and a similar line immediately afterwards, so that it would look like:
std::cout << "calling substr" << std::endl;
std::string body = request.substr(bodypos);
std::cout << "finished calling substr" << std::endl;
StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
If that substr really is throwing the exception, then you'll know because the program will print "calling substr" without a matching "finished calling substr". If it prints the pair of debug messages, though, or none at all, then something else is throwing the exception.
One fairly obvious thing wrong with your code:
int k = read(ns, buf, sizeof(buf)-1);
buf[k] = '\0';
You are not checking that read() succeeded - it returns -1 on failure which will cause all sorts of memory corruption problems if it occurs.
Also:
char * buf2 = const_cast<char *>(reply.c_str());
write(ns,buf2,sizeof(buf2));
You are taking the size of the pointer - you want the length of the output string:
write(ns, buf2, reply.size() );
And you should once again test that write succeeded and that it wrote as many bytes as you requested, though this shouldn't directly cause the substr() error.
Looks like you need an else after
if(bodypos==std::string::npos)
{
HttpError(...);
}
otherwise you are calling substr with bodypos = npos
You might consider using the (unsigned) type std::string::size_type instead of int.
Why are you casting the result of find to an int here:
int(request.find("register"))!=std::string::npos