Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"Indirect" Addressing

37 views
Skip to first unread message

Mike Copeland

unread,
Mar 8, 2017, 4:10:13 PM3/8/17
to
I have a fair amount of code to search for matches on constants and
assign "offset values" of the constants' position in an array. The code
is tedious and slow, and making changes to add new constants is
difficult.
In some other languages I've used there there's a way to assign an
"address value" that's coded in a table, so that a loop can be used to
scan for matches and assign a value to an associated variable whose
address is in the table. Something like:

{"NO.", &BNoffset, "BIB", &BNoffset, "PLACE", &OPoffset, etc. }

Is such a thing available in C++? If so, how is it coded and used?
TIA

// sample of current code:
int DPoffset, BNoffset, OPoffset, FNoffset;
[...]
DPoffset = BNoffset = OPoffset = FNoffset = -1;// defaults
[...]
string ws1; // data variable
size_t jj = tArray.size();
for(int kk = 0; kk < jj; kk++)
{
ws1 = tArray[kk];
if(ws1 == "NO.") BNoffset = kk;
if(ws1 == "BIB") BNoffset = kk;
if(ws1 == "PLACE") OPoffset = kk;
if(ws1 == "OPLACE") OPoffset = kk;
if(ws1 == "OVERALL_RANK") OPoffset = kk;
if(ws1 == "TEAMPLACE") OPoffset = kk;
if(ws1 == "FIRST NAME") FNoffset = kk;
[etc.]
}



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

Alf P. Steinbach

unread,
Mar 8, 2017, 4:33:25 PM3/8/17
to
It seems that for BNoffset you want it to get the index of the last
occurrence of "NO." or "BIB" in the array.

Is this correct, and if so, what do you use that for?


Cheers!,

- Alf


Mike Copeland

