Maelstrom: Added some convenience functions for loading data from XML

https://github.com/libsdl-org/Maelstrom/commit/833339bcceb46cc7d4d38e56b0348faad7d98d55

From 833339bcceb46cc7d4d38e56b0348faad7d98d55 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 29 Oct 2011 01:35:55 -0400
Subject: [PATCH] Added some convenience functions for loading data from XML

---
 screenlib/UIElement.cpp       | 64 +++++++++++++++++++++++++++--------
 screenlib/UIElement.h         |  5 ++-
 screenlib/UIElementButton.cpp | 16 +++------
 screenlib/UIElementLabel.cpp  | 19 ++---------
 screenlib/UIElementLine.cpp   |  5 +--
 screenlib/UIElementRect.cpp   | 15 ++------
 6 files changed, 64 insertions(+), 60 deletions(-)

diff --git a/screenlib/UIElement.cpp b/screenlib/UIElement.cpp
index 6a3edf8d..be4f4089 100644
--- a/screenlib/UIElement.cpp
+++ b/screenlib/UIElement.cpp
@@ -41,32 +41,66 @@ UIElement::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
 		return false;
 	}
 
-	attr = node->first_attribute("name", 0, false);
-	if (attr) {
-		SDL_free(m_name);
-		m_name = SDL_strdup(attr->value());
-	}
+	LoadString(node, "name", m_name);
 
 	return true;
 }
 
-Uint32
-UIElement::LoadColor(rapidxml::xml_node<> *node) const
+bool
+UIElement::LoadBool(rapidxml::xml_node<> *node, const char *name, bool &value)
 {
-	Uint8 r, g, b;
 	rapidxml::xml_attribute<> *attr;
 
-	attr = node->first_attribute("r", 0, false);
+	attr = node->first_attribute(name, 0, false);
 	if (attr) {
-		r = (Uint8)strtol(attr->value(), NULL, 0);
+		const char *text = attr->value();
+		if (*text == '\0' || *text == '0' ||
+		    *text == 'f' || *text == 'F') {
+			value = false;
+		} else {
+			value = true;
+		}
 	}
-	attr = node->first_attribute("g", 0, false);
+}
+
+bool
+UIElement::LoadNumber(rapidxml::xml_node<> *node, const char *name, int &value)
+{
+	rapidxml::xml_attribute<> *attr;
+
+	attr = node->first_attribute(name, 0, false);
 	if (attr) {
-		g = (Uint8)strtol(attr->value(), NULL, 0);
+		value = (int)strtol(attr->value(), NULL, 0);
 	}
-	attr = node->first_attribute("b", 0, false);
+}
+
+bool
+UIElement::LoadString(rapidxml::xml_node<> *node, const char *name, char *&value)
+{
+	rapidxml::xml_attribute<> *attr;
+
+	attr = node->first_attribute(name, 0, false);
 	if (attr) {
-		b = (Uint8)strtol(attr->value(), NULL, 0);
+		if (value) {
+			SDL_free(value);
+		}
+		value = SDL_strdup(attr->value());
+	}
+}
+
+bool
+UIElement::LoadColor(rapidxml::xml_node<> *node, const char *name, Uint32 &value)
+{
+	rapidxml::xml_node<> *child;
+
+	child = node->first_node("color", 0, false);
+	if (child) {
+		rapidxml::xml_attribute<> *attr;
+		int r = 0xFF, g = 0xFF, b = 0xFF;
+
+		LoadNumber(child, "r", r);
+		LoadNumber(child, "g", g);
+		LoadNumber(child, "b", b);
+		value = m_screen->MapRGB(r, g, b);
 	}
-	return m_screen->MapRGB(r, g, b);
 }
diff --git a/screenlib/UIElement.h b/screenlib/UIElement.h
index 71e5567d..5192ecdd 100644
--- a/screenlib/UIElement.h
+++ b/screenlib/UIElement.h
@@ -40,7 +40,10 @@ class UIElement : public UIBaseElement
 	virtual bool Load(rapidxml::xml_node<> *node, const UITemplates *templates);
 
 protected:
