[perl-Glib] GPerlArgv: hide internal parts



commit a78526d7cc4ef6b455953e4d30c2455ddccde74c
Author: Torsten SchÃnfeld <kaffeetisch gmx de>
Date:   Sat Jan 5 23:27:11 2013 +0100

    GPerlArgv: hide internal parts
    
    Move the "shadow" copies from the public struct into a private struct.
    Technically, this is an API change.  But "shadow" is not useful outside of Glib
    itself, so nobody should be using it.
    
    This is in preparation for an upcoming fix that necessitates expanding the
    GPerlArgv struct.

 Glib.xs |   38 +++++++++++++++++++++++++++++++-------
 gperl.h |    2 +-
 2 files changed, 32 insertions(+), 8 deletions(-)
---
diff --git a/Glib.xs b/Glib.xs
index 01559fe..5dfe083 100644
--- a/Glib.xs
+++ b/Glib.xs
@@ -179,6 +179,15 @@ gperl_str_hash (gconstpointer key)
 	return h;
 }
 
+/* --- GPerlArgv ----------------------------------------------------------- */
+
+typedef struct {
+	/* Shadow copies of the pointers to the copies of the strings in argv.
+	 * Used to free the copied strings reliably even if they are removed
+	 * from argv. */
+	char **shadows;
+} GPerlArgvPriv;
+
 =item GPerlArgv * gperl_argv_new ()
 
 Creates a new Perl argv object whose members can then be passed to functions
@@ -197,6 +206,7 @@ gperl_argv_new ()
 	SV * ARGV0;
 	int len, i;
 	GPerlArgv *pargv;
+	GPerlArgvPriv *priv;
 
 	pargv = g_new (GPerlArgv, 1);
 
@@ -224,16 +234,21 @@ gperl_argv_new ()
 	len = av_len (ARGV) + 1;
 
 	pargv->argc = len + 1;
-	pargv->shadow = g_new0 (char*, pargv->argc);
 	pargv->argv = g_new0 (char*, pargv->argc);
 
+	priv = g_new (GPerlArgvPriv, 1);
+	priv->shadows = g_new0 (char*, pargv->argc);
+	pargv->priv = priv;
+
 	pargv->argv[0] = SvPV_nolen (ARGV0);
 
 	for (i = 0 ; i < len ; i++) {
 		SV ** svp = av_fetch (ARGV, i, 0);
-		if (svp && gperl_sv_is_defined (*svp))
-			pargv->shadow[i] = pargv->argv[i+1]
-			                 = g_strdup (SvPV_nolen (*svp));
+		if (svp && gperl_sv_is_defined (*svp)) {
+			const char *arg = SvPV_nolen (*svp);
+			priv->shadows[i] = pargv->argv[i+1]
+			                 = g_strdup (arg);
+		}
 	}
 
 	return pargv;
@@ -247,6 +262,7 @@ Updates @ARGV to resemble the stored argv array.
 void
 gperl_argv_update (GPerlArgv *pargv)
 {
+	GPerlArgvPriv *priv = pargv->priv;
 	AV * ARGV;
 	int i;
 
@@ -254,8 +270,12 @@ gperl_argv_update (GPerlArgv *pargv)
 
 	/* clear and refill @ARGV with whatever gtk_init didn't steal. */
 	av_clear (ARGV);
-	for (i = 1 ; i < pargv->argc ; i++)
-		av_push (ARGV, newSVpv (pargv->argv[i], 0));
+	for (i = 1 ; i < pargv->argc ; i++) {
+		SV *sv;
+		const char *arg = pargv->argv[i];
+		sv = newSVpv (arg, PL_na);
+		av_push (ARGV, sv);
+	}
 }
 
 =item void gperl_argv_free (GPerlArgv *pargv)
@@ -266,11 +286,15 @@ Frees any resources associated with I<pargv>.
 void
 gperl_argv_free (GPerlArgv *pargv)
 {
-	g_strfreev (pargv->shadow);
+	GPerlArgvPriv *priv = pargv->priv;
+	g_strfreev (priv->shadows);
+	g_free (pargv->priv);
 	g_free (pargv->argv);
 	g_free (pargv);
 }
 
+/* ------------------------------------------------------------------------- */
+
 =item char * gperl_format_variable_for_output (SV * sv)
 
 Formats the variable stored in I<sv> for output in error messages.  Like
diff --git a/gperl.h b/gperl.h
index 592e332..27994eb 100644
--- a/gperl.h
+++ b/gperl.h
@@ -405,7 +405,7 @@ guint    gperl_str_hash (gconstpointer key);
 typedef struct {
   int argc;
   char **argv;
-  char **shadow;
+  void *priv;
 } GPerlArgv;
 
 GPerlArgv * gperl_argv_new ();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]