pspp-dev
[Top][All Lists]
Advanced

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

[PATCH 2/2] gui: Make lex_gtk_text_buffer_read() count bytes, not charac


From: Ben Pfaff
Subject: [PATCH 2/2] gui: Make lex_gtk_text_buffer_read() count bytes, not characters.
Date: Sat, 5 May 2012 22:14:16 -0700

The N parameter to lex_gtk_text_buffer_read() is a count of bytes,
but the implementation treated it as characters.

Also fixes a memory leak, since gtk_text_iter_get_text()'s caller
is responsible for freeing the memory that it returns.

Reported by Alle <address@hidden>.
First investigated by John Darrington <address@hidden>.
---
This fixes the problem that I saw with valgrind, but I didn't see the
same problem as John, so I'd like some confirmation that it fixes
that problem too.

 src/ui/gui/psppire-lex-reader.c |   54 ++++++++++++++++++++++++++++----------
 1 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/src/ui/gui/psppire-lex-reader.c b/src/ui/gui/psppire-lex-reader.c
index ae043b0..d8e53c4 100644
--- a/src/ui/gui/psppire-lex-reader.c
+++ b/src/ui/gui/psppire-lex-reader.c
@@ -26,15 +26,24 @@
 
 #include "libpspp/cast.h"
 
+#include "gl/minmax.h"
+
 static const struct lex_reader_class lex_gtk_text_buffer_reader_class ;
 
 
 struct lex_gtk_text_buffer_reader
 {
   struct lex_reader reader;
+
+  /* The GtkTextBuffer from which we are reading. */
   GtkTextBuffer *buffer;
   GtkTextIter start;
   GtkTextIter stop;
+
+  /* Text pulled from part of the GtkTextBuffer. */
+  gchar *part;
+  gsize part_len;               /* Number of bytes in 'part'. */
+  gsize part_ofs;               /* Current offset into 'part'. */
 };
 
 static struct lex_gtk_text_buffer_reader *
@@ -57,6 +66,10 @@ lex_reader_for_gtk_text_buffer (GtkTextBuffer *buffer, 
GtkTextIter start, GtkTex
   r->start = start;
   r->stop = stop;
 
+  r->part = NULL;
+  r->part_len = 0;
+  r->part_ofs = 0;
+
   return &r->reader;
 }
 
@@ -66,26 +79,38 @@ lex_gtk_text_buffer_read (struct lex_reader *r_, char *buf, 
size_t n,
                  enum prompt_style prompt_style UNUSED)
 {
   struct lex_gtk_text_buffer_reader *r = lex_gtk_text_buffer_reader_cast (r_);
-  int n_chars = n;
-  char *s;
+  gsize chunk;
+
+  if (r->part_ofs == r->part_len)
+    {
+      /* Read up to N characters into r->part.  N characters might be more than
+         N bytes, but that's OK: we'll just buffer up some of those bytes for
+         the next read. */
+      int n_chars = n;
+
+      GtkTextIter iter = r->start ;
+
+      int offset = gtk_text_iter_get_offset (&iter);
+      int end_offset = gtk_text_iter_get_offset (&r->stop);
 
-  GtkTextIter iter = r->start ;
-  
-  int offset = gtk_text_iter_get_offset (&iter);
-  int end_offset = gtk_text_iter_get_offset (&r->stop);
+      if ( end_offset - offset < n)
+        n_chars = end_offset - offset;
 
-  if ( end_offset - offset < n)
-    n_chars = end_offset - offset;
-  
-  gtk_text_iter_set_offset (&iter, offset + n_chars);
+      gtk_text_iter_set_offset (&iter, offset + n_chars);
 
-  s = gtk_text_iter_get_text (&r->start, &iter);
+      g_free (r->part);
+      r->part = gtk_text_iter_get_text (&r->start, &iter);
+      r->part_len = strlen (r->part);
+      r->part_ofs = 0;
 
-  strncpy (buf, s, n_chars);
+      r->start = iter;
+    }
 
-  r->start = iter;
+  chunk = MIN (r->part_len - r->part_ofs, n);
+  memcpy (buf, r->part + r->part_ofs, chunk);
+  r->part_ofs += chunk;
 
-  return strlen (s);
+  return chunk;
 }
 
 
@@ -96,6 +121,7 @@ lex_gtk_text_buffer_close (struct lex_reader *r_)
   struct lex_gtk_text_buffer_reader *r = lex_gtk_text_buffer_reader_cast (r_);
 
   g_object_unref (r->buffer);
+  g_free (r->part);
 }
 
 
-- 
1.7.2.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]