Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
114 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Creating a Scalable Console System with STL – Part 1


Console Core

Parsing the Command Line

Now we have to make a function that looks in the list of items and executes it if it's a command or otherwise changes the variable. It all starts in the "passIntro" function.

void console::passIntro()
{
  if(m_commandLine.length() > 0) parseCommandLine();
}

…and continues in "parseCommandLine"…

bool console::parseCommandLine()
{
  std::ostringstream out; // more info here
  std::string::size_type index = 0;
  std::vector<std::string> arguments;
  std::list<console_item_t>::const_iterator iter;

  // add to text buffer
  if(command_echo_enabled)
{
    print(m_commandLine);
}

  // add to commandline buffer
  m_commandBuffer.push_back(m_commandLine);
  if(m_commandBuffer.size() > max_commands)
    m_commandBuffer.erase(m_commandBuffer.begin());

  // tokenize
  while(index != std::string::npos)
  {
    // push word
    std::string::size_type next_space = m_commandLine.find(' ');
    arguments.push_back(m_commandLine.substr(index, next_space));

    // increment index
    if(next_space != std::string::npos) index = next_space + 1;
    else break;
  }

  // execute (look for the command or variable)
  for(iter = m_itemsList.begin(); iter != m_ itemsList.end(); ++iter)
  {
    if(iter->name == arguments[0])
    {
      switch(iter->type)
      {
      ...
      case CTYPE_UINT:
        if(arguments.size() > 2)return false;
        else if(arguments.size() == 1)
        {
          out.str(""); // clear stringstream
          out << (*iter).name << " = " <<
                 *((unsigned int *)(*iter).variable_pointer);
          print(out.str());
          return true;
        }
        else if(arguments.size() == 2)
        {
          *((unsigned int *)(*iter).variable_pointer) =
             (unsigned int) atoi(arguments[1].c_str());
          return true;
        }
        break;
      ...
      case CTYPE_FUNCTION:
        (*iter).function(arguments);
        return true;
        break;
      ...
      default:
        m_defaultCommand(arguments);
        return false;
        break;
      }
    }
  }
}

Nice function, isn't it? It is very easy to understand though, but I will explain the most difficult parts anyway.

The first part of the function adds the commandline to the output text buffer, this works as a command echo, you can enable it or disable it. It's just an extra feature, if you want erase everything related with it and the console will just continue to work perfectly.

The second part adds the commandline to the command history buffer, we've talked about this before.

The third part tokenizes (divides) the commandline into a vector of strings where the first element (element zero) is the actual name of the command and all the other elements are arguments.

The last and more complex part starts by looking one by one all the commands and variables in the list and then compares the name provided in the command line with the name stored in the item information, if we have a match then we go on, if we don't we execute the default command.

If we find that the commandline first argument is a variable and that we have not provided any argument (we just wrote the variable name) then its a query command and we simply format the string and print out the variable content. If we have provided one argument then we convert the argument string to the item type format and we set it to memory (remember arguments size is 2 because the first element is the command or variable name itself!).

We may also come across the execution of a command which its a lot easier, in this case we just execute the associated function passing the vector with the arguments to it. Note that we don't pass a copy of the vector, we pass it by reference!



Usage & Conclusion


Contents
  Introduction
  Planning the Console
  Console Core
  Usage & Conclusion

  Source code
  Printable version
  Discuss this article