From 98ea4d3d5182b6de0bafb281e3bd4db23fb15437 Mon Sep 17 00:00:00 2001
From: Randy Heit <rheit@zdoom.fake>
Date: Sun, 17 Mar 2013 03:04:17 +0000
Subject: [PATCH] - Added C_GetMassCVarString(), which C_WriteCVars() is now a
 wrapper around. (And the latter   should probably be factored away
 eventually.)

SVN r4185 (trunk)
---
 src/c_cvars.cpp | 46 +++++++++++++++++++++++++---------------------
 src/c_cvars.h   |  6 +++++-
 src/g_game.cpp  |  7 ++-----
 3 files changed, 32 insertions(+), 27 deletions(-)

diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp
index f63b74bd24..b07baa6daa 100644
--- a/src/c_cvars.cpp
+++ b/src/c_cvars.cpp
@@ -1274,52 +1274,56 @@ static int STACK_ARGS sortcvars (const void *a, const void *b)
 
 void FilterCompactCVars (TArray<FBaseCVar *> &cvars, DWORD filter)
 {
-	FBaseCVar *cvar = CVars;
-	while (cvar)
+	// Accumulate all cvars that match the filter flags.
+	for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->m_Next)
 	{
 		if (cvar->Flags & filter)
-			cvars.Push (cvar);
-		cvar = cvar->m_Next;
+			cvars.Push(cvar);
 	}
-	if (cvars.Size () > 0)
+	// Now sort them, so they're in a deterministic order and not whatever
+	// order the linker put them in.
+	if (cvars.Size() > 0)
 	{
-		cvars.ShrinkToFit ();
-		qsort (&cvars[0], cvars.Size(), sizeof(FBaseCVar *), sortcvars);
+		qsort(&cvars[0], cvars.Size(), sizeof(FBaseCVar *), sortcvars);
 	}
 }
 
 void C_WriteCVars (BYTE **demo_p, DWORD filter, bool compact)
 {
-	FBaseCVar *cvar = CVars;
-	BYTE *ptr = *demo_p;
+	FString dump = C_GetMassCVarString(filter, compact);
+	size_t dumplen = dump.Len() + 1;	// include terminating \0
+	memcpy(*demo_p, dump.GetChars(), dumplen);
+	*demo_p += dumplen;
+}
+
+FString C_GetMassCVarString (DWORD filter, bool compact)
+{
+	FBaseCVar *cvar;
+	FString dump;
 
 	if (compact)
 	{
 		TArray<FBaseCVar *> cvars;
-		ptr += sprintf ((char *)ptr, "\\\\%ux", filter);
-		FilterCompactCVars (cvars, filter);
+		dump.AppendFormat("\\\\%ux", filter);
+		FilterCompactCVars(cvars, filter);
 		while (cvars.Pop (cvar))
 		{
-			UCVarValue val = cvar->GetGenericRep (CVAR_String);
-			ptr += sprintf ((char *)ptr, "\\%s", val.String);
+			UCVarValue val = cvar->GetGenericRep(CVAR_String);
+			dump << '\\' << val.String;
 		}
 	}
 	else
 	{
-		cvar = CVars;
-		while (cvar)
+		for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next)
 		{
 			if ((cvar->Flags & filter) && !(cvar->Flags & CVAR_NOSAVE))
 			{
-				UCVarValue val = cvar->GetGenericRep (CVAR_String);
-				ptr += sprintf ((char *)ptr, "\\%s\\%s",
-					cvar->GetName (), val.String);
+				UCVarValue val = cvar->GetGenericRep(CVAR_String);
+				dump << '\\' << cvar->GetName() << '\\' << val.String;
 			}
-			cvar = cvar->m_Next;
 		}
 	}
-
-	*demo_p = ptr + 1;
+	return dump;
 }
 
 void C_ReadCVars (BYTE **demo_p)
diff --git a/src/c_cvars.h b/src/c_cvars.h
index b5b0c6ccf7..9c7873802c 100644
--- a/src/c_cvars.h
+++ b/src/c_cvars.h
@@ -150,7 +150,7 @@ private:
 	static bool m_UseCallback;
 	static bool m_DoNoSet;
 
-	friend void C_WriteCVars (BYTE **demo_p, uint32 filter, bool compact);
+	friend FString C_GetMassCVarString (uint32 filter, bool compact);
 	friend void C_ReadCVars (BYTE **demo_p);
 	friend void C_BackupCVars (void);
 	friend FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev);
@@ -162,6 +162,10 @@ private:
 	friend void C_DeinitConsole();
 };
 
+// Returns a string with all cvars whose flags match filter. In compact mode,
+// the cvar names are omitted to save space.
+FString C_GetMassCVarString (uint32 filter, bool compact=false);
+
 // Writes all cvars that could effect demo sync to *demo_p. These are
 // cvars that have either CVAR_SERVERINFO or CVAR_DEMOSAVE set.
 void C_WriteCVars (BYTE **demo_p, uint32 filter, bool compact=false);
diff --git a/src/g_game.cpp b/src/g_game.cpp
index 1f039763b0..e9d11151c0 100644
--- a/src/g_game.cpp
+++ b/src/g_game.cpp
@@ -2096,11 +2096,8 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
 	G_WriteHubInfo(stdfile);
 
 	{
-		BYTE vars[4096], *vars_p;
-		vars_p = vars;
-		C_WriteCVars (&vars_p, CVAR_SERVERINFO);
-		*vars_p = 0;
-		M_AppendPNGText (stdfile, "Important CVARs", (char *)vars);
+		FString vars = C_GetMassCVarString(CVAR_SERVERINFO);
+		M_AppendPNGText (stdfile, "Important CVARs", vars.GetChars());
 	}
 
 	if (level.time != 0 || level.maptime != 0)