D Lang: std.bitmanip read data into struct - d

I found this function: https://dlang.org/phobos/std_bitmanip.html#.read
T read(T, Endian endianness = Endian.bigEndian, R)(ref R range)
if (canSwapEndianness!T && isInputRange!R && is(ElementType!R : const(ubyte)));
But I can't understand how to make reading from data into structure.
Is it possible to use something like this?
struct MyType {
uint value;
this(ubyte act) { // wtf.peek!ubyte();
switch (act) {
case 0:
value = wtf.read!uint();
break;
case 1:
wtf.read!ubyte(); // seek
value = wtf.read!uint() | 0x7;
break;
...
}
}
}
...
buffer.read!MyType();

I don't fully understand the structure of your code - where does wtf come from?
It seems to me you've misunderstood what to pass to MyType's constructor - you probably should pass it the range, and read off of that with std.bitmanip.read. I might have misunderstood your code, though:
import std.range;
import std.bitmanip;
struct MyType {
uint value;
this(R)(auto ref R rng) if (isInputRange!R && is(ElementType!R : const(ubyte)))
{
auto act = rng.peek!ubyte;
switch (act) {
case 0:
value = rng.read!uint;
break;
case 1:
rng.read!ubyte;
value = rng.read!uint;
break;
// ...
default: assert(0);
}
}
}
unittest {
ubyte[] buffer = [0x01,0x12,0x34,0x56,0x78];
auto a = MyType(buffer);
assert(buffer.length == 0);
assert(a.value == 0x12345678);
}
As you can see, I simply call MyType's constructor with the array as parameter, but you could also wrap it in a read function if you really want to:
alias read = std.bitmanip.read;
T read(T : MyType, R)(auto ref R range)
if (isInputRange!R && is(ElementType!R : const(ubyte)))
{
return MyType(range);
}
unittest {
ubyte[] buffer = [0x01,0x12,0x34,0x56,0x78];
auto a = buffer.read!MyType;
assert(buffer.length == 0);
assert(a.value == 0x12345678);
}

Related

Recursive symbol checking

I am getting an error that I am having problems fixing as recursion hasn't "sunk in" yet.
It is supposed to go through an array of symbols already placed by the Class OrderManager Object and check if the symbol passed in is already there or not, if it is not there it should allow the trade, otherwise it will block it (multiple orders on the same currency compounds risk)
[Error] '}' - not all control paths return a value.
I believe it is because of the retest portion not having a return value but again I'm still newish to making my own recursive functions. However it may also be because my base and test cases are wrong possibly?
P.S I added (SE) comments in places to clarify language specific things since it is so close to C++.
P.P.S Due to the compiler error, I have no clue if this meets MVRC. Sorry everyone.
bool OrderManager::Check_Risk(const string symbol, uint iter = 0) {
if((iter + 1) != ArraySize(m_symbols) &&
m_trade_restrict != LEVEL_LOW) // Index is one less than Size (SE if
// m_trade_restrict is set to LOW, it
// allows all trades so just break out)
{
if(OrderSelect(OrderManager::Get(m_orders[iter]),
SELECT_BY_TICKET)) // Check the current iterator position
// order (SE OrderSelect() sets an
// external variable in the terminal,
// sort of like an environment var)
{
string t_base = SymbolInfoString(
OrderSymbol(),
SYMBOL_CURRENCY_BASE); // Test base (SE function pulls apart
// the Symbol into two strings
// representing the currency to check
// against)
string t_profit =
SymbolInfoString(OrderSymbol(), SYMBOL_CURRENCY_PROFIT);
string c_base =
SymbolInfoString(symbol, SYMBOL_CURRENCY_BASE); // Current base
// (SE does the same as above but for the passed variable instead):
string c_profit = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT);
// Uses ENUM_LEVELS from Helpers.mqh (SE ENUM of 5 levels: Strict,
// High, Normal, Low, None in that order):
switch(m_trade_restrict) {
case LEVEL_STRICT: {
if(t_base == c_base || t_profit == c_profit) {
return false; // Restrictions won't allow doubling
// orders on any currency
} else
return Check_Risk(symbol, iter++);
};
case LEVEL_NORMAL: {
if(symbol == OrderSymbol()) {
return false; // Restrictions won't allow doubling
// orders on that curr pair
} else
return Check_Risk(symbol, iter++);
};
default: {
// TODO: Logging Manager
// Hardcoded constant global (SE set to LEVEL_NORMAL):
ENB_Trade_Restrictions(default_level);
return Check_Risk(symbol, iter);
}
}
}
} else {
return true;
}
}
So, I must just have been staring at the code for too long but the problem was the if(OrderSelect(...)) on ln 7 did not have a return case if the order was not properly set in the terminal. I will need to polish this but the following code removes the error.
bool OrderManager::Check_Risk(const string symbol, uint iter=0)
{
if((iter + 1) != ArraySize(m_symbols) && m_trade_restrict != LEVEL_LOW) // Index is one less than Size
{
if(OrderSelect(OrderManager::Get(m_orders[iter]), SELECT_BY_TICKET)) //Check the current iterator position order
{
string t_base = SymbolInfoString(OrderSymbol(), SYMBOL_CURRENCY_BASE); //Test base
string t_profit = SymbolInfoString(OrderSymbol(), SYMBOL_CURRENCY_PROFIT);
string c_base = SymbolInfoString(symbol, SYMBOL_CURRENCY_BASE); //Current base
string c_profit = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT);
switch(m_trade_restrict) // Uses ENUM_LEVELS from Helpers.mqh
{
case LEVEL_STRICT :
{
if(t_base == c_base || t_profit == c_profit)
{
return false;
}
else return Check_Risk(symbol, ++iter);
};
case LEVEL_NORMAL :
{
if(symbol == OrderSymbol())
{
return false;
}
else return Check_Risk(symbol, ++iter);
};
default: {
// TODO: Logging Messages
ENB_Trade_Restrictions(default_level); //Hardcoded constant global
return Check_Risk(symbol, iter);
}
}
}
else {return Check_Risk(symbol, ++iter);}
}
else {return true;}
}

