Changeset - r5142:6842a881353e
[Not reviewed]
master
0 3 0
Darkvater - 18 years ago 2006-11-21 20:23:57
darkvater@openttd.org
(svn r7232) -Codechange: Also allow for the save/load of non pre-allocated strings inside structs.
3 files changed with 30 insertions and 17 deletions:
0 comments (0 inline, 0 general)
saveload.c
Show inline comments
 
@@ -484,13 +484,14 @@ static void SlSaveLoadConv(void *ptr, Va
 
}
 

	
 
/** Calculate the net length of a string. This is in almost all cases
 
 * just strlen(), but if the string is not properly terminated, we'll
 
 * resort to the maximum length of the buffer.
 
 * @param ptr pointer to the stringbuffer
 
 * @param length maximum length of the string (buffer)
 
 * @param length maximum length of the string (buffer). If -1 we don't care
 
 * about a maximum length, but take string length as it is.
 
 * @return return the net length of the string */
 
static inline size_t SlCalcNetStringLen(const char *ptr, size_t length)
 
{
 
	return minu(strlen(ptr), length - 1);
 
}
 

	
 
@@ -502,16 +503,27 @@ static inline size_t SlCalcNetStringLen(
 
 * @return return the gross length of the string */
 
static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv)
 
{
 
	size_t len;
 
	const char *str;
 

	
 
	conv = GetVarMemType(conv);
 
	/* For strings without a pre-allocated buffer, we need an extra indirection of course */
 
	str = (conv == SLE_VAR_STR || conv == SLE_VAR_STRQ) ? *(const char**)ptr : (const char*)ptr;
 
	len = SlCalcNetStringLen(str, length);
 
	switch (GetVarMemType(conv)) {
 
		default: NOT_REACHED();
 
		case SLE_VAR_STR:
 
		case SLE_VAR_STRQ:
 
			str = *(const char**)ptr;
 
			len = -1;
 
			break;
 
		case SLE_VAR_STRB:
 
		case SLE_VAR_STRBQ:
 
			str = (const char*)ptr;
 
			len = length;
 
			break;
 
	}
 

	
 
	len = SlCalcNetStringLen(str, len);
 
	return len + SlGetArrayLength(len); // also include the length of the index
 
}
 

	
 
/**
 
 * Save/Load a string.
 
 * @param ptr the string being manipulated
 
@@ -520,30 +532,31 @@ static inline size_t SlCalcStringLen(con
 
static void SlString(void *ptr, size_t length, VarType conv)
 
{
 
	size_t len;
 

	
 
	if (_sl.save) { /* SAVE string */
 
		switch (GetVarMemType(conv)) {
 
			default: NOT_REACHED();
 
			case SLE_VAR_STRB:
 
			case SLE_VAR_STRBQ:
 
				len = SlCalcNetStringLen(ptr, length);
 
				break;
 
			case SLE_VAR_STR:
 
			case SLE_VAR_STRQ:
 
				ptr = *(char**)ptr;
 
				len = SlCalcNetStringLen(ptr, 0);
 
				len = SlCalcNetStringLen(ptr, -1);
 
				break;
 
			default: NOT_REACHED();
 
		}
 

	
 
		SlWriteArrayLength(len);
 
		SlCopyBytes(ptr, len);
 
	} else { /* LOAD string */
 
		len = SlReadArrayLength();
 

	
 
		switch (GetVarMemType(conv)) {
 
			default: NOT_REACHED();
 
			case SLE_VAR_STRB:
 
			case SLE_VAR_STRBQ:
 
				if (len >= length) {
 
					DEBUG(misc, 0) ("[Sl] String length in savegame is bigger than buffer, truncating");
 
					SlCopyBytes(ptr, length);
 
					SlSkipBytes(len - length);
 
@@ -556,13 +569,12 @@ static void SlString(void *ptr, size_t l
 
			case SLE_VAR_STRQ: /* Malloc'd string, free previous incarnation, and allocate */
 
				free(*(char**)ptr);
 
				*(char**)ptr = malloc(len + 1); // terminating '\0'
 
				ptr = *(char**)ptr;
 
				SlCopyBytes(ptr, len);
 
				break;
 
			default: NOT_REACHED();
 
		}
 

	
 
		((char*)ptr)[len] = '\0'; // properly terminate the string
 
	}
 
}
 

	
 
@@ -639,24 +651,24 @@ static inline bool SlSkipVariableOnLoad(
 
}
 

	
 
/**
 
 * Calculate the size of an object.
 
 * @param sld The @SaveLoad description of the object so we know how to manipulate it
 
 */
 
static size_t SlCalcObjLength(const SaveLoad *sld)
 
static size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
 
{
 
	size_t length = 0;
 

	
 
	// Need to determine the length and write a length tag.
 
	for (; sld->cmd != SL_END; sld++) {
 
		length += SlCalcObjMemberLength(sld);
 
		length += SlCalcObjMemberLength(object, sld);
 
	}
 
	return length;
 
}
 

	
 
size_t SlCalcObjMemberLength(const SaveLoad *sld)
 
size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
 
{
 
	assert(_sl.save);
 

	
 
	switch (sld->cmd) {
 
		case SL_VAR:
 
		case SL_REF:
 
@@ -666,18 +678,18 @@ size_t SlCalcObjMemberLength(const SaveL
 
			if (!SlIsObjectValidInSavegame(sld)) break;
 

	
 
			switch (sld->cmd) {
 
			case SL_VAR: return SlCalcConvFileLen(sld->conv);
 
			case SL_REF: return SlCalcRefLen();
 
			case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv);
 
			case SL_STR: return SlCalcStringLen(sld->address, sld->length, sld->conv);
 
			case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv);
 
			default: NOT_REACHED();
 
			}
 
			break;
 
		case SL_WRITEBYTE: return 1; // a byte is logically of size 1
 
		case SL_INCLUDE: return SlCalcObjLength(_sl.includes[sld->version_from]);
 
		case SL_INCLUDE: return SlCalcObjLength(object, _sl.includes[sld->version_from]);
 
		default: NOT_REACHED();
 
	}
 
	return 0;
 
}
 

	
 

	
 
