Linear Probing Hash Function not working? - c++

What am i doing wrong with my linear probing function?
bool HashTable_lp::insert( const string & x )
{
// Insert x as active
int currentPos = findPos( x );
if( isActive( currentPos ) )
return true;
array[ currentPos ] = HashEntry( x, ACTIVE );
if( ++currentSize > array.size( ) / 2 )
rehash( );
return false;
}

You generally want a while loop until you find an empty slot. The other problem is you were equating a cell that your string hashes to being active to meaning that the cell contains the same value you are trying to insert. In general, you need to check the value of your key to insert against existing entries. It may be worth making an insert version that does not do this check for cases where the user can guarantee the item is not already in the hash table to avoid these comparisons...
bool HashTable_lp::insert( const string & x )
{
// Insert x as active
int currentPos = findPos( x );
while( isActive( currentPos ) ){
// here key gets out of array[currentPos] the string key
if(key(currentPos)==x) return true; // already in hash
currentPos++; // linearly probe to next guy
}
// at this point we know currentPos is empty
array[ currentPos ] = HashEntry( x, ACTIVE );
if( ++currentSize > array.size( ) / 2 ) // ensure load factor is .5 to guarantee probing works!
rehash( );
return false;
}

Related

Adding XPointer/XPath searches to ALL(?) C++ JSON libraries, is it doable?

Is it possible to extend all(?) existing C++ JSON libraries with XPath/XPointer or subset with just one C++ implementation? At least those with iterators for object and array values?
I have reviewed three C++ JSON libraries (reviewing nlohmann, Boost.JSON and RapidJSON) to see the internals and check their search functionality. Some have implemented Json pointer. Json pointer is basic, almost like working with json as a name-value list.
XML has XPath and XPointer searches and rules are standardized. With XPath and XPointer you can do more.
One reason to reviewing these libraries was to see if it is possible to extend any of them with better search functionality. Or might it be possible to extend all(?) C++ JSON libraries at once?
A longer text describing this can be found here, trying to be brief.
I tried to do one traverse method that selects json values with one specific property name and that method should work an all tested JSON libraries. If I got that to work it may be possible to add more search logic and get it to work on almost all C++ JSON.
I got this C++ templated function to work an all tested json libraries. It can walk the JSON tree and select json values on all tested libraries.
What is needed to is to implement specializations of is_object, is_array, compare_name, get_value, begin and end. That are just one liners so it's easy.
template<typename json_value>
bool is_object( const json_value* p )
{ static_assert(sizeof(json_value) == 0, "Only specializations of is_object is allowed"); }
template<typename json_value>
bool is_array( const json_value* p )
{ static_assert(sizeof(json_value) == 0, "Only specializations of is_array is allowed"); }
template<typename iterator>
bool compare_name( iterator it, std::string_view stringName )
{ static_assert(sizeof(it) == 0, "Only specializations of compare_name is allowed"); }
template<typename iterator, typename json_value>
const json_value* get_value( iterator it )
{ static_assert(sizeof(it) == 0, "Only specializations of get_value is allowed"); }
template<typename iterator, typename json_value>
iterator begin( const json_value& v ) { return std::begin( v ); }
template<typename iterator, typename json_value>
iterator end( const json_value& v ) { return std::end( v ); }
// ------------------------------------------------
// Selects all json values that match property name
template<typename json_value, typename object_iterator,typename array_iterator = object_iterator>
uint32_t select( const json_value& jsonValue, std::string_view stringQuery, std::vector<const json_value*>* pvectorValue = nullptr )
{ assert( is_object( &jsonValue ) || is_array( &jsonValue ) );
uint32_t uCount = 0;
if( is_object( &jsonValue ) == true ) // found object ?
{
for( auto it = begin<object_iterator,json_value>( jsonValue ); it != end<object_iterator,json_value>( jsonValue ); it++ )
{
if( is_object( get_value<object_iterator,json_value>( it ) ) == true )
{ // found object, scan it
auto value = get_value<object_iterator,json_value>( it );
uCount += select<json_value,object_iterator>( *value, stringQuery, pvectorValue );
}
else if( is_array( get_value<object_iterator,json_value>( it ) ) == true )
{ // found array, scan it
auto parray = get_value<object_iterator,json_value>( it );
uCount += select<json_value,object_iterator,array_iterator>( *parray, stringQuery, pvectorValue );
}
else if( compare_name<object_iterator>( it, stringQuery ) == true )
{ // property name matches, store value if pointer to vector
if( pvectorValue != nullptr ) pvectorValue->push_back( get_value<object_iterator,json_value>( it ) );
uCount++;
}
}
}
else if( is_array( &jsonValue ) == true ) // found array
{
for( auto it = begin<array_iterator,json_value>( jsonValue ); it != end<array_iterator,json_value>( jsonValue ); it++ )
{
if( is_object( get_value<array_iterator,json_value>( it ) ) == true )
{ // found object, scan it
auto value = get_value<array_iterator,json_value>( it );
uCount += select<json_value,object_iterator>( *value, stringQuery, pvectorValue );
}
else if( is_array( get_value<array_iterator,json_value>( it ) ) == true )
{ // found array, scan it
auto parray = get_value<array_iterator,json_value>( it );
uCount += select<json_value,object_iterator,array_iterator>( *parray, stringQuery, pvectorValue );
}
}
}
return uCount;
}
if this works and if I haven't forgot something, shouldn't it be possible to extend all libraries with just one implementation? The additional logic for XPath and XPointer is not dependent on the implementation of these C++ JSON libraries.
Am I missing something