Point to a struct member?

I have the following typedefined struct:
typedef struct
{
uint8_t u8Byte1; // This byte takes the needed values sometimes
uint8_t u8Byte2; // Not used
uint8_t u8Byte3; // This byte takes the needed values the other times
uint8_t u8Byte4; // Not used
} tstrMapMetadata;
And I have a thread that fills (with data from a sensor) this struct and uses one of its values:
while(true)
{
tstrMapMetadata * pstrMapMetadata = something();
if(pstrMapMetadata->u8Byte1 == SOMETHING) //<---- this line
{
//Do something special
}
}
But now I have a condition (constant during the thread) in which I want the comparison of the marked line done with u8Byte3 instead of u8Byte1.
Of course I could
if(((condition) ? pstrMapMetadata->u8Byte1 : pstrMapMetadata->u8Byte3) == SOMETHING) //<---- this line
But the I would be doing the same comparison all the time.
Is there a way to point to one of the members (are they called like this?) of the struct before its declaration?
Something like (this code of course doesn't work but gives an idea of what I'm looking for):
uint8_t * coolPointer;
if(condition)
{
coolPointer = (someOperation)tstrMapMetadata(u8Byte1);
}
else
{
coolPointer = (someOperation)tstrMapMetadata(u8Byte3);
}
while(true)
{
tstrMapMetadata * pstrMapMetadata = something();
if(coolPointer == SOMETHING) //<---- this line
{
//Do something special
}
}
Thanks!
There is pointer to member:
uint8_t tstrMapMetadata::*member = condition ?
&tstrMapMetadata::u8Byte1 :
&tstrMapMetadata::u8Byte3;
while (true)
{
tstrMapMetadata* pstrMapMetadata = something();
if (pstrMapMetadata->*member == SOMETHING) // usage with ->* ( .* for objet )
{
//Do something special
}
}

C Mysql driver in C++: Fetch field only (function returns mixed type)

I'm trying to implement fetching data function from mysql just for one field instead whole row.
auto FetchField(char *value, MYSQL_FIELD *field) {
if (value == NULL) {
return nullptr;
}
switch(field->type) {
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
return atof(value);
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_INT24:
return atoi(value);
default:
return value;
}
}
And usage function:
auto QueryField(MYSQL *db, const char *query, ...) {
va_list params;
va_start(params, query);
StmtExec(db, query, params); // this calls mysql_query with params
va_end(params);
MYSQL_RES *res = mysql_store_result(db);
MYSQL_ROW row = mysql_fetch_row(res);
return FetchField(row[0], mysql_fetch_field(res));
}
So it shows error: deduced return type "double" conflicts with previously deduced type "std::nullptr_t"
I'd like avoid using mysql_fetch_row but how can I do it in other way? Just fetch one field instead of whole row.
I'd like my function will return automatic type or something like that (I know C++ has strict typing but maybe there's some way to implement it). Because now I'm doing there same (without defining datatype structs schema explicitly using nlohmann::json container).
nlohmann::json FetchRow(MYSQL_RES *res) {
int fields_count = mysql_num_fields(res);
MYSQL_ROW row = mysql_fetch_row(res);
nlohmann::json row_json;
mysql_field_seek(res, 0);
for(int j=0; j<fields_count; j++)
{
MYSQL_FIELD *field = mysql_fetch_field(res);
if (row[j] == NULL) {
row_json[field->name] = nullptr;
continue;
}
switch(field->type) {
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
row_json[field->name] = atof(row[j]);
break;
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_INT24:
row_json[field->name] = atoi(row[j]);
break;
default:
row_json[field->name] = row[j];
break;
}
}
return row_json;
}
So I'd like to also reuse this method from FetchRow method as well if that's possible.
The point why I use C driver instead of C++ because I simply don't need to use classes and OOP in my project.
Is there any other way to implement what I want?
Thanks

