GameMonkey Script

GameMonkey Script Forums
It is currently Mon Mar 18, 2019 7:24 pm

All times are UTC




Post new topic Reply to topic  [ 1 post ] 
Author Message
PostPosted: Thu Feb 03, 2005 8:51 am 
Offline

Joined: Mon Dec 15, 2003 1:38 pm
Posts: 708
Sometimes a script table simply represents a data structure, like an array or pair of name & values. This post demonstrates how to access data from a gmTable and convert it to a compatible C++ data structure for use, for example, as configuration data. There are two main ways to accomplish this.

One way is to access the gmTableObject from C++, iterate the members using that interface and copy the table contents.

The other way is to bind some C++ functions to script, iterate the table members in script, calling those bound functions to pass data to C++ for copying.

Here's an example of the first method:
Code:
#include "gmThread.h"

//
// Example Data node class to store general config type data
// This is not implemented, just for example. 
// There is no reason to copy this style or partial implementation.
//
class Data
{
public:

  enum
  {
    TYPE_NULL,
    TYPE_INT,
    TYPE_FLOAT,
    TYPE_STRING,
    TYPE_NODE,
  };
 
  static Data* Create(const char* a_name, int a_type); // Creator instead of 'new Data()' etc.
 
  Data* Add(const char* a_name, int a_type);
  void SetInt(int a_value);
  void SetFloat(float a_value);
  void SetString(const char* a_value);
  void SetName(const char* a_name);
 
  // TODO implement the storage for this class
};


//
// Example function to iterate a gmTable from C++ and copy the contents into a C++ data structure.
// This method does not require binding any extra functions.
//
Data* gmTableToData(gmMachine* a_gm, gmTableObject* a_table, Data* a_data)
{
  if(!a_table)
  {
    return NULL;
  }

  // Some operating memory for AsString()
  const gtInt bufferLen = 256;
  char buffer[bufferLen];

  if(!a_data)
  {
    a_data = Data::Create("", Data::TYPE_NODE);
  }

  gmTableIterator it;
  gmTableNode* curNode = a_table->GetFirst(it);
  while(curNode)
  {
    int valueType = curNode->m_value.m_type;
    gtString keyString = curNode->m_key.AsString(a_gm, buffer, bufferLen);
    // NOTE: keyString may just be "1","2" etc for indexed members, may want to ignore these
    gmVariable* curVar = &curNode->m_value;

    if(valueType == GM_INT)
    {
      Data* newData = a_data->Add(keyString, Data::TYPE_INT);
      newData->SetInt(curVar->m_value.m_int);
    }
    else if(valueType == GM_FLOAT)
    {
      Date* newData = a_data->Add(keyString, Data::TYPE_FLOAT);
      newData->SetFloat(curVar->m_value.m_float);
    }
    else if(valueType == GM_STRING)
    {
      gmStringObject* objString = (gmStringObject*)(curVar->m_value.m_ref);
      Data* newData = a_data->Add(keyString, Data::TYPE_STRING);
      newData->SetString(objString->GetString());
    }
    else if(valueType == GM_TABLE)
    {
      gmTableObject* objTable = (gmTableObject*)(curVar->m_value.m_ref);
      Data* newData = a_data->Add(keyString, Data::TYPE_NODE);
      gmTableToData(a_gm, objTable, newData); // Recurse for nested table
    }
    else
    {
      ASSERT("Invalid type for table conversion");
      return NULL;
    }
   
    curNode = a_table->GetNext(it);
  }
  return a_data;
}


Data* gmTableToData(gmMachine* a_gm, gmVariable* a_var)
{
  if(a_var->m_type == GM_TABLE)
  {
    gmTableObject* table = (gmTableObject*)a_var->m_value.m_ref;
    return gmTableToData(a_gm, table, NULL);
  }
  return NULL;
}


Data* gmTableToData(gmMachine* a_gm, const char* a_globalTableName)
{
  gmVariable foundVar = a_gm->GetGlobals()->Get(a_gm, a_globalTableName);
  if(foundVar.m_type == GM_TABLE)
  {
    gmTableObject* table = (gmTableObject*)foundVar.m_value.m_ref;
    Data* data = gmTableToData(a_gm, table, NULL);
    if(data)
    {
      data->SetName(a_globalTableName);
    }
    return data;
  }
  return NULL;
}


Here's an example of the second method:
Code:
//
// Helper GM Script function to convert a table to Data for boxing.
// This is an example as if a type called 'Data' with supporting 'DataType' were bound in C++
// The function iterates the table contents and calls bound functions to fill the data on the C++ side.
//
// You may want to alter the data interpretation, for example, check if the table is only indexed
// and create an array of its contents instead of nested node types.
//
TableToData = function(a_table, a_data)
{
  if(a_table and a_data)
  {
    foreach(key and value in a_table)
    {
      local data = null;
      keyString = key.String();

      if(typeId(value) == 1)
      {
        data = Data(keyString, DataType.INT);
        data.SetInt(value);
      }
      else if(typeId(value) == 2)
      {
        data = Data(keyString, DataType.FLOAT);
        data.SetFloat(value);
      }
      else if(typeId(value) == 3)
      {
        data = Data(keyString, DataType.STRING);
        data.SetString(value);
      }
      else if(typeId(value) == 4)
      {
        data = Data(keyString, DataType.NODE);
       
        TableToData(value, data); // Recurse into this table
      }
      else
      {
        assert(!"Unknown gm type for table to Data boxing!");
      }
     
      // Insert data into our table
      a_data.Add(data);
    }
  }
};


This post was somewhat motivated by this thread by DrEvil-OB
http://www.gmscript.com/index.php?name= ... topic&t=75


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group