[gnome-keyring] gcr: More record functionality.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring] gcr: More record functionality.
- Date: Mon, 16 May 2011 05:30:23 +0000 (UTC)
commit 2383cf15f17f79240c442456488c2e4886e0811c
Author: Stef Walter <stefw collabora co uk>
Date: Fri May 13 21:06:30 2011 +0200
gcr: More record functionality.
* Add boxed type for records
* Allow parsing of space delimited records.
* Lookup unsigned integers in records.
* More tests for GcrRecord
https://bugzilla.gnome.org/show_bug.cgi?id=650255
docs/reference/gcr/gcr-sections.txt | 1 +
gcr/gcr-record.c | 138 +++++++++++++++++++++++++++++++----
gcr/gcr-record.h | 15 ++++
gcr/tests/test-record.c | 122 ++++++++++++++++++++++++++++++-
4 files changed, 257 insertions(+), 19 deletions(-)
---
diff --git a/docs/reference/gcr/gcr-sections.txt b/docs/reference/gcr/gcr-sections.txt
index d4240e4..11f19dc 100644
--- a/docs/reference/gcr/gcr-sections.txt
+++ b/docs/reference/gcr/gcr-sections.txt
@@ -449,6 +449,7 @@ GCR_IS_GNUPG_KEY
GCR_IS_GNUPG_KEY_CLASS
GCR_TYPE_GNUPG_COLLECTION
GCR_TYPE_GNUPG_KEY
+GCR_TYPE_RECORD
GcrRecordColumns
GcrRecordPubColumns
GcrRecordUidColumns
diff --git a/gcr/gcr-record.c b/gcr/gcr-record.c
index 25a1bb2..b0a3924 100644
--- a/gcr/gcr-record.c
+++ b/gcr/gcr-record.c
@@ -27,31 +27,69 @@
#define DEBUG_FLAG GCR_DEBUG_PARSE
#include "gcr-debug.h"
+#include <stdlib.h>
#include <string.h>
#define MAX_COLUMNS 32
struct _GcrRecord {
gchar *data;
+ gsize n_data;
gchar *columns[MAX_COLUMNS];
guint n_columns;
};
+GType
+_gcr_record_get_boxed_type (void)
+{
+ static gsize initialization_value = 0;
+ static GType type = 0;
+
+ if (g_once_init_enter (&initialization_value)) {
+ type = g_boxed_type_register_static ("GcrRecord",
+ (GBoxedCopyFunc)_gcr_record_copy,
+ (GBoxedFreeFunc)_gcr_record_free);
+ g_once_init_leave (&initialization_value, 1);
+ }
+
+ return type;
+}
+
+GcrRecord*
+_gcr_record_copy (GcrRecord *record)
+{
+ GcrRecord *result;
+ gchar *column;
+ guint i;
+
+ result = g_slice_new0 (GcrRecord);
+ result->data = g_memdup (record->data, record->n_data);
+ result->n_data = record->n_data;
+
+ for (i = 0; i < record->n_columns; i++) {
+ column = (gchar*)record->columns[i];
+ g_assert (column >= record->data);
+ result->columns[i] = result->data + (column - record->data);
+ }
+ result->n_columns = record->n_columns;
+ return result;
+}
+
static GcrRecord*
-parse_internal (gchar *line, gsize n_line)
+take_and_parse_internal (gchar *line, gchar delimiter, gboolean allow_empty)
{
GcrRecord *result;
- gchar *p;
+ gchar *at, *beg, *end;
g_assert (line);
- g_assert (n_line);
result = g_slice_new0 (GcrRecord);
result->data = line;
+ result->n_data = strlen (line) + 1;
- _gcr_debug ("parsing line %.*s", (gint)n_line, line);
+ _gcr_debug ("parsing line %s", line);
- p = result->data;
+ at = result->data;
for (;;) {
if (result->n_columns >= MAX_COLUMNS) {
_gcr_debug ("too many record (%d) in gnupg line", MAX_COLUMNS);
@@ -59,14 +97,23 @@ parse_internal (gchar *line, gsize n_line)
return NULL;
}
- result->columns[result->n_columns] = p;
- result->n_columns++;
+ beg = at;
+ result->columns[result->n_columns] = beg;
+
+ at = strchr (beg, delimiter);
+ if (at == NULL) {
+ end = (result->data + result->n_data) - 1;
+ } else {
+ at[0] = '\0';
+ end = at;
+ at++;
+ }
+
+ if (allow_empty || end > beg)
+ result->n_columns++;
- p = strchr (p, ':');
- if (p == NULL)
+ if (at == NULL)
break;
- p[0] = '\0';
- p++;
}
return result;
@@ -78,11 +125,32 @@ _gcr_record_parse_colons (const gchar *line, gssize n_line)
g_return_val_if_fail (line, NULL);
if (n_line < 0)
n_line = strlen (line);
+ return take_and_parse_internal (g_strndup (line, n_line), ':', TRUE);
+}
+
+GcrRecord*
+_gcr_record_take_colons (gchar *line)
+{
+ GcrRecord *record;
- return parse_internal (g_strndup (line, n_line), n_line);
+ g_return_val_if_fail (line, NULL);
+ record = take_and_parse_internal (line, ':', TRUE);
+ if (record == NULL)
+ g_warning ("internal parsing of colons format failed");
+ return record;
}
GcrRecord*
+_gcr_record_parse_spaces (const gchar *line, gssize n_line)
+{
+ g_return_val_if_fail (line, NULL);
+ if (n_line < 0)
+ n_line = strlen (line);
+ return take_and_parse_internal (g_strndup (line, n_line), ' ', FALSE);
+}
+
+
+GcrRecord*
_gcr_record_find (GPtrArray *records, GQuark schema)
{
guint i;
@@ -98,6 +166,13 @@ _gcr_record_find (GPtrArray *records, GQuark schema)
return NULL;
}
+guint
+_gcr_record_get_count (GcrRecord *record)
+{
+ g_return_val_if_fail (record, 0);
+ return record->n_columns;
+}
+
gchar*
_gcr_record_get_string (GcrRecord *record, guint column)
{
@@ -118,14 +193,45 @@ _gcr_record_get_string (GcrRecord *record, guint column)
converted = g_convert (text, -1, "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
g_free (text);
- if (!converted) {
- _gcr_debug ("failed to convert value from latin1 to utf-8: %s", text);
- return NULL;
- }
+ /*
+ * latin1 to utf-8 conversion can't really fail, just produce
+ * garbage... so there's no need to check here.
+ */
return converted;
}
+gboolean
+_gcr_record_get_uint (GcrRecord *record, guint column, guint *value)
+{
+ const gchar *raw;
+ glong result;
+ gchar *end = NULL;
+
+ g_return_val_if_fail (record, FALSE);
+
+ raw = _gcr_record_get_raw (record, column);
+ if (raw == NULL)
+ return FALSE;
+
+ result = strtol (raw, &end, 10);
+ if (!end || end[0]) {
+ _gcr_debug ("invalid unsigned integer value: %s", raw);
+ return FALSE;
+ }
+
+ if (result < 0 || result > G_MAXUINT32) {
+ _gcr_debug ("unsigned integer value is out of range: %s", raw);
+ return FALSE;
+ }
+
+ if (value)
+ *value = (guint)result;
+ return TRUE;
+}
+
+
+
const gchar*
_gcr_record_get_raw (GcrRecord *record, guint column)
{
diff --git a/gcr/gcr-record.h b/gcr/gcr-record.h
index b3a54ae..268d5a8 100644
--- a/gcr/gcr-record.h
+++ b/gcr/gcr-record.h
@@ -29,6 +29,7 @@
#define GCR_RECORD_H
#include <glib.h>
+#include <glib-object.h>
/*
* Gnupg's official format for listing keys is in the '--with-colons' format.
@@ -85,9 +86,17 @@ typedef enum {
typedef struct _GcrRecord GcrRecord;
+#define GCR_TYPE_RECORD (_gcr_record_get_boxed_type ())
+
+GType _gcr_record_get_boxed_type (void) G_GNUC_CONST;
+
+GcrRecord* _gcr_record_copy (GcrRecord *record);
+
GcrRecord* _gcr_record_parse_colons (const gchar *line,
gssize n_line);
+GcrRecord* _gcr_record_take_colons (gchar *line);
+
GcrRecord* _gcr_record_parse_spaces (const gchar *line,
gssize n_line);
@@ -96,9 +105,15 @@ void _gcr_record_free (gpointer record);
GcrRecord* _gcr_record_find (GPtrArray *records,
GQuark schema);
+guint _gcr_record_get_count (GcrRecord *record);
+
gchar* _gcr_record_get_string (GcrRecord *record,
guint column);
+gboolean _gcr_record_get_uint (GcrRecord *record,
+ guint column,
+ guint *value);
+
const gchar* _gcr_record_get_raw (GcrRecord *record,
guint column);
diff --git a/gcr/tests/test-record.c b/gcr/tests/test-record.c
index 0cf91b8..7d7073f 100644
--- a/gcr/tests/test-record.c
+++ b/gcr/tests/test-record.c
@@ -35,7 +35,7 @@ typedef struct {
static void
setup (Test *test, gconstpointer unused)
{
- test->record = _gcr_record_parse_colons ("one:tab\\there::four:f\xfc""nf:", -1);
+ test->record = _gcr_record_parse_colons ("one:tab\\there::four:f\xfc""nf:3533333:-88", -1);
}
static void
@@ -45,7 +45,13 @@ teardown (Test *test, gconstpointer unused)
}
static void
-test_parse (void)
+test_count (Test *test, gconstpointer unused)
+{
+ g_assert_cmpuint (_gcr_record_get_count (test->record), ==, 7);
+}
+
+static void
+test_parse_colons (void)
{
GcrRecord *record;
@@ -64,6 +70,45 @@ test_parse (void)
}
static void
+test_take_colons (void)
+{
+ GcrRecord *record;
+
+ record = _gcr_record_take_colons (g_strdup ("one:two::four::six"));
+ g_assert (record);
+
+ g_assert_cmpstr (_gcr_record_get_raw (record, 0), ==, "one");
+ g_assert_cmpstr (_gcr_record_get_raw (record, 1), ==, "two");
+ g_assert_cmpstr (_gcr_record_get_raw (record, 2), ==, "");
+ g_assert_cmpstr (_gcr_record_get_raw (record, 3), ==, "four");
+ g_assert_cmpstr (_gcr_record_get_raw (record, 4), ==, "");
+ g_assert_cmpstr (_gcr_record_get_raw (record, 5), ==, "six");
+ g_assert (_gcr_record_get_raw (record, 6) == NULL);
+ g_assert_cmpuint (_gcr_record_get_count (record), ==, 6);
+
+ _gcr_record_free (record);
+}
+
+
+static void
+test_parse_spaces (void)
+{
+ GcrRecord *record;
+
+ record = _gcr_record_parse_spaces (" one two four six ", -1);
+ g_assert (record);
+
+ g_assert_cmpstr (_gcr_record_get_raw (record, 0), ==, "one");
+ g_assert_cmpstr (_gcr_record_get_raw (record, 1), ==, "two");
+ g_assert_cmpstr (_gcr_record_get_raw (record, 2), ==, "four");
+ g_assert_cmpstr (_gcr_record_get_raw (record, 3), ==, "six");
+ g_assert (_gcr_record_get_raw (record, 4) == NULL);
+ g_assert_cmpuint (_gcr_record_get_count (record), ==, 4);
+
+ _gcr_record_free (record);
+}
+
+static void
test_parse_part (void)
{
GcrRecord *record;
@@ -142,6 +187,34 @@ test_get_string_latin1 (Test *test, gconstpointer unused)
}
static void
+test_get_uint (Test *test, gconstpointer unused)
+{
+ guint value = 0;
+
+ if (!_gcr_record_get_uint (test->record, 5, &value))
+ g_assert_not_reached ();
+ g_assert_cmpuint (value, ==, 3533333);
+}
+
+static void
+test_get_uint_range (Test *test, gconstpointer unused)
+{
+ guint value = 0;
+
+ if (_gcr_record_get_uint (test->record, 6, &value))
+ g_assert_not_reached ();
+}
+
+static void
+test_get_uint_invalid (Test *test, gconstpointer unused)
+{
+ guint value = 0;
+
+ if (_gcr_record_get_uint (test->record, 0, &value))
+ g_assert_not_reached ();
+}
+
+static void
test_free_null (void)
{
_gcr_record_free (NULL);
@@ -161,19 +234,62 @@ test_get_schema (Test *test, gconstpointer unused)
g_assert_cmpstr (g_quark_to_string (schema), ==, "one");
}
+static void
+test_copy (Test *test, gconstpointer unused)
+{
+ GcrRecord *copy;
+ guint count, i;
+
+ copy = _gcr_record_copy (test->record);
+
+ count = _gcr_record_get_count (test->record);
+ g_assert_cmpuint (_gcr_record_get_count (copy), ==, count);
+ for (i = 0; i < count; i++) {
+ g_assert_cmpstr (_gcr_record_get_raw (copy, i), ==,
+ _gcr_record_get_raw (test->record, i));
+ }
+}
+
+static void
+test_boxed (Test *test, gconstpointer unused)
+{
+ GcrRecord *copy;
+ guint count, i;
+
+ copy = g_boxed_copy (GCR_TYPE_RECORD, test->record);
+
+ count = _gcr_record_get_count (test->record);
+ g_assert_cmpuint (_gcr_record_get_count (copy), ==, count);
+ for (i = 0; i < count; i++) {
+ g_assert_cmpstr (_gcr_record_get_raw (copy, i), ==,
+ _gcr_record_get_raw (test->record, i));
+ }
+
+ g_boxed_free (GCR_TYPE_RECORD, copy);
+}
+
int
main (int argc, char **argv)
{
+ g_type_init ();
g_test_init (&argc, &argv, NULL);
- g_test_add_func ("/gcr/record/parse", test_parse);
+ g_test_add_func ("/gcr/record/parse_colons", test_parse_colons);
+ g_test_add_func ("/gcr/record/take_colons", test_take_colons);
+ g_test_add_func ("/gcr/record/parse_colons", test_parse_spaces);
g_test_add_func ("/gcr/record/parse_part", test_parse_part);
g_test_add_func ("/gcr/record/parse_too_long", test_parse_too_long);
g_test_add_func ("/gcr/record/free_null", test_free_null);
g_test_add_func ("/gcr/record/find", test_find);
+ g_test_add ("/gcr/record/count", Test, NULL, setup, test_count, teardown);
+ g_test_add ("/gcr/record/copy", Test, NULL, setup, test_copy, teardown);
+ g_test_add ("/gcr/record/boxed", Test, NULL, setup, test_boxed, teardown);
g_test_add ("/gcr/record/get_string", Test, NULL, setup, test_get_string, teardown);
g_test_add ("/gcr/record/get_string_null", Test, NULL, setup, test_get_string_null, teardown);
g_test_add ("/gcr/record/get_string_latin1", Test, NULL, setup, test_get_string_latin1, teardown);
+ g_test_add ("/gcr/record/get_uint", Test, NULL, setup, test_get_uint, teardown);
+ g_test_add ("/gcr/record/get_uint_invalid", Test, NULL, setup, test_get_uint_invalid, teardown);
+ g_test_add ("/gcr/record/get_uint_range", Test, NULL, setup, test_get_uint_range, teardown);
g_test_add ("/gcr/record/get_schema", Test, NULL, setup, test_get_schema, teardown);
return g_test_run ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]