Game Development Community

Alphabetize fields during save ?

by Orion Elenzil · in Torque Game Engine · 03/02/2006 (12:45 pm) · 4 replies

When saving a mission file or a .gui file,
the ordering of fields, especially Tagged fields,
seems to be pretty much the order in which they were created,
or generally just not in a reproduced order.

for example:

-------------------------------------------
visible = "1";
numTabs = "0";
buttons0 = "0";
maxTabs = "3";
currentTabIndex = "-1";
tabs0 = "0";
-------------------------------------------
visible = "1";
currentTabIndex = "-1";
maxTabs = "3";
buttons0 = "0";
numTabs = "0";
tabs0 = "0";
-------------------------------------------

note that there's absolutely no difference in the object's fields,
except they've been saved in a different order.

this makes version control a nightmare.


files like the mission or a .gui which could be nicely merged between developers essentially become binary as far as version control goes.

my questions are two:

1. is there any reason Not to order the fields in stricmp() order when saving ?

2. has this already been done ?

3. if it hasn't already been done and it is a good idea, any one happen to know off the top a good place for me to start ?

cheers,
orion

#1
03/02/2006 (2:23 pm)
We faced that problem a while ago, with .MIS files with lots of custom fields giving us major headaches in version control.

Try replacing the function SimFieldDictionary::writeFields in simBase.cc by this one:
(I'm not sure if this depends on other changes... try diff'ing it against the original for more details.

void SimFieldDictionary::writeFields(SimObject *obj, Stream &stream, U32 tabStop)
{
   const AbstractClassRep::FieldList &list = obj->getFieldList();
   char expandedBuffer[1024];

	typedef char rowOrderBuffer[1024];
	static const int nrows = 4000;
	rowOrderBuffer *orderBuffer;
	char *ob;
	int count=0,total;
	
	orderBuffer = (rowOrderBuffer*) malloc(nrows * 1024 * sizeof(char));

   for(U32 i = 0; i < HashTableSize; i++)
   {
      for(Entry *walk = mHashTable[i];walk; walk = walk->next)
      {
         // make sure we haven't written this out yet:
         U32 i;
         for(i = 0; i < list.size(); i++)
            if(list[i].pFieldname == walk->slotName)
               break;
         if(i != list.size())
            continue;

         //writeTabs(stream, tabStop+1);
         dSprintf(expandedBuffer, sizeof(expandedBuffer), "%s = \"", walk->slotName);
         expandEscape(expandedBuffer + dStrlen(expandedBuffer), walk->value);
         dStrcat(expandedBuffer, "\";\r\n");

			ob = orderBuffer[count];
			//ob = (char *)(&orderBuffer+1024*count);
			dSprintf(ob, sizeof(expandedBuffer), "%s",expandedBuffer);
			count++;
			if (count>nrows){
				Con::printf("INFAMOUS ERROR: \"PRLD MAX 4000 Dynamic Fields\" Raise value of nrows in simBase.cc:255");	
			}
         //stream.write(dStrlen(expandedBuffer),expandedBuffer);
      }
   }

   total = count;
	count = 0;

	for(U32 x = 0; x < (total-1); x++) 
	{
		count = x; //count now will save the string with less value
		for(U32 y = (x+1); y < (total); y++) 
		{
			if (dStricmp(orderBuffer[count],orderBuffer[y]) > 0) 
			{
				count = y;
			}
		}
		//Need Switch?
		if (count != x)
		{
			//expandedBuffer used as a temp
			dSprintf(expandedBuffer, sizeof(expandedBuffer), "%s",orderBuffer[x]);
			dSprintf(orderBuffer[x], sizeof(expandedBuffer), "%s",orderBuffer[count]);
			dSprintf(orderBuffer[count], sizeof(expandedBuffer), "%s",expandedBuffer);
		}
	}

	for(U32 x = 0; x < total; x++) 
	{
		writeTabs(stream, tabStop+1);
      stream.write(dStrlen(orderBuffer[x]),orderBuffer[x]);
	}

	free(orderBuffer);

}
#2
03/02/2006 (2:54 pm)
This is a good candidate to include in a future point release of 1.4 IMO.

I hate merging MIS and GUI files for just this reason.
#3
03/02/2006 (4:29 pm)
Thanks Manoel. I'll let you know how it goes.
#4
03/08/2006 (10:38 am)
Hi Manoel -

finally got around to implementing this.
i dropped in your code, changed malloc() and free() to dMalloc() and dFree(),
and it seems to be working great.

many thanks!

even for a one-person team, this should make a big difference if you're using version control,
and if you're a multi-person team it's even bigger.

I echo Tom, this would be great in Head.