unread,
Mar 8, 2017, 4:56:19 PM3/8/17
to
In article <o9pt5l$f6j$1...@dont-email.me>,
alf.p.stein...@gmail.com says...
No, that's not quite what I'm doing. I'm processing a CSV file that
has a reader record (the constants). I want to determine the offset for
each data field in data record so that I know how to process the data
values. For example, if Column 2 has the "BIB" values, I want to
process that data with a routine that's coded for whatever the
"BNoffset" index is for that file. That is, when I process the "Bib#"
field data, I need to know that the data for that processing is in the
2nd field in the data records.
Furthermore, the "Bib#" field can be identified in various files by
"NO.", "BIB", or other header names. So, for each fiel's processing I
need to scan the header, determine which columns have the data values I
want to process, and be able to access the data from a parsed CSV
records.
So, as I scan the header record, as I find a match on specific
constant values, I want to save the column offset in the named offset
values (BNoffset, OPoffset, FNoffset, etc.). There are many fields and
even more field names, and any field can be in any column of the file.
8<{{
Does this help?

red floyd

unread,
Mar 8, 2017, 6:30:18 PM3/8/17
to
std::map<std::string,std::function> ?



Manfred

unread,
Mar 8, 2017, 7:36:03 PM3/8/17
to
I think a static std::map<std::string,std::function> (indeed) that maps
field names to field handlers.
Then also a dynamic std::map<int,std::function> that maps field indices
to field handlers.
Alternatively a dynamic std::map<int,std::string> that maps field
indices to field names, and then find the handlers via the static map -
obviously less efficient.

Alf P. Steinbach

unread,
Mar 9, 2017, 4:32:15 AM3/9/17
to
Yes, much more clear what you're after.

Here's some code that might help:


#include <exception> // std::runtime_error
#include <string> // std::string
#include <unordered_map> // std::unordered_map
#include <vector> // std::vector

namespace mc {
using std::string;
using std::to_string;
using std::vector;

using X = std::runtime_error;

template< class Key, class Value >
using Map_ = std::unordered_map<Key, Value>;

struct Col_id
{
enum Enum { dp, bn, op, fn, _ };
static constexpr int n_values = _;
};

inline auto operator++( Col_id::Enum& e )
-> Col_id::Enum&
{
e = Col_id::Enum( e + 1 );
return e;
}

struct Named_offset{ string name; int value; };
using Col_offsets = Map_<Col_id::Enum, Named_offset>;

class Col_names
{
private:
Map_<string, Col_id::Enum> items_;

public:
auto id_for( string const& name ) const
-> Col_id::Enum
{
auto const it = items_.find( name );
if( it == items_.end() )
{
throw X{ "Col_names: no such name as `" + name + "`" };
}
return it->second;
}

Col_names()
{
items_ =
{
{ "NO.", Col_id::bn },
{ "BIB", Col_id::bn },
{ "PLACE", Col_id::op },
{ "OPLACE", Col_id::op },
{ "OVERALL_RANK", Col_id::op },
{ "TEAMPLACE", Col_id::op },
{ "FIRST NAME", Col_id::fn }
};
}
};

// This is a Meyers' singleton:
inline auto col_names()
-> Col_names const&
{
static Col_names const the_names;
return the_names;
}

inline auto offsets_from( vector<string> const& col_headers )
-> Col_offsets
{
Col_offsets result;
int offset = 0;
for( string const& name : col_headers )
{
Col_id::Enum const id = col_names().id_for( name );
auto const pair = result.insert( {id, Named_offset{ name,
offset} } );
bool const was_inserted = pair.second;
if( not was_inserted )
{
string const description = name + "` -> " + to_string(
id );
throw X{ "offsets_from: duplicate id, `" + description };
}
++offset;
}
return result;
}

} // namespace mc

#include <iostream> // std::cout etc.
#include <stdlib.h> // EXIT_FAILURE, EXIT_SUCCESS
using namespace std;

void cpp_main()
{
vector<string> const col_headers = { "BIB", "FIRST NAME",
"TEAMPLACE" };

cout << "Names:";
for( string const& name : col_headers )
{
cout << " `" << name << "`";
}
cout << endl;

mc::Col_offsets const offsets = mc::offsets_from( col_headers );

using Id = mc::Col_id;

cout << "Offsets:";
vector<Id::Enum> missing;
for( Id::Enum id{}; id < Id::n_values; ++id )
{
try
{
mc::Named_offset const& offset = offsets.at( id );
cout << " " << offset.name << "->" << offset.value;
}
catch( ... )
{
missing.push_back( id );
}
}
cout << endl;
cout << missing.size() << " known columns were not present";
if( missing.size() == 0 )
{
cout << "." << endl;
}
else
{
cout << ", namely (id)";
for( Id::Enum const id : missing )
{
cout << " " << id;
}
cout << "." << endl;
}
}

auto main()
-> int
{
try
{
cpp_main();
return EXIT_SUCCESS;
}
catch( exception const& x )
{
cerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}


Cheers!,

- Alf


Scott Lurndal

unread,
Mar 9, 2017, 8:51:55 AM3/9/17
to
Mike Copeland <mrc...@cox.net> writes:
> I have a fair amount of code to search for matches on constants and
>assign "offset values" of the constants' position in an array. The code
>is tedious and slow, and making changes to add new constants is
>difficult.
> In some other languages I've used there there's a way to assign an
>"address value" that's coded in a table, so that a loop can be used to
>scan for matches and assign a value to an associated variable whose
>address is in the table. Something like:
>
> {"NO.", &BNoffset, "BIB", &BNoffset, "PLACE", &OPoffset, etc. }
>
> Is such a thing available in C++? If so, how is it coded and used?

If you can do it in C, you can do it in C++, the same way. Consider
a class as a struct and use offset_of to store the offset of the
class/struct data member in the array.

# define OFFSET_OF(struct, member) \
((size_t)(&(reinterpret_cast<struct*>(__alignof__(struct*)))->member) - \
__alignof__(struct*))

/**
* Describe the "location" of each of the registers named above in the
* current guest. The entries in this table should be ordered
* consistent with the register enumeration and regnames tables.
*/
static struct _reglist guestregs[] = {
{ OFFSET_OF(user_regs_t, rax), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rbx), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rcx), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rdx), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rsp), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rbp), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rsi), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rdi), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r8 ), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r9 ), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r10), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r11), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r12), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r13), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r14), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r15), sizeof(uint64), BASE_URP },
{ OFFSET_OF(vmcb_t, rip), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, rflags), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, ss.selector), sizeof(uint16), BASE_VMCB },
{ OFFSET_OF(vmcb_t, cs.selector), sizeof(uint16), BASE_VMCB },
{ OFFSET_OF(vmcb_t, exit_code)+4, sizeof(uint32), BASE_VMCB },
{ OFFSET_OF(vmcb_t, exit_info1)+4, sizeof(uint32), BASE_VMCB },
{ OFFSET_OF(vmcb_t, cr0), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, cr2), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, cr3), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, cr4), sizeof(uint64), BASE_VMCB },
{ 0, sizeof(uint64), BASE_DR },
{ 1, sizeof(uint64), BASE_DR },
{ 2, sizeof(uint64), BASE_DR },
{ 3, sizeof(uint64), BASE_DR },
{ 4, sizeof(uint64), BASE_DR },
{ 5, sizeof(uint64), BASE_DR },
{ OFFSET_OF(vmcb_t, dr6), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, dr7), sizeof(uint64), BASE_VMCB },
};