Refactoring switch or if/else statement? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
i'm working on a school project and got some feedback from my teacher. He said that in my code there are some bad practices, he said that the switch cases could be replaced by a polymorphic approach. Only i have no clue how i could do this.
My code is receiving messages from a CAN bus. Those messages come from different devices, I check the messages from which device they come from. If there is a new device I create a object and parse the message and store the information.
This system is pretty much the same for each message.
Here is my code.
void Application::PollWhisperConnectBus()
{
HAL_GPIO_TogglePin(PORT_LED1, PIN_LED1);
whisper_connect_id_ = hcan2.pRxMsg->StdId;
if (whisper_connect_id_ >= 0x580 && whisper_connect_id_ <= 0x58F)
{
WIBDevice();
}
if (whisper_connect_id_ >= 0x590 && whisper_connect_id_ <= 0x59F)
{
BMSSDevice();
}
if (whisper_connect_id_ >= 0x5B0 && whisper_connect_id_ <= 0x5BF)
{
DCPowerCubeDevice();
}
if (whisper_connect_id_ >= 0x5C0 && whisper_connect_id_ <= 0x5CF)
{
ACPowerCubeDevice();
}
if (whisper_connect_id_ >= 0x700 && whisper_connect_id_ <= 0x70F)
{
WIBHeartBeatDevice();
}
}
This is one of the functions which checked if there is an object of the class, if so parse the message.
void Application::DCPowerCubeDevice()
{
bool found_device = false;
int device = (hcan2.pRxMsg->StdId & 0x0F) + device_instance_offset_;
WhisperConnectDevice* whisper_connect_device;
for(unsigned int i = 0; i < whisper_connect_device_list_.size(); ++i)
{
if ((whisper_connect_device = whisper_connect_device_list_.at(i)) != NULL &&
whisper_connect_device->GetClassName() == "DCPowerCube")
{
DCPowerCube* dc_powercube = dynamic_cast<DCPowerCube*>(whisper_connect_device);
if (dc_powercube != NULL)
{
if (dc_powercube->GetDevice() == device)
{
dc_powercube->ParseCanMessage(&hcan2);
found_device = true;
break;
}
}
}
}
if (!found_device)
{
WhisperConnectDevice* dc_powercube;
if ((dc_powercube = new DCPowerCube) != NULL)
{
dc_powercube->SetDevice(device);
int n2k_address = nmea2000_.FindFirstFreeCanId(n2k_address_, device_list_);
if (n2k_address != 0xFFFF)
{
dc_powercube->SetSrcCanId(n2k_address);
dc_powercube->SetDeviceInstanceOffset(device_instance_offset_);
dc_powercube->SetDeviceInstance(0x30 + device);
dc_powercube->AddressClaim(nmea2000_);
dc_powercube->SendPGN126996(nmea2000_);
dc_powercube->SendPGN126998(nmea2000_, "DCPowerCube", "", "");
device_list_.at(n2k_address) = 0x01;
}
DCPowerCube* dc_powercube2 = dynamic_cast<DCPowerCube*>(dc_powercube);
if (dc_powercube2 != NULL)
{
dc_powercube2->SetCurrentLimit(16);
}
AddToWPCDeviceList(dc_powercube);
}
}
}
void DCPowerCube::ParseCanMessage(CAN_HandleTypeDef *can_handle)
{
if (can_handle != NULL)
{
uint16_t message_index = (can_handle->pRxMsg->Data[1] << 8) + can_handle->pRxMsg->Data[2];
switch (message_index)
{
case 0x1008:
device_name_[0] = can_handle->pRxMsg->Data[4];
device_name_[1] = can_handle->pRxMsg->Data[5];
device_name_[2] = can_handle->pRxMsg->Data[6];
device_name_[3] = can_handle->pRxMsg->Data[7];
device_name_[4] = '\0';
break;
case 0x100A:
software_version_[0] = can_handle->pRxMsg->Data[4];
software_version_[1] = can_handle->pRxMsg->Data[5];
software_version_[2] = can_handle->pRxMsg->Data[6];
software_version_[3] = can_handle->pRxMsg->Data[7];
software_version_[4] = '\0';
break;
case 0x1018:
serial_number_ = can_handle->pRxMsg->Data[4] << 24 | can_handle->pRxMsg->Data[5] << 16 |
can_handle->pRxMsg->Data[6] << 8 | can_handle->pRxMsg->Data[7];
break;
case 0x2100: // DC PowerCube status
power_cube_status_ = can_handle->pRxMsg->Data[4];
io_status_bit_ = can_handle->pRxMsg->Data[5];
dip_switch_status_bit_ = can_handle->pRxMsg->Data[6];
break;
case 0x2111: // Grid voltage, current, current limit
grid_voltage_ = (can_handle->pRxMsg->Data[4] << 8) + can_handle->pRxMsg->Data[5];
grid_current_ = can_handle->pRxMsg->Data[6];
grid_current_limit_ = can_handle->pRxMsg->Data[7];
break;
case 0x2112: // Generator frequency, RPM
generator_freq_ = (can_handle->pRxMsg->Data[4] << 8) + can_handle->pRxMsg->Data[5];
rpm_ = (can_handle->pRxMsg->Data[6] << 8) + can_handle->pRxMsg->Data[7];
break;
case 0x2113: // Generator current
gen_current_phase1_ = can_handle->pRxMsg->Data[4];
gen_current_phase2_ = can_handle->pRxMsg->Data[5];
gen_current_phase3_ = can_handle->pRxMsg->Data[6];
gen_current_limit_ = can_handle->pRxMsg->Data[7];
break;
case 0x2114: // Load percentage
grid_load_ = can_handle->pRxMsg->Data[4];
generator_load_ = can_handle->pRxMsg->Data[5];
dc_output_load_ = can_handle->pRxMsg->Data[6];
break;
case 0x2151: // Battery type & charger state
battery_type_ = can_handle->pRxMsg->Data[4];
charger_state_ = can_handle->pRxMsg->Data[5];
break;
case 0x2152: // DC output voltage & DC slave voltage
dc_output_voltage_ = (can_handle->pRxMsg->Data[4] << 8) + can_handle->pRxMsg->Data[5];
dc_slave_voltage_ = (can_handle->pRxMsg->Data[6] << 8) + can_handle->pRxMsg->Data[7];
break;
case 0x2153: // DC output current & DC output current limit
dc_output_current_ = (can_handle->pRxMsg->Data[4] << 8) + can_handle->pRxMsg->Data[5];
dc_output_current_limit_ = (can_handle->pRxMsg->Data[6] << 8) + can_handle->pRxMsg->Data[7];
break;
case 0x21A0: // Temperature sensor
temp_sens_BTS_ = can_handle->pRxMsg->Data[4];
temp_sens_intern1_ = can_handle->pRxMsg->Data[5];
temp_sens_intern2_ = can_handle->pRxMsg->Data[6];
temp_sens_intern3_ = can_handle->pRxMsg->Data[7];
break;
case 0x21A1:
break;
}
}
}
The WhisperConnectDevice is the base class of DCPowerCube.
I would love to get some feedback on how to approach this problem.
Whether or not you introduce polymorphism it appears you have to map an externally provided type number (ID) to code so you will always need some structure inbetween.
Your candidates are:
A block of if statements probably if-else-if...
A switch statement (if values are ameanable)
Some kind of look-up table (array, associative map, other...)
You've already got if but could improve with if-else-if.
That is normally considered the ugliest high-maintenance potential coding hot-spot approach. Coding hot-spot because all new IDs return to this code block.
I also notice in this case all your ranges are 0xnn0 to 0xnnF inclusive for some nn so you can at least simplify by reducing out the low 4 bits:
auto whisper_connect_type = whisper_connect_id_ >> 4;
Your switch option is then simplified to:
switch(whisper_connect_type) {
case 0x58: WIBDevice(); break;
case 0x59: BMSSDevice(); break;
case 0x5B: DCPowerCubeDevice(); break;
case 0x5C: ACPowerCubeDevice(); break;
case 0x70: WIBHeartBeatDevice(); break;
default: HandleUnknownDeviceIDError(whisper_connect_id_); break;
}
NB: I very strongly recommend some code to handle an unsupported ID. My advice is throwing an exception or something leading to termination. The break; is for completeness. I don't think you're coming back from an unknown ID.
An alternative is to define an associative map:
#include <iostream>
#include <unordered_map>
#include <memory>
class WhisperHandler {
public:
virtual void HandleWhisper() const = 0 ;
virtual ~WhisperHandler() {}
};
class WhisperHandlerWIBDevice : public WhisperHandler {
public:
void HandleWhisper() const override {
std::cout << "Handler WIBDevice...\n";
}
} ;
int main() {
std::unordered_map<unsigned,std::unique_ptr<const WhisperHandler>> handlers;
//...
std::unique_ptr<const WhisperHandler> handler(std::make_unique<const WhisperHandlerWIBDevice>());
std::pair<const unsigned , std::unique_ptr<const WhisperHandler> > pair({0x5B,std::move(handler)});
handlers.insert(std::move(pair));
//...
{
const auto &chandlers=handlers;
auto handlerit(chandlers.find(0x5B1));
if(handlerit!=chandlers.end()){
handlerit->second->HandleWhisper();
}else{
//ERROR - UNKNOWN HANDLER.
}
}
return 0;
}
I would suggest however you're only going to get return on investment for all this polymorphic machinery if you're going to allow the registration of handlers dynamically either from different modules of the application or by dynamically loading libraries that register themselves on load.
If it's a single project application (which it appears to be) then the switch table dispatch will probably work fine.
Because applications tend to communicate using IDs of some kind OO can start to look cumbersome when it in practice it needs to take an ID, map it to a polymorphic handler and then call the handler. Logically you've done the ID to logic mapping twice!
Footnote: The trick of knocking out the lowest 4-bits is somewhat separate from these methods and (of course) slightly fragile if the lower 4 bits become relevant to determining the handler down the line.

