Get rid of the ID number cruft in the string resource system:

* At the only place where these ID numbers where used (scrValDefSave and scrValDefLoad), use the key-string instead (e.g. "ZNULLBODY" instead of 17)
 * Rename function strresGetStringByID to strresGetString
 * Increment event save file version to 4 (version of savegame.es files)
 * Reject loading of savegames that need to load non-NULL ST_TEXTSTRING variables from version < 4

NOTE: This may break current savegames of games that use scripts with variables of type TEXTSTRING in them (AFAIK currently only ''some'' campaign and tutorial savegames have these).

This closes ticket:19

git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@5685 4a71c877-e1ca-e34f-864e-861f7616d084
master
Giel van Schijndel 2008-07-27 23:58:49 +00:00
parent 54ae7cda3a
commit 3eabf084ad
10 changed files with 128 additions and 104 deletions

View File

@ -40,7 +40,6 @@
typedef struct STR_RES
{
struct TREAP_NODE** psIDTreap; ///< The treap to store string identifiers
int nextID; ///< The next free ID
} STR_RES;
/* Initialise the string system */
@ -53,7 +52,6 @@ STR_RES* strresCreate()
abort();
return NULL;
}
psRes->nextID = 0;
psRes->psIDTreap = treapCreate();
if (!psRes->psIDTreap)
@ -89,19 +87,10 @@ BOOL strresStoreString(STR_RES *psRes, const char* pID, const char* pString)
return false;
}
return treapAdd(psRes->psIDTreap, pID, pString, psRes->nextID++);
return treapAdd(psRes->psIDTreap, pID, pString);
}
/* Get the string from an ID number */
const char* strresGetString(const STR_RES * psRes, int id)
{
ASSERT(psRes != NULL, "Invalid string resource pointer");
return treapFindByID(psRes->psIDTreap, id);
}
const char* strresGetStringByID(const STR_RES* psRes, const char* ID)
const char* strresGetString(const STR_RES* psRes, const char* ID)
{
const char * string;
@ -140,9 +129,9 @@ BOOL strresLoad(STR_RES* psRes, const char* fileName)
}
/* Get the ID number for a string*/
int strresGetIDfromString(STR_RES *psRes, const char *pString)
const char* strresGetIDfromString(STR_RES *psRes, const char *pString)
{
ASSERT(psRes != NULL, "Invalid string res pointer");
return treapFindID(psRes->psIDTreap, pString);
return treapFindKey(psRes->psIDTreap, pString);
}

View File

@ -32,9 +32,6 @@ extern struct STR_RES* strresCreate(void);
/* Release a string resource object */
extern void strresDestroy(struct STR_RES *psRes);
/* Get the string from an ID number */
extern const char* strresGetString(const struct STR_RES *psRes, int id);
/**
* Retrieve a resource string from its identifier string.
*
@ -43,12 +40,12 @@ extern const char* strresGetString(const struct STR_RES *psRes, int id);
* @return the string associated with the given @c ID string, or NULL if none
* could be found.
*/
extern const char* strresGetStringByID(const struct STR_RES* psRes, const char* ID);
extern const char* strresGetString(const struct STR_RES* psRes, const char* ID);
/* Load a string resource file */
extern BOOL strresLoad(struct STR_RES* psRes, const char* fileName);
/* Get the ID string for a string */
extern int strresGetIDfromString(struct STR_RES *psRes, const char *pString);
extern const char* strresGetIDfromString(struct STR_RES *psRes, const char *pString);
#endif

View File