-	Uint32 LoadColor(rapidxml::xml_node<> *node) const;
+	bool LoadBool(rapidxml::xml_node<> *node, const char *name, bool &value);
+	bool LoadNumber(rapidxml::xml_node<> *node, const char *name, int &value);
+	bool LoadString(rapidxml::xml_node<> *node, const char *name, char *&value);
+	bool LoadColor(rapidxml::xml_node<> *node, const char *name, Uint32 &value);
 
 protected:
 	static UIElementType s_elementType;
diff --git a/screenlib/UIElementButton.cpp b/screenlib/UIElementButton.cpp
index 23c752dd..db14df8f 100644
--- a/screenlib/UIElementButton.cpp
+++ b/screenlib/UIElementButton.cpp
@@ -61,7 +61,7 @@ UIElementButton::~UIElementButton()
 	SetButtonDelegate(NULL);
 
 	if (m_clickPanel) {
-		delete[] m_clickPanel;
+		SDL_free(m_clickPanel);
 	}
 }
 
@@ -107,16 +107,10 @@ UIElementButton::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
 		}
 	}
 
-	attr = node->first_attribute("clickSound", 0, false);
-	if (attr) {
-		m_clickSound = atoi(attr->value());
-	}
-	attr = node->first_attribute("clickPanel", 0, false);
-	if (attr) {
-		const char *value = attr->value();
-		m_clickPanel = new char[strlen(value)+1];
-		strcpy(m_clickPanel, value);
-	}
+	
+	LoadNumber(node, "clickSound", m_clickSound);
+	LoadString(node, "clickPanel", m_clickPanel);
+
 	return true;
 }
 
diff --git a/screenlib/UIElementLabel.cpp b/screenlib/UIElementLabel.cpp
index 48dd5da9..e29b641e 100644
--- a/screenlib/UIElementLabel.cpp
+++ b/screenlib/UIElementLabel.cpp
@@ -51,28 +51,15 @@ UIElementLabel::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
 		return false;
 	}
 
-	attr = node->first_attribute("fontName", 0, false);
-	if (attr) {
-		if (m_fontName) {
-			SDL_free(m_fontName);
-		}
-		m_fontName = SDL_strdup(attr->value());
-	}
-
-	attr = node->first_attribute("fontSize", 0, false);
-	if (attr) {
-		m_fontSize = SDL_atoi(attr->value());
-	}
+	LoadString(node, "fontName", m_fontName);
+	LoadNumber(node, "fontSize", m_fontSize);
 
 	attr = node->first_attribute("fontStyle", 0, false);
 	if (attr) {
 		m_fontStyle = ParseStyle(attr->value());
 	}
 
-	child = node->first_node("color", 0, false);
-	if (child) {
-		m_color = LoadColor(child);
-	}
+	LoadColor(node, "color", m_color);
 
 	attr = node->first_attribute("text", 0, false);
 	if (attr) {
diff --git a/screenlib/UIElementLine.cpp b/screenlib/UIElementLine.cpp
index 0e1288d5..e89f0b67 100644
--- a/screenlib/UIElementLine.cpp
+++ b/screenlib/UIElementLine.cpp
@@ -20,10 +20,7 @@ UIElementLine::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
 		return false;
 	}
 
-	child = node->first_node("color", 0, false);
-	if (child) {
-		m_color = LoadColor(child);
-	}
+	LoadColor(node, "color", m_color);
 
 	return true;
 }
diff --git a/screenlib/UIElementRect.cpp b/screenlib/UIElementRect.cpp
index 2ca0636d..26f28910 100644
--- a/screenlib/UIElementRect.cpp
+++ b/screenlib/UIElementRect.cpp
@@ -22,19 +22,8 @@ UIElementRect::Load(rapidxml::xml_node<> *node, const UITemplates *templates)
 		return false;
 	}
 
-	attr = node->first_attribute("fill", 0, false);
-	if (attr) {
-		const char *value = attr->value();
-
-		if (*value == '1' || *value == 't' || *value == 'T') {
-			m_fill = true;
-		}
-	}
-
-	child = node->first_node("color", 0, false);
-	if (child) {
-		m_color = LoadColor(child);
-	}
+	LoadBool(node, "fill", m_fill);
+	LoadColor(node, "color", m_color);
 
 	return true;
 }