switch (rp->r_base) {
case BASE_URP:
base = urp;
break;
case BASE_VMCB:
base = vp;
break;
...
}

switch (rp->r_len) {
case sizeof(uint64_t):
contents = getu64((uint64)base + rp->r_offset);
break;
case sizeof(uint32_t):
contents = getu32((uint64)base + rp->r_offset);
break;
case sizeof(uint16_t):
contents = getu16((uint64)base + rp->r_offset);
break;
case sizeof(uint8_t):
contents = getu8((uint64)base + rp->r_offset);
break;
}

/**
* Return an unsigned 16-bit quantity from the designed address.
* Returns the value zero if the address couldn't be validated.
*
* @param addr The address from which to fetch the word
* @returns the word value at address, or zero if address isn't valid
*/
inline uint16_t
c_debugger::getu16(uint64_t addr)
{
if (check(addr, sizeof(uint16_t))) return *(uint16_t *)addr;
return 0;
}

(This code is from a bare-metal hypervisor written in C++)

Mike Copeland

unread,
Mar 9, 2017, 11:45:02 AM3/9/17
to
In article <o9r791$s2k$1...@dont-email.me>,
Wow, that's much more than I can understand! (My failure)
I've tried the following:

std::map<std::string, int> csvMap;
std::string temp = "BIB";
int BNoffset;
csvMap[temp] = BNoffset;
csvMap[temp] = &BNoffset;
csvMap[temp] = *BNoffset;
csvMap["NO."] = BNoffset;

none of compiles. I've tried variations (*int, &int, *BNoffset,
&BNoffset) without success. I cannot store a map object with a string
data variable, so I can't store an integer value in the std::map object.
Please advise. TIA

Paavo Helde

unread,
Mar 9, 2017, 1:48:18 PM3/9/17
to
On 9.03.2017 18:44, Mike Copeland wrote:
> I've tried the following:
>
> std::map<std::string, int> csvMap;
> std::string temp = "BIB";
> int BNoffset;
> csvMap[temp] = BNoffset;
> csvMap[temp] = &BNoffset;
> csvMap[temp] = *BNoffset;
> csvMap["NO."] = BNoffset;
>
> none of compiles. I've tried variations (*int, &int, *BNoffset,
> &BNoffset) without success.

The following compiles for me fine. Either you are not posting your real
code, or you have messed something else up. Please post real code and
include error messages!

#include <map>
#include <string>
int main() {
std::map<std::string, int> csvMap;
std::string temp = "BIB";
int BNoffset = 42;
csvMap[temp] = BNoffset;
csvMap["NO."] = BNoffset;
}


Mike Copeland

unread,
Mar 9, 2017, 2:21:17 PM3/9/17
to
In article <kvSdnXUOxb72PlzF...@giganews.com>,
myfir...@osa.pri.ee says...
>
> > std::map<std::string, int> csvMap;
> > std::string temp = "BIB";
> > int BNoffset;
> > csvMap[temp] = BNoffset;
> > csvMap[temp] = &BNoffset;
> > csvMap[temp] = *BNoffset;
> > csvMap["NO."] = BNoffset;
> >
> > none of it compiles. I've tried variations (*int, &int, *BNoffset,
> > &BNoffset) without success.
>
> The following compiles for me fine. Either you are not posting your real
> code, or you have messed something else up. Please post real code and
> include error messages!
>
> #include <map>
> #include <string>
> int main() {
> std::map<std::string, int> csvMap;
> std::string temp = "BIB";
> int BNoffset = 42;
> csvMap[temp] = BNoffset;
> csvMap["NO."] = BNoffset;
> }