@ -39,7 +39,6 @@ typedef struct TREAP_NODE
const char* key; //< The key to sort the node on
unsigned int priority; //< Treap priority
const char* string; //< The string stored in the treap
int id; //< An ID number that can be used to refer to these strings
struct TREAP_NODE *psLeft, *psRight; //< The sub trees
} TREAP_NODE;
@ -137,7 +136,7 @@ static void treapAddNode(TREAP_NODE **ppsRoot, TREAP_NODE *psNew)
/* Add an object to a treap
*/
BOOL treapAdd(TREAP_NODE** psTreap, const char* key, const char* string, int id)
BOOL treapAdd(TREAP_NODE** psTreap, const char* key, const char* string)
{
/* Over-allocate so that we can put the key and the string in the same
* chunck of memory as the TREAP_NODE struct. Which means a single
@ -156,8 +155,6 @@ BOOL treapAdd(TREAP_NODE** psTreap, const char* key, const char* string, int id)
psNew->key = strcpy((char*)(psNew + 1), key);
psNew->string = strcpy((char*)(psNew + 1) + key_size, string);
psNew->id = id;
psNew->priority = rand();
psNew->psLeft = NULL;
psNew->psRight = NULL;
@ -204,64 +201,34 @@ const char* treapFind(TREAP_NODE** psTreap, const char *key)
return treapFindRec(*psTreap, key);
}
static const char* treapFindByIDRec(TREAP_NODE const * const psNode, const int id)
static const char* treapFindKeyRec(TREAP_NODE const * const psNode, const char * const string)
{
const char* str;
const char* key;
if (psNode == NULL)
{
return NULL;
}
if (psNode->id == id)
{
return psNode->string;
}
str = treapFindByIDRec(psNode->psLeft, id);
if (str)
{
return str;
}
return treapFindByIDRec(psNode->psRight, id);
}
const char* treapFindByID(TREAP_NODE** psTreap, int id)
{
ASSERT(psTreap != NULL, "Invalid treap pointer!");
return treapFindByIDRec(*psTreap, id);
}
static int treapFindIDRec(TREAP_NODE const * const psNode, const char * const string)
{
int id;
if (psNode == NULL)
{
return -1;
}
if (strcmp(psNode->string, string) == 0)
{
return psNode->id;
return psNode->key;
}
id = treapFindIDRec(psNode->psLeft, string);
if (id != -1)
key = treapFindKeyRec(psNode->psLeft, string);
if (key)
{
return id;
return key;
}
return treapFindIDRec(psNode->psRight, string);
return treapFindKeyRec(psNode->psLeft, string);
}
int treapFindID(TREAP_NODE** psTreap, const char* string)
const char* treapFindKey(TREAP_NODE** psTreap, const char* string)
{
ASSERT(psTreap != NULL, "Invalid treap pointer!");
return treapFindIDRec(*psTreap, string);
return treapFindKeyRec(*psTreap, string);
}
/* Recursively free a treap */

View File

@ -45,16 +45,13 @@ extern struct TREAP_NODE** treapCreate(void);
/* Add an object to a treap
*/
extern BOOL treapAdd(struct TREAP_NODE** psTreap, const char *key, const char* string, int id);
extern BOOL treapAdd(struct TREAP_NODE** psTreap, const char *key, const char* string);
/* Find an object in a treap */
extern const char* treapFind(struct TREAP_NODE** psTreap, const char *key);
/** Find the string associated with the given ID number */
extern const char* treapFindByID(struct TREAP_NODE** psTreap, int id);
/** Find the ID number associated with the given string (if any) */
extern int treapFindID(struct TREAP_NODE** psTreap, const char* string);
/** Find the key associated with the given string number */
extern const char* treapFindKey(struct TREAP_NODE** psTreap, const char* string);
/* Destroy a treap and release all the memory associated with it */
extern void treapDestroy(struct TREAP_NODE** psTreap);

View File

@ -4256,7 +4256,7 @@ const char* getTemplateName(const DROID_TEMPLATE *psTemplate)
/* See if the name has a string resource associated with it by trying
* to get the string resource.
*/
const char * const pNameID = strresGetStringByID(psStringRes, psTemplate->aName);
const char * const pNameID = strresGetString(psStringRes, psTemplate->aName);
// If we couldn't find a string resource, return the name passed in
if (!pNameID)
@ -4287,7 +4287,7 @@ BOOL getDroidResourceName(char *pName)
/* See if the name has a string resource associated with it by trying
* to get the string resource.
*/
const char * const name = strresGetStringByID(psStringRes, pName);
const char * const name = strresGetString(psStringRes, pName);
if (!name)
{

View File

@ -5166,7 +5166,7 @@ DROID_TEMPLATE *FindDroidTemplate(const char * const name)
DROID_TEMPLATE *Template;
// get the name from the resource associated with it
const char * const nameStr = strresGetStringByID(psStringRes, name);
const char * const nameStr = strresGetString(psStringRes, name);
if (!nameStr)
{
debug( LOG_ERROR, "Cannot find resource for template - %s", name );
@ -11662,10 +11662,12 @@ BOOL writeFiresupportDesignators(char *pFileName)
// write the event state to a file on disk
static BOOL writeScriptState(char *pFileName)
{
static const int32_t current_event_version = 4;
char *pBuffer;
UDWORD fileSize;
if (!eventSaveState(3, &pBuffer, &fileSize))
if (!eventSaveState(current_event_version, &pBuffer, &fileSize))
{
return false;
}

View File

@ -545,7 +545,7 @@ VIEWDATA *loadViewData(const char *pViewMsgData, UDWORD bufferSize)
pViewMsgData += cnt;
// Get the string from the ID string
psViewData->ppTextMsg[dataInc] = strresGetStringByID(psStringRes, name);
psViewData->ppTextMsg[dataInc] = strresGetString(psStringRes, name);
if (!psViewData->ppTextMsg[dataInc])
{
ASSERT(!"Cannot find string resource", "Cannot find the view data string with id \"%s\"", name);
@ -697,7 +697,7 @@ VIEWDATA *loadViewData(const char *pViewMsgData, UDWORD bufferSize)
pViewMsgData += cnt;
// Get the string from the ID string
psViewReplay->pSeqList[dataInc].ppTextMsg[seqInc] = strresGetStringByID(psStringRes, name);
psViewReplay->pSeqList[dataInc].ppTextMsg[seqInc] = strresGetString(psStringRes, name);
if (!psViewReplay->pSeqList[dataInc].ppTextMsg[seqInc])
{
ASSERT(!"Cannot find string resource", "Cannot find the view data string with id \"%s\"", name);

View File

@ -856,29 +856,20 @@ BOOL scrValDefSave(INTERP_VAL *psVal, char *pBuffer, UDWORD *pSize)
*pSize = sizeof(UDWORD);
break;
case ST_TEXTSTRING:
{
const char * const idStr = psVal->v.sval ? strresGetIDfromString(psStringRes, psVal->v.sval) : NULL;
uint16_t len = idStr ? strlen(idStr) + 1 : 0;
if (pBuffer)
{
if (psVal->v.sval == NULL)
{
*((UDWORD*)pBuffer) = UDWORD_MAX;
}
else
{
const int strID = strresGetIDfromString(psStringRes, psVal->v.sval);
*((uint16_t*)pBuffer) = len;
endian_uword((uint16_t*)pBuffer);
if (strID == -1)
{
*((UDWORD*)pBuffer) = UDWORD_MAX;
memcpy(pBuffer + sizeof(len), idStr, len);
}
else
{
*((UDWORD*)pBuffer) = strID;
}
}
endian_udword((UDWORD*)pBuffer);
}
*pSize = sizeof(UDWORD);
*pSize = sizeof(len) + len;
break;
}
case ST_LEVEL:
if (psVal->v.sval != NULL)
{
@ -1190,14 +1181,30 @@ BOOL scrValDefLoad(SDWORD version, INTERP_VAL *psVal, char *pBuffer, UDWORD size
}
break;
case ST_TEXTSTRING:
if (version < 4)
{
if (size != sizeof(UDWORD))
{
debug(LOG_ERROR, "Data size is too small, %u is expected, but %u is provided", (unsigned int)(sizeof(UDWORD)), (unsigned int)size);
return false;
}
id = *((UDWORD*)pBuffer);
endian_udword(&id);
if (id == UDWORD_MAX)
{
psVal->v.sval = '\0';
psVal->v.sval = NULL;
}
else
{
/* This code is commented out, because it depends on assigning the
* id-th loaded string from the string resources. And from version
* 4 of this file format onward, we do not count strings anymore.
*
* Thus loading of these strings is practically impossible.
*/
#if 0
const char * const str = strresGetString(psStringRes, id);
if (!str)
{
@ -1206,6 +1213,71 @@ BOOL scrValDefLoad(SDWORD version, INTERP_VAL *psVal, char *pBuffer, UDWORD size
return false;
}
psVal->v.sval = strdup(str);
if (!psVal->v.sval)
{
debug(LOG_ERROR, "Out of memory");
abort();
return false;
}
#else
debug(LOG_ERROR, "Incompatible savegame format version %u, should be at least version 4", (unsigned int)version);
return false;
#endif
}
}
else
{
const char* str;
char* idStr;
uint16_t len;
if (size < sizeof(len))
{
debug(LOG_ERROR, "Data size is too small, %u is expected, but %u is provided", (unsigned int)(sizeof(len)), (unsigned int)size);
return false;
}
len = *((uint16_t*)pBuffer);
endian_uword(&len);
if (size < sizeof(len) + len)
{
debug(LOG_ERROR, "Data size is too small, %u is expected, but %u is provided", (unsigned int)(sizeof(len) + len), (unsigned int)size);
return false;
}
if (len == 0)
{
psVal->v.sval = NULL;
return true;
}
idStr = malloc(len);
if (!idStr)
{
debug(LOG_ERROR, "Out of memory (tried to allocate %u bytes)", (unsigned int)len);
// Don't abort() here, as this might be the result from a bad "len" field in the data
return false;
}
memcpy(idStr, pBuffer + sizeof(len), len);
if (idStr[len - 1] != '\0')
{
debug(LOG_WARNING, "Non-NUL terminated string encountered!");
}
idStr[len - 1] = '\0';
str = strresGetString(psStringRes, idStr);
if (!str)
{
debug(LOG_ERROR, "Couldn't find string with id \"%s\"", idStr);
free(idStr);
return false;
}
free(idStr);
psVal->v.sval = strdup(str);
if (!psVal->v.sval)
{

View File

@ -627,7 +627,7 @@ var_init: var_entry TYPE var_value
yyerror("Typemismatch for variable %d", $1);
YYABORT;
}
pString = strresGetStringByID(psStringRes, $3.pString);
pString = strresGetString(psStringRes, $3.pString);
if (!pString)
{
yyerror("Cannot find the string for id \"%s\"", $3.pString);

View File

@ -2615,7 +2615,7 @@ const char* getName(const char *pNameID)
/* See if the name has a string resource associated with it by trying
* to get the string resource.
*/
const char * const name = strresGetStringByID(psStringRes, pNameID);
const char * const name = strresGetString(psStringRes, pNameID);
if (!name)
{
debug( LOG_ERROR, "Unable to find string resource for %s", pNameID );
@ -2819,7 +2819,7 @@ char* allocateName(const char* name)
/* Check whether the given string has a string resource associated with
* it.
*/
if (!strresGetStringByID(psStringRes, name))
if (!strresGetString(psStringRes, name))
{
debug(LOG_ERROR, "Unable to find string resource for %s", name);
abort();