.:: Bots United ::.

.:: Bots United ::. (http://forums.bots-united.com/index.php)
-   General Programming (http://forums.bots-united.com/forumdisplay.php?f=25)
-   -   Pointer to vector element (http://forums.bots-united.com/showthread.php?t=973)

Lazy 03-03-2004 23:54

Pointer to vector element
 
I cannot figure out how to get a pointer to an element through an iterator,
indexing works but since I'm using an iterator that is out.

The vector holds structures by value and the class that it is contained in has a method to get an iterator to an item by looking up it's name.

The return of the Find method is something like this: std::vector< mystruct* >::iterator.

Since Find is a private method I have also added a public Lookup method to return a pointer to the element in the array.
I don't use Vector or the STL that often so I'm not quite sure how to do this.

Any ideas?

Lazy 08-03-2004 00:49

Re: Pointer to vector element
 
Well, I guess posting no code isn't very smart of me.
Here is what I have but it really needs to be cleaned up and possibly rewritten.

Code:

#ifndef USERMESSAGE_H
#define USERMESSAGE_H
  #ifndef _VECTOR_        // If vector has not been included
          #include <vector> // Include it now...
  #endif                          // End statement
  // pfnMessageProc
  // Type for a function pointer to a callback function.
  typedef int ( *pfnMessageProc ) ( edict_t* pDest, void* pData );
  // struct usermessage_s
  // usermessage_t
  // Structure containing data about a network message.
  typedef struct usermessage_s
  {
          char szName[ 12 ];  // Name of message
          int iId,        // Id of message
                  iSize;  // Size of message
          pfnMessageProc pfnCallback;  // Function to call when this message is started,
                                                                        // finished or written to.
  } usermessage_t;
  // CUserMessageHandler
  // Class to aid in the registration, lookup and capture of network messages.
  class CUserMessageHandler
  {
          std::vector< usermessage_t > m_uMessages;  // Vector list of all messages currently registered
          int m_iCurrentMsg;                                                  // Id of the message currently being sent
          // Find
          // Iterates through the currently registered messages
          // and returns the an iterator to the requested element.
          // Search is case sensitive.
          std::vector< usermessage_t >::iterator Find( const char* pszName )
          {
                std::vector< usermessage_t >::iterator iBegin = m_uMessages.begin( );
                std::vector< usermessage_t >::iterator iEnd = m_uMessages.end( );
                usermessage_t uCurrent;
                while ( iBegin != iEnd )
                {
                        uCurrent = *iBegin;
                        if ( uCurrent.szName )
                        {
                          if ( ! strcmp( uCurrent.szName, pszName ) )
                                  return iBegin;
                        }
                        ++iBegin;
                }
                return 0;
          }
          // Find
          // Overloaded to lookup a message from it's id.
          std::vector< usermessage_t >::iterator Find( int iId )
          {
                std::vector< usermessage_t >::iterator iBegin = m_uMessages.begin( );
                std::vector< usermessage_t >::iterator iEnd = m_uMessages.end( );
                usermessage_t uCurrent;
                while ( iBegin != iEnd )
                {
                        uCurrent = *iBegin;
                        if ( uCurrent.iId == iId )
                        {
                          return iBegin;
                        }
                        ++iBegin;
                }
                return 0;
          }
          usermessage_t Dummy( void )
          {
                usermessage_t uDummy;
                memset( &uDummy, 0, sizeof( usermessage_t ) );
                return uDummy;
          }
          public:
                // Reset
                // Clear all user messages registered.
                // Make sure this is done in ServerActivate otherwise they will repeat.
                void Reset( void )
                {
                        m_uMessages.clear( );
                }
                // Add
                // Registers a message with the message handler.
                // This is usually done in RegUserMsg and optionally you can pass a pointer to
                // a function that gets called when the message is started, finished or written to.
                void Add( const char* pszName, int iSize, int iId, pfnMessageProc pfnCallback )
                {
                        usermessage_t uTemp;
                        strcpy( uTemp.szName, pszName );
                        uTemp.pfnCallback = pfnCallback;
                        uTemp.iSize = iSize;
                        uTemp.iId = iId;
                        m_uMessages.push_back( uTemp );
                }
                // Remove
                // Removes a message from the handler by name.
                void Remove( const char* pszName )
                {
                        std::vector< usermessage_t >::iterator iIndex = Find( pszName );
                        if ( iIndex != 0 )
                        {
                          m_uMessages.erase( iIndex );
                        }
                }
                // Lookup
                // Returns a usermessage_t pointer to a previously registered message.
                usermessage_t Lookup( const char* pszName )
                {
                        std::vector< usermessage_t >::iterator iIndex = Find( pszName );
                        if ( iIndex != 0 )
                        {
                          return *iIndex;
                        }
                        return Dummy( );
                }
  };
  extern CUserMessageHandler gHandler;
#endif  // USERMESSAGE_H

The idea for the Lookup method is to return a pointer to the element, if it was not found I could simply return NULL which cannot be done by value.

Pierre-Marie Baty 08-03-2004 09:38

Re: Pointer to vector element
 
wow, C++.
I suck at C++.

Personally I would get rid of the STL and use my own struct for that. Then using an array like this:
Code:

struct usermessage_t messages[MAX_USERMESSAGES];
I would just fill this array for each call of pfnRegUserMsg(), then parse this array and return a pointer to the right slot each time pfnMessageBegin() is called (actually that's what I do already in my bot code).

Adding a pointer to the callback function in the network message structure is a smart idea, I think I will borrow this one ! :)

What's the advantage of using the STL by the way ? Auto-sorting by name or by ID ? This can be done using a binary tree and a linked list instead of an array for sorting by name; and sorting by ID can be done just by inserting the messages at their right position in the array since there's 256 registerable user messages at max in the HL engine.

Lazy 08-03-2004 09:45

Re: Pointer to vector element
 
To be honest, if I could write this stuff in a pure C compiler I would but this seemed to be the easiest way to do things. Much less complicated that way.

The problem with allocating a fixed array of 256 user message objects is that any given dll only sees from 60 and above wasting quite a bit of space.

Useless addition that has nothing to do with this post:

Hehe - whenever my fan goes faster or slower the usage light on my ups goes up or down a notch.

@$3.1415rin 08-03-2004 09:49

Re: Pointer to vector element
 
STL is quite fine since the performance is ok, and you dont have to care about implementing your own lists, etc. and the vector class is as fast as an array as long as you dont look at adding elements ...

already tried &(*iterator) for getting a pointer to an element ?

Lazy 08-03-2004 09:52

Re: Pointer to vector element
 
Yeah, but I think it's a pointer to the iterator not the element.

Pierre-Marie Baty 08-03-2004 09:58

Re: Pointer to vector element
 
Quote:

Originally Posted by Lazy
The problem with allocating a fixed array of 256 user message objects is that any given dll only sees from 60 and above wasting quite a bit of space.

malloc()ate it then :)

Lazy 08-03-2004 10:03

Re: Pointer to vector element
 
Well, ignore my comment earlier I misread @$.1415rin's post.
A small test shows that &(*iterator) gives a pointer to the element.

Thanks to all who posted here.

@PMB:
Then there are more steps to do, its a choice between wasting memory or extra lookup steps.
I looked at this problem and saw an object-oriented solution though those methods you mentioned probably work great aswell.
vbmenu_register("postmenu_8440", true);

Cheeseh 02-04-2004 01:06

Re: Pointer to vector element
 
or you can use my code you know, :) in rcbot I use similar structures for catching network messages (without STL but my own generic structures... ho hum)

oh .. and it should be easy to understand, that's what I've been trying to do with most of my code (...heh without comments *cough*)

Lazy 02-04-2004 01:21

Re: Pointer to vector element
 
Well, since you must write all half-life code in C++ there was no sense in ignoring the STL. It was easy to use and didn't require alot of maintenance.

When I get around to finishing my C sdk for half-life I'll start using it instead of C++.


All times are GMT +2. The time now is 10:22.

Powered by vBulletin® Version 3.8.2
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.