@@ -743,13 +755,13 @@ bool SlObjectMember(void *ptr, const Sav
 
 * @param sld The @SaveLoad description of the object so we know how to manipulate it
 
 */
 
void SlObject(void *object, const SaveLoad *sld)
 
{
 
	// Automatically calculate the length?
 
	if (_sl.need_length != NL_NONE) {
 
		SlSetLength(SlCalcObjLength(sld));
 
		SlSetLength(SlCalcObjLength(object, sld));
 
		if (_sl.need_length == NL_CALCLENGTH) return;
 
	}
 

	
 
	for (; sld->cmd != SL_END; sld++) {
 
		void *ptr = GetVariableAddress(object, sld);
 
		SlObjectMember(ptr, sld);
 
@@ -760,13 +772,13 @@ void SlObject(void *object, const SaveLo
 
 * Save or Load (a list of) global variables
 
 * @param desc The global variable that is being loaded or saved
 
 */
 
void SlGlobList(const SaveLoadGlobVarList *sldg)
 
{
 
	if (_sl.need_length != NL_NONE) {
 
		SlSetLength(SlCalcObjLength((const SaveLoad*)sldg));
 
		SlSetLength(SlCalcObjLength(NULL, (const SaveLoad*)sldg));
 
		if (_sl.need_length == NL_CALCLENGTH) return;
 
	}
 

	
 
	for (; sldg->cmd != SL_END; sldg++) {
 
		SlObjectMember(sldg->address, (const SaveLoad*)sldg);
 
	}
saveload.h
Show inline comments
 
@@ -286,13 +286,13 @@ void WriteValue(void *ptr, VarType conv,
 
void SlSetArrayIndex(uint index);
 
int SlIterateArray(void);
 

	
 
void SlAutolength(AutolengthProc *proc, void *arg);
 
uint SlGetFieldLength(void);
 
void SlSetLength(size_t length);
 
size_t SlCalcObjMemberLength(const SaveLoad *sld);
 
size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld);
 

	
 
byte SlReadByte(void);
 
void SlWriteByte(byte b);
 

	
 
void SlGlobList(const SaveLoadGlobVarList *sldg);
 
void SlArray(void *array, uint length, VarType conv);
settings.c
Show inline comments
 
@@ -1714,13 +1714,14 @@ static void SaveSettings(const SettingDe
 
{
 
	/* We need to write the CH_RIFF header, but unfortunately can't call
 
	 * SlCalcLength() because we have a different format. So do this manually */
 
	const SettingDesc *i;
 
	size_t length = 0;
 
	for (i = sd; i->save.cmd != SL_END; i++) {
 
		length += SlCalcObjMemberLength(&i->save);
 
		const void *ptr = GetVariableAddress(object, &i->save);
 
		length += SlCalcObjMemberLength(ptr, &i->save);
 
	}
 
	SlSetLength(length);
 

	
 
	for (i = sd; i->save.cmd != SL_END; i++) {
 
		void *ptr = GetVariableAddress(object, &i->save);
 
		SlObjectMember(ptr, &i->save);
0 comments (0 inline, 0 general)