Here is the actual code (from within a code module I use with
multiple programs).
Note that I discovered that I had another "csvMap" declaration
elsewhere in other modules, so I changed my original posting to declare
"csvMap2" in my code. Same compile failure; same diagnostics.

#include <map>
#include <string>
std::map<std::string, int> csvMap2;
std::string temp = "BIB";
int BNoffset = 42;
csvMap2[temp] = BNoffset;
csvMap2["NO."] = BNoffset;

Here are the (many) errors I get from the compile (and I don't know
how to deal with them, as there's no "int []" in this code. Very
confusing, and that drives me to ask for help in this forum. This is
new logic for me, and I don't know how (or if) it works. The IDE
(VS2013) flags both "temp" and "NO." as the problem code, which is why I
tried to use a string declaration ("temp") as a way to get it to
compile. I had hoped to use string constants throughout...

Error 5 error C2040: 'csvMap2' : 'int []' differs in levels of
indirection from 'std::map<std::string,int,std::less
<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' c:\cpp10\source
\rpum2.cpp 236 1 rsutil23
Error 10 error C2040: 'csvMap2' : 'int []' differs in levels of
indirection from 'std::map<std::string,int,std::less
<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' c:\cpp10\source
\rpum2.cpp 237 1 rsutil23
Error 2 error C2057: expected constant expression c:\cpp10\source
\rpum2.cpp 236 1 rsutil23
Error 7 error C2057: expected constant expression c:\cpp10\source
\rpum2.cpp 237 1 rsutil23
Error 1 error C2086: 'int BNoffset' : redefinition c:\cpp10
\source\rpum2.cpp 235 1 rsutil23
Error 6 error C2440: 'initializing' : cannot convert from 'int' to
'int []' c:\cpp10\source\rpum2.cpp 236 1 rsutil23
Error 11 error C2440: 'initializing' : cannot convert from 'int' to
'int []' c:\cpp10\source\rpum2.cpp 237 1 rsutil23
Error 3 error C2466: cannot allocate an array of constant size 0
c:\cpp10\source\rpum2.cpp 236 1 rsutil23
Error 8 error C2466: cannot allocate an array of constant size 0
c:\cpp10\source\rpum2.cpp 237 1 rsutil23
Error 4 error C4430: missing type specifier - int assumed. Note:
C++ does not support default-int c:\cpp10\source\rpum2.cpp 236 1
rsutil23
Error 9 error C4430: missing type specifier - int assumed. Note:
C++ does not support default-int c:\cpp10\source\rpum2.cpp 237 1
rsutil23
12 IntelliSense: expression must have a constant value c:
\CPP10\source\rpum2.cpp 236 9 rsutil23
13 IntelliSense: this constant expression has type "const char
*" instead of the required "unsigned int" type c:\CPP10\source
\rpum2.cpp 237 9 rsutil23

Scott Lurndal

unread,
Mar 9, 2017, 2:26:56 PM3/9/17
to
Mike Copeland <mrc...@cox.net> writes:

>
>#include <map>
>#include <string>
>std::map<std::string, int> csvMap2;
>std::string temp = "BIB";
>int BNoffset = 42;
>csvMap2[temp] = BNoffset;
>csvMap2["NO."] = BNoffset;

You are including the last two lines in a function, right?

Mike Copeland

unread,
Mar 9, 2017, 2:49:38 PM3/9/17
to
In article <Z%hwA.17739$Hf3....@fx37.iad>, sc...@slp53.sl.home says...
>
> >#include <map>
> >#include <string>
> >std::map<std::string, int> csvMap2;
> >std::string temp = "BIB";
> >int BNoffset = 42;
> >csvMap2[temp] = BNoffset;
> >csvMap2["NO."] = BNoffset;
>
> You are including the last two lines in a function, right?

OMG...I did not! I am SO embarrassed - a real example of "Missing
the forest for the trees". I'm sorry, guys! 8<{{
0 new messages