What is the most efficient logic to check for all possible combinations of three flags?

I have three flags which may be True or False. I need to display an icon for each possible combination of flags. Since there are three flags that means, in combination, there are eight possible states. (Shown below, where bold represents true.)
A B C
A B C
A B C
A B C
A B C
A B C
A B C
A B C
Is there an advantageous control flow to use in checking the flags to minimize unnecessary checking? (Would this vary by which flags are likely to be on or off?)
Edit:
For example, when I was looking at simply flags A and B, my control flow was -
if(A & B)
{
// Display icon for A+B
}
else if (A)
{
// Display icon for A
}
else if (B)
{
// Display icon for B
}
I would set up an 8 bit variable, allowing bits 2,1,0 to store your flag states.
Then
switch(variablename)
{
case 0:
break;
..
..
case 7:
break;
}
protected void grdDemo_ItemDataBound(object sender, GridItemEventArgs e)
{
if (!(e.Item is GridDataItem) || (e.Item.DataItem == null))
{
return;
}
///////////////////
//// Solution 1 ///
///////////////////
// If it is possible to manipulate image name
MyClass M1 = e.Item.DataItem as MyClass;
ImageButton imgStatus = (ImageButton)e.Item.FindControl("imgStatus");
StringBuilder sb = new StringBuilder();
sb.Append(M1.A ? "1" : "0");
sb.Append(M1.B ? "1" : "0");
sb.Append(M1.C ? "1" : "0");
string ImageName = "imgStaus" + sb.ToString() + ".jpg";
imgStatus.ImageUrl = "~/path/" + ImageName;
///////////////////
//// Solution 2 ///
///////////////////
ImageName = string.Empty;
double FlagCount = 0;
FlagCount += Math.Pow((M1.A ? 0 : 1) * 2, 3);
FlagCount += Math.Pow((M1.B ? 0 : 1) * 2, 2);
FlagCount += Math.Pow((M1.B ? 0 : 1) * 2, 1);
var intFlagCount = (int)FlagCount;
switch (intFlagCount)
{
case 0:
ImageName = "imgStausFFF.jpg";
break;
case 1:
ImageName = "imgStausFFT.jpg";
break;
case 2:
ImageName = "imgStausFTF.jpg";
break;
case 3:
ImageName = "imgStausFTT.jpg";
break;
case 4:
ImageName = "imgStausTFF.jpg";
break;
case 5:
ImageName = "imgStausTFT.jpg";
break;
case 6:
ImageName = "imgStausTTF.jpg";
break;
case 7:
ImageName = "imgStausTTT.jpg";
break;
}
imgStatus.ImageUrl = "~/path/" + ImageName;
//////DONE!!!!!!!!!!
}
class MyClass
{
public bool A { get; set; }
public bool B { get; set; }
public bool C { get; set; }
}