OpenVR - IVRSystem::GetControllerState always returns empty structs

I've been following Kamran Bigdely-Shamloo's article on how to get positional information from the HTC Vive and it has worked well so far. My next step was to "listen" to button presses. I've read the documentation and it says here that all I need to do is query IVRSystem::GetControllerStateand it'll return a
"struct with the current state of the controller"
This struct however always contains variables that have the 0 value. The following function is called in a while (true) loop from the main function.
bool CMainApplication::HandleInput()
{
SDL_Event sdlEvent;
bool bRet = false;
while ( SDL_PollEvent( &sdlEvent ) != 0 )
{
if ( sdlEvent.type == SDL_QUIT )
{
bRet = true;
}
else if ( sdlEvent.type == SDL_KEYDOWN )
{
if ( sdlEvent.key.keysym.sym == SDLK_ESCAPE
|| sdlEvent.key.keysym.sym == SDLK_q )
{
bRet = true;
}
if( sdlEvent.key.keysym.sym == SDLK_c )
{
m_bShowCubes = !m_bShowCubes;
}
}
}
// Process SteamVR events
// Periodically returns an event of type 404 ("VREvent_SceneApplicationChanged = 404, // data is process - The App actually drawing the scene changed (usually to or from the compositor)"
vr::VREvent_t event;
vr::VREvent_Controller_t controllerEvent;
std::chrono::milliseconds ms4;
while( m_pHMD->PollNextEvent( &event, sizeof( event ) ) )
{
ms4 = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
);
ProcessVREvent( &event);
printPositionalData(&event, ms4);
}
vr::VRControllerState_t state;
// Check every device attached, usually it's four devices
// Second if statement is never reached
for (int i = 0; i < 1000; i++) {
if (m_pHMD->GetControllerState(i, &state, sizeof(state))) {
dprintf("%d", i);
if (state.ulButtonPressed != 0 || state.unPacketNum != 0 || state.ulButtonTouched != 0) {
dprintf("Some action?");
}
}
}
dprintf("\n");
// Process SteamVR action state
// UpdateActionState is called each frame to update the state of the actions themselves. The application
// controls which action sets are active with the provided array of VRActiveActionSet_t structs.
vr::VRActiveActionSet_t actionSet = { 0 };
actionSet.ulActionSet = m_actionsetDemo;
vr::VRInput()->UpdateActionState( &actionSet, sizeof(actionSet), 1 );
m_bShowCubes = !GetDigitalActionState( m_actionHideCubes );
vr::VRInputValueHandle_t ulHapticDevice;
if ( GetDigitalActionRisingEdge( m_actionTriggerHaptic, &ulHapticDevice ) )
{
if ( ulHapticDevice == m_rHand[Left].m_source )
{
vr::VRInput()->TriggerHapticVibrationAction( m_rHand[Left].m_actionHaptic, 0, 1, 4.f, 1.0f, vr::k_ulInvalidInputValueHandle );
}
if ( ulHapticDevice == m_rHand[Right].m_source )
{
vr::VRInput()->TriggerHapticVibrationAction( m_rHand[Right].m_actionHaptic, 0, 1, 4.f, 1.0f, vr::k_ulInvalidInputValueHandle );
}
}
vr::InputAnalogActionData_t analogData;
if ( vr::VRInput()->GetAnalogActionData( m_actionAnalongInput, &analogData, sizeof( analogData ), vr::k_ulInvalidInputValueHandle ) == vr::VRInputError_None && analogData.bActive )
{
m_vAnalogValue[0] = analogData.x;
m_vAnalogValue[1] = analogData.y;
}
m_rHand[Left].m_bShowController = true;
m_rHand[Right].m_bShowController = true;
vr::VRInputValueHandle_t ulHideDevice;
if ( GetDigitalActionState( m_actionHideThisController, &ulHideDevice ) )
{
if ( ulHideDevice == m_rHand[Left].m_source )
{
m_rHand[Left].m_bShowController = false;
}
if ( ulHideDevice == m_rHand[Right].m_source )
{
m_rHand[Right].m_bShowController = false;
}
}
for ( EHand eHand = Left; eHand <= Right; ((int&)eHand)++ )
{
vr::InputPoseActionData_t poseData;
if ( vr::VRInput()->GetPoseActionData( m_rHand[eHand].m_actionPose, vr::TrackingUniverseStanding, 0, &poseData, sizeof( poseData ), vr::k_ulInvalidInputValueHandle ) != vr::VRInputError_None
|| !poseData.bActive || !poseData.pose.bPoseIsValid )
{
m_rHand[eHand].m_bShowController = false;
}
else
{
m_rHand[eHand].m_rmat4Pose = ConvertSteamVRMatrixToMatrix4( poseData.pose.mDeviceToAbsoluteTracking );
vr::InputOriginInfo_t originInfo;
if ( vr::VRInput()->GetOriginTrackedDeviceInfo( poseData.activeOrigin, &originInfo, sizeof( originInfo ) ) == vr::VRInputError_None
&& originInfo.trackedDeviceIndex != vr::k_unTrackedDeviceIndexInvalid )
{
std::string sRenderModelName = GetTrackedDeviceString( originInfo.trackedDeviceIndex, vr::Prop_RenderModelName_String );
if ( sRenderModelName != m_rHand[eHand].m_sRenderModelName )
{
m_rHand[eHand].m_pRenderModel = FindOrLoadRenderModel( sRenderModelName.c_str() );
m_rHand[eHand].m_sRenderModelName = sRenderModelName;
}
}
}
}
return bRet;
m_pHMD is initalized as follows:
vr::IVRSystem *m_pHMD;
....
m_pHMD = vr::VR_Init( &eError, vr::VRApplication_Background );
I must be doing something wrong because in the following snippet, the if statement is passed only for the first four iterations, which should be a controller, the vive tracker, the headset and the lighthouses. This tells me that I am able to access these states, but I am somehow not able to read the information.
for (int i = 0; i < 1000; i++) {
if (m_pHMD->GetControllerState(i, &state, sizeof(state))) {
dprintf("%d", i);
if (state.ulButtonPressed != 0 || state.unPacketNum != 0 || state.ulButtonTouched != 0) {
dprintf("Some action?");
}
}
I can't imagine its a bug, so my guess is that my configuration is faulty, or I'm doing the wrong query.
Any help is greatly appreciated!
Apparently I was making two mistakes.
Mistake #1 was that I was using the wrong sample file. I used hellovr_opengl from the OpenVr sample folder, but instead hellovr_dx12 was the working solution. It must have a different kind of configration as well, since I copied a function which was working into the hellovr_opengl project and there, it did not work! Then I copied the functions I added to the hellovr_dx12 project and was able to get the controller states of the Vive controller.
However, I wanted to get the states of the Vive Tracker, which didn't work. After some googling I found out about an issue with the current SteamVR driver, so I reverted it back to a beta hoftix, which solved the Vive Tracker issue for me.
You have to call;
vr::VRInput()->SetActionManifestPath

Not able to return out of recursion

I have the following piece of code. It aims at traversing the [attached screenshot] Tree structure in depth first manner.
As you can see, I am interested in the highlighted entry in green -> Has Class( DatasetType ) node of this tree structure. This Tree structure is subjected to additions of new nodes by customers. So, I have to traverse the Tree structure to find my node of interest. I have formulated the below code. But And I can see that it identifies that node of my interest.
However, it is not stopping there. It is proceeding onto the next sibling i.e., Has Class( EPMJob ). I want my processing to stop. I am pretty sure that my way of returning stuff is missing something. but not able to pin point.
Any inputs are most welcome.
tag_t findHasTypeDatasetNodeInAMTree( tag_t amTreeNode )
{
CharPointer nodeName;
Response stat = askRuleName( amTreeNode, &nodeName );
CharPointer nodeArgument;
stat = askRuleArg( amTreeNode, &nodeArgument );
if( tc_strcmp( nodeName.getString(), "Has Class" ) == 0 && tc_strcmp( nodeArgument.getString(), "DatasetType" ) == 0 )
{
return amTreeNode;
}
int numChildNodes = 0;
TagPointer childNodes;
stat = askChildren( amTreeNode, &numChildNodes, &childNodes );
if( numChildNodes == 0 )
{
return NULLTAG;
}
// The following is the piece that needs attention.
// Do not want to NULL check here though
for( int inx = 0; inx < numChildNodes; ++inx )
{
findHasTypeDatasetNodeInAMTree( childNodes[inx] );
}
return NULLTAG;
}
I'm not sure what this is doing:
for( int inx = 0; inx < numChildNodes; ++inx )
{
findHasTypeDatasetNodeInAMTree( childNodes[inx] );
}
But I'm pretty sure it doesn't stop when you find something so the result is ALWAYS NULLTAG. How about something like:
for( int inx = 0; inx < numChildNodes; ++inx )
{
auto result = findHasTypeDatasetNodeInAMTree( childNodes[inx] );
if( result != NULLTAG )
return result;
}

MongoDb creating sparse index using c++ driver

Is there a way to create a sparse index using the MongoDb (2.2) C++ driver?
It seems that the ensureIndex function does not accept this argument. From MongoDb docs:
bool mongo::DBClientWithCommands::ensureIndex(
const string & ns,
BSONObj keys,
bool unique = false,
const string & name = "",
bool cache = true,
bool background = false,
int v = -1)
For that matter, dropDups isn't an argument either...
As a workaround, you can build the server command yourself and append the sparse argument. If you follow this link, you'll notice that the server command consists of building a BSONObject and the various index options are appended as fields. It should be straightforward to write your own version of ensureIndex.
I ended up patching the Mongo source code (mongo/cleint/dbclient.cpp):
bool DBClientWithCommands::ensureIndex( const string &ns , BSONObj keys , bool unique, const string & name , bool cache, bool background, int version, bool sparse ) {
BSONObjBuilder toSave;
toSave.append( "ns" , ns );
toSave.append( "key" , keys );
string cacheKey(ns);
cacheKey += "--";
if ( name != "" ) {
toSave.append( "name" , name );
cacheKey += name;
}
else {
string nn = genIndexName( keys );
toSave.append( "name" , nn );
cacheKey += nn;
}
if( version >= 0 )
toSave.append("v", version);
if ( unique )
toSave.appendBool( "unique", unique );
if ( sparse )
toSave.appendBool( "sparse", true );
if( background )
toSave.appendBool( "background", true );
if ( _seenIndexes.count( cacheKey ) )
return 0;
if ( cache )
_seenIndexes.insert( cacheKey );
insert( Namespace( ns.c_str() ).getSisterNS( "system.indexes" ).c_str() , toSave.obj() );
return 1;
}
The issue should be resolved in version 2.3.2

Error handling for xml parsing

I'm using tinyxml to parse xml files, and I've found that error handling here lends itself to arrow code. Our error handling is simply reporting a message to a file.
Here is an example:
const TiXmlElement *objectType = dataRoot->FirstChildElement( "game_object" );
if ( objectType ) {
do {
const char *path = objectType->Attribute( "path" );
if ( path ) {
const TiXmlElement *instance = objectType->FirstChildElement( "instance" );
if ( instance ) {
do {
int x, y = 0;
instance->QueryIntAttribute( "x", &x );
instance->QueryIntAttribute( "y", &y );
if ( x >= 0 && y >= 0 ) {
AddGameObject( new GameObject( path, x, y ));
} else {
LogErr( "Tile location negative for GameObject in state file." );
return false;
}
} while ( instance = instance->NextSiblingElement( "instance" ));
} else {
LogErr( "No instances specified for GameObject in state file." );
return false;
}
} else {
LogErr( "No path specified for GameObject in state file." );
return false;
}
} while ( objectType = objectType->NextSiblingElement( "game_object" ));
} else {
LogErr( "No game_object specified in <game_objects>. Thus, not necessary." );
return false;
}
return true;
I'm not huffing and puffing over it, but if anyone can think of a cleaner way to accomplish this it would be appreciated.
P.S. Exceptions not an option.
Edit:
Would something like this be preferable?
if ( !path ) {
// Handle error, return false
}
// Continue
This eliminates the arrow code, but the arrow code kind of puts all of the error logging on one place.
Using return values as error codes just leads to such code, it can't be improved much. A slightly cleaner way would use goto to group all error handling into a single block and to decrease the nesting of blocks.
This does however not solve the actual problem, which is using return values as error codes. In C, there is no alternative, but in C++ exceptions are available and should be used. If they are not an option, you're are stuck with what you have.
You could create a macro for that, which encapsulates the if (!var) { .. return false; } and error reporting.
However, I do not see how this can be improved all that much; its just the way it is. C'est la vie. C'est le code...
I'm not huffing and puffing over it,
but if anyone can think of a cleaner
way to accomplish this it would be
appreciated.
I have replaced the nested ifs with return statements on error (this makes the code "flow down" instead of going "arrow shaped". I have also replaced your do loopps with for loops (so I could understand it better).
Is this what you wanted?
const TiXmlElement *objectType = dataRoot->FirstChildElement( "game_object" );
if ( !objectType ) {
LogErr( "No game_object specified in <game_objects>. Thus, not necessary." );
return false;
}
for(; objectType != 0; objectType = objectType->NextSiblingElement( "game_object" )) {
const char *path = objectType->Attribute( "path" );
if ( !path ) {
LogErr( "No path specified for GameObject in state file." );
return false;
}
const TiXmlElement *instance = objectType->FirstChildElement( "instance" );
if ( !instance ) {
LogErr( "No instances specified for GameObject in state file." );
return false;
}
for(; instance != 0; instance = instance->NextSiblingElement( "instance" )) {
int x, y = 0;
instance->QueryIntAttribute( "x", &x );
instance->QueryIntAttribute( "y", &y );
if ( x >= 0 && y >= 0 ) {
AddGameObject( new GameObject( path, x, y ));
} else {
LogErr( "Tile location negative for GameObject in state file." );
return false;
}
}
}
return true;
I know it is a little late, but I know that QueryIntAttribute returns a value which can be used for error handling in case you want this for your attributes too.
if (instance->QueryIntAttribute("x",&x)!=TIXML_SUCCESS)
cout << "No x value found";