summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBST 1999 Tony Gale <gale@gtk.org>1999-04-17 20:04:49 +0000
committerTony Gale <gale@src.gnome.org>1999-04-17 20:04:49 +0000
commit32aecf31a71601572137a1b6542bfcbc112c489b (patch)
treedc843ba3480739079126996724a3304e1db061cd
parentfb55f0056ea77efedcc51fe83552efcaf9ac3e93 (diff)
downloadglib-32aecf31a71601572137a1b6542bfcbc112c489b.tar.gz
Add new g_string functions for reading from file/socket descriptors, and
Sat Apr 17 20:55:13 BST 1999 Tony Gale <gale@gtk.org> * glib.h, gstring.c: Add new g_string functions for reading from file/socket descriptors, and tokenising strings. Added various g_string macros.
-rw-r--r--ChangeLog7
-rw-r--r--ChangeLog.pre-2-07
-rw-r--r--ChangeLog.pre-2-107
-rw-r--r--ChangeLog.pre-2-127
-rw-r--r--ChangeLog.pre-2-27
-rw-r--r--ChangeLog.pre-2-47
-rw-r--r--ChangeLog.pre-2-67
-rw-r--r--ChangeLog.pre-2-87
-rw-r--r--glib.h109
-rw-r--r--glib/glib.h109
-rw-r--r--glib/gstring.c222
-rw-r--r--gstring.c222
12 files changed, 648 insertions, 70 deletions
diff --git a/ChangeLog b/ChangeLog
index bd0c2cac2..b07bb2805 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Sat Apr 17 20:55:13 BST 1999 Tony Gale <gale@gtk.org>
+
+ * glib.h, gstring.c: Add new g_string functions for reading
+ from file/socket descriptors, and tokenising strings.
+
+ Added various g_string macros.
+
Tue Apr 13 23:28:32 1999 Tor Lillqvist <tml@iki.fi>
* README.win32: Mention the tests directory.
diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0
index bd0c2cac2..b07bb2805 100644
--- a/ChangeLog.pre-2-0
+++ b/ChangeLog.pre-2-0
@@ -1,3 +1,10 @@
+Sat Apr 17 20:55:13 BST 1999 Tony Gale <gale@gtk.org>
+
+ * glib.h, gstring.c: Add new g_string functions for reading
+ from file/socket descriptors, and tokenising strings.
+
+ Added various g_string macros.
+
Tue Apr 13 23:28:32 1999 Tor Lillqvist <tml@iki.fi>
* README.win32: Mention the tests directory.
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index bd0c2cac2..b07bb2805 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,10 @@
+Sat Apr 17 20:55:13 BST 1999 Tony Gale <gale@gtk.org>
+
+ * glib.h, gstring.c: Add new g_string functions for reading
+ from file/socket descriptors, and tokenising strings.
+
+ Added various g_string macros.
+
Tue Apr 13 23:28:32 1999 Tor Lillqvist <tml@iki.fi>
* README.win32: Mention the tests directory.
diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12
index bd0c2cac2..b07bb2805 100644
--- a/ChangeLog.pre-2-12
+++ b/ChangeLog.pre-2-12
@@ -1,3 +1,10 @@
+Sat Apr 17 20:55:13 BST 1999 Tony Gale <gale@gtk.org>
+
+ * glib.h, gstring.c: Add new g_string functions for reading
+ from file/socket descriptors, and tokenising strings.
+
+ Added various g_string macros.
+
Tue Apr 13 23:28:32 1999 Tor Lillqvist <tml@iki.fi>
* README.win32: Mention the tests directory.
diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2
index bd0c2cac2..b07bb2805 100644
--- a/ChangeLog.pre-2-2
+++ b/ChangeLog.pre-2-2
@@ -1,3 +1,10 @@
+Sat Apr 17 20:55:13 BST 1999 Tony Gale <gale@gtk.org>
+
+ * glib.h, gstring.c: Add new g_string functions for reading
+ from file/socket descriptors, and tokenising strings.
+
+ Added various g_string macros.
+
Tue Apr 13 23:28:32 1999 Tor Lillqvist <tml@iki.fi>
* README.win32: Mention the tests directory.
diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4
index bd0c2cac2..b07bb2805 100644
--- a/ChangeLog.pre-2-4
+++ b/ChangeLog.pre-2-4
@@ -1,3 +1,10 @@
+Sat Apr 17 20:55:13 BST 1999 Tony Gale <gale@gtk.org>
+
+ * glib.h, gstring.c: Add new g_string functions for reading
+ from file/socket descriptors, and tokenising strings.
+
+ Added various g_string macros.
+
Tue Apr 13 23:28:32 1999 Tor Lillqvist <tml@iki.fi>
* README.win32: Mention the tests directory.
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index bd0c2cac2..b07bb2805 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -1,3 +1,10 @@
+Sat Apr 17 20:55:13 BST 1999 Tony Gale <gale@gtk.org>
+
+ * glib.h, gstring.c: Add new g_string functions for reading
+ from file/socket descriptors, and tokenising strings.
+
+ Added various g_string macros.
+
Tue Apr 13 23:28:32 1999 Tor Lillqvist <tml@iki.fi>
* README.win32: Mention the tests directory.
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index bd0c2cac2..b07bb2805 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,3 +1,10 @@
+Sat Apr 17 20:55:13 BST 1999 Tony Gale <gale@gtk.org>
+
+ * glib.h, gstring.c: Add new g_string functions for reading
+ from file/socket descriptors, and tokenising strings.
+
+ Added various g_string macros.
+
Tue Apr 13 23:28:32 1999 Tor Lillqvist <tml@iki.fi>
* README.win32: Mention the tests directory.
diff --git a/glib.h b/glib.h
index bfd1f49bf..44d61fd0a 100644
--- a/glib.h
+++ b/glib.h
@@ -1689,39 +1689,82 @@ gchar* g_string_chunk_insert_const (GStringChunk *chunk,
/* Strings
*/
-GString* g_string_new (const gchar *init);
-GString* g_string_sized_new (guint dfl_size);
-void g_string_free (GString *string,
- gint free_segment);
-GString* g_string_assign (GString *lval,
- const gchar *rval);
-GString* g_string_truncate (GString *string,
- gint len);
-GString* g_string_append (GString *string,
- const gchar *val);
-GString* g_string_append_c (GString *string,
- gchar c);
-GString* g_string_prepend (GString *string,
- const gchar *val);
-GString* g_string_prepend_c (GString *string,
- gchar c);
-GString* g_string_insert (GString *string,
- gint pos,
- const gchar *val);
-GString* g_string_insert_c (GString *string,
- gint pos,
- gchar c);
-GString* g_string_erase (GString *string,
- gint pos,
- gint len);
-GString* g_string_down (GString *string);
-GString* g_string_up (GString *string);
-void g_string_sprintf (GString *string,
- const gchar *format,
- ...) G_GNUC_PRINTF (2, 3);
-void g_string_sprintfa (GString *string,
- const gchar *format,
- ...) G_GNUC_PRINTF (2, 3);
+typedef enum
+{
+ G_STRING_ERROR_NONE, /* No error occurred */
+ G_STRING_ERROR_INVAL, /* Invalid input value to function */
+ G_STRING_ERROR_READ, /* read() returned an error - check errno */
+ G_STRING_ERROR_NODATA, /* No more input data - result string may contain data */
+ G_STRING_ERROR_LENGTH /* max_length reached */
+} GStringError;
+
+#define g_string_length(fstring) (fstring ? fstring->len : 0)
+#define g_string_str(fstring) (fstring ? fstring->str : NULL)
+#define g_string_char(fstring, n) (fstring->str[n])
+
+#define g_string_copy(a,b) (g_string_assign(a, b->str))
+#define g_string_dup(fstring) (fstring ? g_string_new(fstring->str) :\
+ g_string_new(NULL))
+
+#define g_string_cmp(a,b) (strcmp(g_string_str(a), \
+ g_string_str(b)))
+#define g_string_ncmp(a,b,n) (strncmp(g_string_str(a), \
+ g_string_str(b), n))
+#define g_string_casecmp(a,b) (g_strcasecmp(g_string_str(a), \
+ g_string_str(b)))
+#define g_string_ncasecmp(a,b) (g_strncasecmp(g_string_str(a), \
+ g_string_str(b), n))
+
+#define g_string_strcmp(a,b) (strcmp(g_string_str(a), b))
+#define g_string_strcasecmp(a,b) (g_strcasecmp(g_string_str(a), b))
+
+GString* g_string_new (const gchar *init);
+GString* g_string_sized_new (guint dfl_size);
+void g_string_free (GString *string,
+ gint free_segment);
+GString* g_string_assign (GString *lval,
+ const gchar *rval);
+GString* g_string_truncate (GString *string,
+ gint len);
+GString* g_string_append (GString *string,
+ const gchar *val);
+GString* g_string_append_c (GString *string,
+ gchar c);
+GString* g_string_prepend (GString *string,
+ const gchar *val);
+GString* g_string_prepend_c (GString *string,
+ gchar c);
+GString* g_string_insert (GString *string,
+ gint pos,
+ const gchar *val);
+GString* g_string_insert_c (GString *string,
+ gint pos,
+ gchar c);
+GString* g_string_erase (GString *string,
+ gint pos,
+ gint len);
+GString* g_string_down (GString *string);
+GString* g_string_up (GString *string);
+void g_string_sprintf (GString *string,
+ const gchar *format,
+ ...) G_GNUC_PRINTF (2, 3);
+void g_string_sprintfa (GString *string,
+ const gchar *format,
+ ...) G_GNUC_PRINTF (2, 3);
+GStringError g_string_readline (GString *dest_str,
+ gint max_length,
+ gint fd);
+GStringError g_string_readline_buffered (GString *dest_str,
+ GString *buff_str,
+ gint max_length,
+ gint fd,
+ gint match_bare_cr);
+GList* g_string_tokenise (GString *string,
+ gchar *delims,
+ gint max_tokens,
+ gint allow_empty);
+void g_string_tokenise_free (GList *tokens,
+ gint free_token);
/* Resizable arrays, remove fills any cleared spot and shortens the
diff --git a/glib/glib.h b/glib/glib.h
index bfd1f49bf..44d61fd0a 100644
--- a/glib/glib.h
+++ b/glib/glib.h
@@ -1689,39 +1689,82 @@ gchar* g_string_chunk_insert_const (GStringChunk *chunk,
/* Strings
*/
-GString* g_string_new (const gchar *init);
-GString* g_string_sized_new (guint dfl_size);
-void g_string_free (GString *string,
- gint free_segment);
-GString* g_string_assign (GString *lval,
- const gchar *rval);
-GString* g_string_truncate (GString *string,
- gint len);
-GString* g_string_append (GString *string,
- const gchar *val);
-GString* g_string_append_c (GString *string,
- gchar c);
-GString* g_string_prepend (GString *string,
- const gchar *val);
-GString* g_string_prepend_c (GString *string,
- gchar c);
-GString* g_string_insert (GString *string,
- gint pos,
- const gchar *val);
-GString* g_string_insert_c (GString *string,
- gint pos,
- gchar c);
-GString* g_string_erase (GString *string,
- gint pos,
- gint len);
-GString* g_string_down (GString *string);
-GString* g_string_up (GString *string);
-void g_string_sprintf (GString *string,
- const gchar *format,
- ...) G_GNUC_PRINTF (2, 3);
-void g_string_sprintfa (GString *string,
- const gchar *format,
- ...) G_GNUC_PRINTF (2, 3);
+typedef enum
+{
+ G_STRING_ERROR_NONE, /* No error occurred */
+ G_STRING_ERROR_INVAL, /* Invalid input value to function */
+ G_STRING_ERROR_READ, /* read() returned an error - check errno */
+ G_STRING_ERROR_NODATA, /* No more input data - result string may contain data */
+ G_STRING_ERROR_LENGTH /* max_length reached */
+} GStringError;
+
+#define g_string_length(fstring) (fstring ? fstring->len : 0)
+#define g_string_str(fstring) (fstring ? fstring->str : NULL)
+#define g_string_char(fstring, n) (fstring->str[n])
+
+#define g_string_copy(a,b) (g_string_assign(a, b->str))
+#define g_string_dup(fstring) (fstring ? g_string_new(fstring->str) :\
+ g_string_new(NULL))
+
+#define g_string_cmp(a,b) (strcmp(g_string_str(a), \
+ g_string_str(b)))
+#define g_string_ncmp(a,b,n) (strncmp(g_string_str(a), \
+ g_string_str(b), n))
+#define g_string_casecmp(a,b) (g_strcasecmp(g_string_str(a), \
+ g_string_str(b)))
+#define g_string_ncasecmp(a,b) (g_strncasecmp(g_string_str(a), \
+ g_string_str(b), n))
+
+#define g_string_strcmp(a,b) (strcmp(g_string_str(a), b))
+#define g_string_strcasecmp(a,b) (g_strcasecmp(g_string_str(a), b))
+
+GString* g_string_new (const gchar *init);
+GString* g_string_sized_new (guint dfl_size);
+void g_string_free (GString *string,
+ gint free_segment);
+GString* g_string_assign (GString *lval,
+ const gchar *rval);
+GString* g_string_truncate (GString *string,
+ gint len);
+GString* g_string_append (GString *string,
+ const gchar *val);
+GString* g_string_append_c (GString *string,
+ gchar c);
+GString* g_string_prepend (GString *string,
+ const gchar *val);
+GString* g_string_prepend_c (GString *string,
+ gchar c);
+GString* g_string_insert (GString *string,
+ gint pos,
+ const gchar *val);
+GString* g_string_insert_c (GString *string,
+ gint pos,
+ gchar c);
+GString* g_string_erase (GString *string,
+ gint pos,
+ gint len);
+GString* g_string_down (GString *string);
+GString* g_string_up (GString *string);
+void g_string_sprintf (GString *string,
+ const gchar *format,
+ ...) G_GNUC_PRINTF (2, 3);
+void g_string_sprintfa (GString *string,
+ const gchar *format,
+ ...) G_GNUC_PRINTF (2, 3);
+GStringError g_string_readline (GString *dest_str,
+ gint max_length,
+ gint fd);
+GStringError g_string_readline_buffered (GString *dest_str,
+ GString *buff_str,
+ gint max_length,
+ gint fd,
+ gint match_bare_cr);
+GList* g_string_tokenise (GString *string,
+ gchar *delims,
+ gint max_tokens,
+ gint allow_empty);
+void g_string_tokenise_free (GList *tokens,
+ gint free_token);
/* Resizable arrays, remove fills any cleared spot and shortens the
diff --git a/glib/gstring.c b/glib/gstring.c
index fd8e5122c..f714b3a53 100644
--- a/glib/gstring.c
+++ b/glib/gstring.c
@@ -1,5 +1,6 @@
/* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Portions Copyright (C) 1999 Tony Gale
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -28,6 +29,13 @@
* MT safe
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
@@ -35,6 +43,7 @@
#include <ctype.h>
#include "glib.h"
+#define G_STRING_BLOCK_SIZE 512
typedef struct _GRealStringChunk GRealStringChunk;
typedef struct _GRealString GRealString;
@@ -189,7 +198,7 @@ g_string_chunk_insert_const (GStringChunk *fchunk,
/* Strings.
*/
static gint
-nearest_pow (gint num)
+nearest_power (gint num)
{
gint n = 1;
@@ -199,16 +208,36 @@ nearest_pow (gint num)
return n;
}
+static gint
+nearest_multiple (int num, const int block)
+{
+ gint n = block;
+
+ while (n < num)
+ n += block;
+
+ return n;
+}
+
static void
g_string_maybe_expand (GRealString* string, gint len)
{
if (string->len + len >= string->alloc)
{
- string->alloc = nearest_pow (string->len + len + 1);
+ string->alloc = nearest_power (string->len + len + 1);
string->str = g_realloc (string->str, string->alloc);
}
}
+static void
+g_string_set_size (GRealString* string, gint size)
+{
+ if (string->alloc <= size) {
+ string->alloc = nearest_power(size + 1);
+ string->str = g_realloc (string->str, string->alloc);
+ }
+}
+
GString*
g_string_sized_new (guint dfl_size)
{
@@ -512,3 +541,192 @@ g_string_sprintfa (GString *string,
g_string_sprintfa_int (string, fmt, args);
va_end (args);
}
+
+GStringError
+g_string_readline (GString *dest_str,
+ gint max_length,
+ gint fd)
+{
+ gint count=0, retval;
+ gchar c;
+
+ g_return_val_if_fail (dest_str != NULL, G_STRING_ERROR_INVAL);
+ g_return_val_if_fail (max_length > 0, G_STRING_ERROR_INVAL);
+ g_string_truncate(dest_str, 0);
+
+ for (count = 0; count < max_length; count++) {
+ if ( (retval = read(fd, &c, 1)) == 1 ) {
+ if (c == '\r') {
+ continue;
+ }
+ if (c == '\n') {
+ return(G_STRING_ERROR_NONE);
+ }
+ g_string_maybe_expand ((GRealString *) dest_str, 1);
+ dest_str->str[dest_str->len++] = c;
+ dest_str->str[dest_str->len] = 0;
+ } else if (retval == 0) {
+ return(G_STRING_ERROR_NODATA);
+ } else {
+ return(G_STRING_ERROR_READ);
+ }
+ }
+ return(G_STRING_ERROR_LENGTH);
+}
+
+GStringError
+g_string_readline_buffered (GString *dest_str,
+ GString *buff_str,
+ gint max_length,
+ gint fd,
+ gint match_bare_cr)
+{
+ guint count, i=0, buff_size;
+
+ g_return_val_if_fail (dest_str != NULL, G_STRING_ERROR_INVAL);
+ g_return_val_if_fail (buff_str != NULL, G_STRING_ERROR_INVAL);
+ g_return_val_if_fail (max_length > 0, G_STRING_ERROR_INVAL);
+
+ /* Make the buffer a multiple of G_STRING_BLOCK_SIZE and
+ * bigger then max_length */
+ buff_size = nearest_multiple(max_length, G_STRING_BLOCK_SIZE);
+ g_string_set_size( (GRealString *) buff_str, buff_size);
+
+ do {
+ /* Allow the buffer to empty before reading more data.
+ * Prevents blocking on read() when data in the buffer */
+
+ if (buff_str->len != 0) {
+ /* Search for a CRLF, CR or LF */
+ for (i = 0; i < max_length-1; i++) {
+
+ /* Look for a CR */
+ if (buff_str->str[i] == '\r') {
+
+ /* Check for CRLF */
+ if (buff_str->str[i+1] == '\n') {
+ buff_str->str[i] = '\0';
+ i++;
+ } else if (match_bare_cr) {
+ buff_str->str[i] = '\0';
+ } else {
+ continue;
+ }
+
+ /* Copy the line to the destination string and
+ * remove it from the buffer */
+ g_string_assign( dest_str, buff_str->str );
+ g_string_erase( buff_str, 0, i+1);
+ return (G_STRING_ERROR_NONE);
+ }
+
+ /* Look for LF */
+ if (buff_str->str[i] == '\n') {
+ buff_str->str[i] = '\0';
+
+ /* Copy the line to the destination string and
+ * remove it from the buffer */
+ g_string_assign( dest_str, buff_str->str );
+ g_string_erase( buff_str, 0, i+1);
+ return (G_STRING_ERROR_NONE);
+ }
+
+ /* If we hit a '\0' then we've exhausted the buffer */
+ if (buff_str->str[i] == '\0') {
+ break;
+ }
+ }
+ }
+
+ /* Read in a block of data, appending it to the buffer */
+ if ( (count = read(fd, buff_str->str + buff_str->len,
+ buff_size - buff_str->len - 1)) < 0) {
+ return (G_STRING_ERROR_READ);
+ } else if (count == 0) {
+ return (G_STRING_ERROR_NODATA);
+ } else {
+ /* Fix up the buffer */
+ buff_str->len += count;
+ buff_str->str[buff_str->len] = '\0';
+ }
+
+ } while (i != max_length-1);
+
+ /* If we get here then we have reached max_length */
+ g_string_assign (dest_str, buff_str->str);
+ g_string_truncate (dest_str, max_length-1);
+ g_string_erase (buff_str, 0, max_length-1);
+
+ return (G_STRING_ERROR_LENGTH);
+}
+
+GList*
+g_string_tokenise (GString *string,
+ gchar *delims,
+ gint max_tokens,
+ gint allow_empty)
+{
+ GList *tokens=NULL;
+ GString *token;
+ gchar *current, *start, c;
+ guint count=1;
+
+ g_return_val_if_fail (string != NULL, NULL);
+ g_return_val_if_fail (delims != NULL, NULL);
+
+ if (max_tokens < 1) {
+ max_tokens = G_MAXINT;
+ }
+
+ current = string->str;
+ while (*current) {
+ /* Remove any leading delimiters */
+ if (!allow_empty) {
+ while ( *current && (strchr(delims, *current) != NULL) ) {
+ current++;
+ }
+ }
+
+ /* If we've reached max_tokens, use the remaining input string
+ * as the last token */
+ if (count == max_tokens) {
+ token = g_string_new(current);
+ tokens = g_list_append(tokens, token);
+ return (tokens);
+ }
+
+ /* Find the extent of the current token */
+ if ( *current ) {
+ start = current;
+ while ( *current && (strchr(delims, *current) == NULL) ) {
+ current++;
+ }
+ c = *current;
+ *current = '\0';
+ token = g_string_new( start );
+ *current = c;
+ tokens = g_list_append(tokens, token);
+ count++;
+ if (*current) {
+ current++;
+ }
+ }
+ }
+
+ return (tokens);
+}
+
+void
+g_string_tokenise_free (GList *tokens,
+ gint free_token)
+{
+
+ if (free_token) {
+ while(tokens) {
+ g_string_free( (GString *) tokens->data, TRUE );
+ tokens = g_list_next(tokens);
+ }
+ }
+
+ g_list_free(tokens);
+}
diff --git a/gstring.c b/gstring.c
index fd8e5122c..f714b3a53 100644
--- a/gstring.c
+++ b/gstring.c
@@ -1,5 +1,6 @@
/* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Portions Copyright (C) 1999 Tony Gale
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -28,6 +29,13 @@
* MT safe
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
@@ -35,6 +43,7 @@
#include <ctype.h>
#include "glib.h"
+#define G_STRING_BLOCK_SIZE 512
typedef struct _GRealStringChunk GRealStringChunk;
typedef struct _GRealString GRealString;
@@ -189,7 +198,7 @@ g_string_chunk_insert_const (GStringChunk *fchunk,
/* Strings.
*/
static gint
-nearest_pow (gint num)
+nearest_power (gint num)
{
gint n = 1;
@@ -199,16 +208,36 @@ nearest_pow (gint num)
return n;
}
+static gint
+nearest_multiple (int num, const int block)
+{
+ gint n = block;
+
+ while (n < num)
+ n += block;
+
+ return n;
+}
+
static void
g_string_maybe_expand (GRealString* string, gint len)
{
if (string->len + len >= string->alloc)
{
- string->alloc = nearest_pow (string->len + len + 1);
+ string->alloc = nearest_power (string->len + len + 1);
string->str = g_realloc (string->str, string->alloc);
}
}
+static void
+g_string_set_size (GRealString* string, gint size)
+{
+ if (string->alloc <= size) {
+ string->alloc = nearest_power(size + 1);
+ string->str = g_realloc (string->str, string->alloc);
+ }
+}
+
GString*
g_string_sized_new (guint dfl_size)
{
@@ -512,3 +541,192 @@ g_string_sprintfa (GString *string,
g_string_sprintfa_int (string, fmt, args);
va_end (args);
}
+
+GStringError
+g_string_readline (GString *dest_str,
+ gint max_length,
+ gint fd)
+{
+ gint count=0, retval;
+ gchar c;
+
+ g_return_val_if_fail (dest_str != NULL, G_STRING_ERROR_INVAL);
+ g_return_val_if_fail (max_length > 0, G_STRING_ERROR_INVAL);
+ g_string_truncate(dest_str, 0);
+
+ for (count = 0; count < max_length; count++) {
+ if ( (retval = read(fd, &c, 1)) == 1 ) {
+ if (c == '\r') {
+ continue;
+ }
+ if (c == '\n') {
+ return(G_STRING_ERROR_NONE);
+ }
+ g_string_maybe_expand ((GRealString *) dest_str, 1);
+ dest_str->str[dest_str->len++] = c;
+ dest_str->str[dest_str->len] = 0;
+ } else if (retval == 0) {
+ return(G_STRING_ERROR_NODATA);
+ } else {
+ return(G_STRING_ERROR_READ);
+ }
+ }
+ return(G_STRING_ERROR_LENGTH);
+}
+
+GStringError
+g_string_readline_buffered (GString *dest_str,
+ GString *buff_str,
+ gint max_length,
+ gint fd,
+ gint match_bare_cr)
+{
+ guint count, i=0, buff_size;
+
+ g_return_val_if_fail (dest_str != NULL, G_STRING_ERROR_INVAL);
+ g_return_val_if_fail (buff_str != NULL, G_STRING_ERROR_INVAL);
+ g_return_val_if_fail (max_length > 0, G_STRING_ERROR_INVAL);
+
+ /* Make the buffer a multiple of G_STRING_BLOCK_SIZE and
+ * bigger then max_length */
+ buff_size = nearest_multiple(max_length, G_STRING_BLOCK_SIZE);
+ g_string_set_size( (GRealString *) buff_str, buff_size);
+
+ do {
+ /* Allow the buffer to empty before reading more data.
+ * Prevents blocking on read() when data in the buffer */
+
+ if (buff_str->len != 0) {
+ /* Search for a CRLF, CR or LF */
+ for (i = 0; i < max_length-1; i++) {
+
+ /* Look for a CR */
+ if (buff_str->str[i] == '\r') {
+
+ /* Check for CRLF */
+ if (buff_str->str[i+1] == '\n') {
+ buff_str->str[i] = '\0';
+ i++;
+ } else if (match_bare_cr) {
+ buff_str->str[i] = '\0';
+ } else {
+ continue;
+ }
+
+ /* Copy the line to the destination string and
+ * remove it from the buffer */
+ g_string_assign( dest_str, buff_str->str );
+ g_string_erase( buff_str, 0, i+1);
+ return (G_STRING_ERROR_NONE);
+ }
+
+ /* Look for LF */
+ if (buff_str->str[i] == '\n') {
+ buff_str->str[i] = '\0';
+
+ /* Copy the line to the destination string and
+ * remove it from the buffer */
+ g_string_assign( dest_str, buff_str->str );
+ g_string_erase( buff_str, 0, i+1);
+ return (G_STRING_ERROR_NONE);
+ }
+
+ /* If we hit a '\0' then we've exhausted the buffer */
+ if (buff_str->str[i] == '\0') {
+ break;
+ }
+ }
+ }
+
+ /* Read in a block of data, appending it to the buffer */
+ if ( (count = read(fd, buff_str->str + buff_str->len,
+ buff_size - buff_str->len - 1)) < 0) {
+ return (G_STRING_ERROR_READ);
+ } else if (count == 0) {
+ return (G_STRING_ERROR_NODATA);
+ } else {
+ /* Fix up the buffer */
+ buff_str->len += count;
+ buff_str->str[buff_str->len] = '\0';
+ }
+
+ } while (i != max_length-1);
+
+ /* If we get here then we have reached max_length */
+ g_string_assign (dest_str, buff_str->str);
+ g_string_truncate (dest_str, max_length-1);
+ g_string_erase (buff_str, 0, max_length-1);
+
+ return (G_STRING_ERROR_LENGTH);
+}
+
+GList*
+g_string_tokenise (GString *string,
+ gchar *delims,
+ gint max_tokens,
+ gint allow_empty)
+{
+ GList *tokens=NULL;
+ GString *token;
+ gchar *current, *start, c;
+ guint count=1;
+
+ g_return_val_if_fail (string != NULL, NULL);
+ g_return_val_if_fail (delims != NULL, NULL);
+
+ if (max_tokens < 1) {
+ max_tokens = G_MAXINT;
+ }
+
+ current = string->str;
+ while (*current) {
+ /* Remove any leading delimiters */
+ if (!allow_empty) {
+ while ( *current && (strchr(delims, *current) != NULL) ) {
+ current++;
+ }
+ }
+
+ /* If we've reached max_tokens, use the remaining input string
+ * as the last token */
+ if (count == max_tokens) {
+ token = g_string_new(current);
+ tokens = g_list_append(tokens, token);
+ return (tokens);
+ }
+
+ /* Find the extent of the current token */
+ if ( *current ) {
+ start = current;
+ while ( *current && (strchr(delims, *current) == NULL) ) {
+ current++;
+ }
+ c = *current;
+ *current = '\0';
+ token = g_string_new( start );
+ *current = c;
+ tokens = g_list_append(tokens, token);
+ count++;
+ if (*current) {
+ current++;
+ }
+ }
+ }
+
+ return (tokens);
+}
+
+void
+g_string_tokenise_free (GList *tokens,
+ gint free_token)
+{
+
+ if (free_token) {
+ while(tokens) {
+ g_string_free( (GString *) tokens->data, TRUE );
+ tokens = g_list_next(tokens);
+ }
+ }
+
+ g_list_free(tokens);
+}