Kouhei Sutou
null+****@clear*****
Wed Jan 22 00:22:09 JST 2014
Kouhei Sutou 2014-01-22 00:22:09 +0900 (Wed, 22 Jan 2014) New Revision: 0ffd92059b9dc37a5af794ad2bc46849fe252aee https://github.com/groonga/groonga-gobject/commit/0ffd92059b9dc37a5af794ad2bc46849fe252aee Message: Add GGrnCommand Added files: groonga-gobject/ggrn-command.c groonga-gobject/ggrn-command.h test/test-command.c Modified files: groonga-gobject/Makefile.am groonga-gobject/ggrn-context.c groonga-gobject/ggrn-internal.h groonga-gobject/ggrn.h test/Makefile.am Modified: groonga-gobject/Makefile.am (+3 -1) =================================================================== --- groonga-gobject/Makefile.am 2014-01-22 00:21:13 +0900 (3c75f68) +++ groonga-gobject/Makefile.am 2014-01-22 00:22:09 +0900 (9ace95e) @@ -1,4 +1,4 @@ -# Copyright (C) 2013 Kouhei Sutou <kou �� clear-code.com> +# Copyright (C) 2013-2014 Kouhei Sutou <kou �� clear-code.com> # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -40,6 +40,8 @@ libgroonga_gobject_la_SOURCES = \ ggrn.h \ ggrn-context.c \ ggrn-context.h \ + ggrn-command.c \ + ggrn-command.h \ ggrn-error.c \ ggrn-error.h \ ggrn-internal.c \ Added: groonga-gobject/ggrn-command.c (+346 -0) 100644 =================================================================== --- /dev/null +++ groonga-gobject/ggrn-command.c 2014-01-22 00:22:09 +0900 (049d3f1) @@ -0,0 +1,346 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2014 Kouhei Sutou <kou �� clear-code.com> + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> + +#include <groonga.h> + +#include "ggrn-command.h" +#include "ggrn-internal.h" + +/** +* SECTION: ggrn-command +* @short_description: An object to create a Groonga command. +* +* The #GGrnCommand is a class to create a Groonga command string. +*/ +G_DEFINE_TYPE(GGrnCommand, ggrn_command, G_TYPE_OBJECT) + +#define GGRN_COMMAND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ + GGRN_TYPE_COMMAND, \ + GGrnCommandPrivate)) + +typedef struct _GGrnCommandPrivate GGrnCommandPrivate; +struct _GGrnCommandPrivate +{ + GGrnContext *context; + gchar *name; + GHashTable *arguments; +}; + +enum +{ + PROP_0, + PROP_CONTEXT, + PROP_NAME, + N_PROPERTIES +}; + +static GParamSpec *properties[N_PROPERTIES] = {NULL,}; + +static void +ggrn_command_init(GGrnCommand *object) +{ + GGrnCommandPrivate *priv = GGRN_COMMAND_GET_PRIVATE(object); + + priv->context = NULL; + priv->name = NULL; + priv->arguments = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); +} + +static void +dispose(GObject *object) +{ + GGrnCommandPrivate *priv = GGRN_COMMAND_GET_PRIVATE(object); + + if (priv->context) { + g_object_unref(priv->context); + priv->context = NULL; + } + + if (priv->name) { + g_free(priv->name); + priv->name = NULL; + } + + if (priv->arguments) { + g_hash_table_unref(priv->arguments); + priv->arguments = NULL; + } + + G_OBJECT_CLASS(ggrn_command_parent_class)->dispose(object); +} + +static void +set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GGrnCommandPrivate *priv = GGRN_COMMAND_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_CONTEXT: + { + GGrnContext *context = priv->context; + priv->context = g_value_get_object(value); + if (priv->context != context) { + if (priv->context) { + g_object_ref(priv->context); + } + if (context) { + g_object_unref(context); + } + } + } + break; + case PROP_NAME: + g_free(priv->name); + priv->name = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GGrnCommandPrivate *priv = GGRN_COMMAND_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_CONTEXT: + g_value_set_object(value, priv->context); + break; + case PROP_NAME: + g_value_set_string(value, priv->name); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +ggrn_command_class_init(GGrnCommandClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + GParamSpec *spec; + + object_class->dispose = dispose; + object_class->set_property = set_property; + object_class->get_property = get_property; + + spec = g_param_spec_object("context", + "Context", + "The context for the command", + GGRN_TYPE_CONTEXT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(object_class, PROP_CONTEXT, spec); + + spec = g_param_spec_string("name", + "Command name", + "The name of the command", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(object_class, PROP_NAME, spec); + + g_type_class_add_private(object_class, sizeof(GGrnCommandPrivate)); +} + +/** + * ggrn_command_new: + * + * Allocates a new #GGrnCommand. + * + * Returns: a new #GGrnCommand. + */ +GGrnCommand * +ggrn_command_new(GGrnContext *context, const gchar *name) +{ + return g_object_new(GGRN_TYPE_COMMAND, + "context", context, + "name", name, + NULL); +} + +/** + * ggrn_command_add_argument: + * @command: A #GGrnCommand. + * @name: The name of the argument. + * @value: The value of the argument. + * + * Adds an argument of the command. + * + * If you add the same name argument twice, the old argument value is + * overrode. + */ +void +ggrn_command_add_argument(GGrnCommand *command, + const gchar *name, const gchar *value) +{ + GGrnCommandPrivate *priv = GGRN_COMMAND_GET_PRIVATE(command); + + g_hash_table_insert(priv->arguments, g_strdup(name), g_strdup(value)); +} + +/** + * ggrn_command_execute: + * @command: A #GGrnCommand. + * + * Executes the command and returns the executed result. + * + * Returns: The executed result of @command. It must be freed with + * g_free() when no longer needed. + */ +gchar * +ggrn_command_execute(GGrnCommand *command) +{ + GGrnCommandPrivate *priv = GGRN_COMMAND_GET_PRIVATE(command); + gchar *command_line; + gchar *result; + + command_line = ggrn_command_to_command_line(command); + result = ggrn_context_execute_command(priv->context, command_line); + g_free(command_line); + + return result; +} + +static void +to_path_append_argument(gpointer key, gpointer value, gpointer user_data) +{ + GString *path = user_data; + + if (path->str[path->len - 1] != '?') { + g_string_append_c(path, '&'); + } + g_string_append_uri_escaped(path, key, NULL, FALSE); + g_string_append_c(path, '='); + g_string_append_uri_escaped(path, value, NULL, FALSE); +} + +/** + * ggrn_command_to_path: + * @command: A #GGrnCommand. + * + * Formats the command as path format like the following: + * + * |[ + * /d/table_create?name=Logs&flags=TABLE_NO_KEY + * ]| + * + * Returns: The path format command. It must be freed with + * g_free() when no longer needed. + */ +gchar * +ggrn_command_to_path(GGrnCommand *command) +{ + GGrnCommandPrivate *priv = GGRN_COMMAND_GET_PRIVATE(command); + GString *path; + + path = g_string_new("/d/"); + g_string_append(path, priv->name); + if (g_hash_table_size(priv->arguments) > 0) { + g_string_append_c(path, '?'); + g_hash_table_foreach(priv->arguments, + to_path_append_argument, + path); + } + + return g_string_free(path, FALSE); +} + +static void +to_command_line_append_value(GString *command_line, const gchar *value) +{ + const gchar *value_current, *value_next; + + g_string_append_c(command_line, '"'); + value_current = value; + while (value_current) { + gsize char_length; + value_next = g_utf8_next_char(value_current); + if (value_next) { + char_length = value_next - value_current; + } else { + char_length = strlen(value_current); + } + if (char_length == 1) { + switch (*value_current) { + case '"': + case '\\': + g_string_append_c(command_line, '\\'); + break; + default: + break; + } + } + g_string_append_len(command_line, value_current, char_length); + value_current = value_next; + } + g_string_append_c(command_line, '"'); +} + +static void +to_command_line_append_argument(gpointer key, gpointer value, gpointer user_data) +{ + const gchar *name = key; + GString *command_line = user_data; + + g_string_append_printf(command_line, " --%s ", name); + to_command_line_append_value(command_line, value); +} + +/** + * ggrn_command_to_command_line: + * @command: A #GGrnCommand. + * + * Formats the command as command line format like the following: + * + * |[ + * table_create --name Logs --flags TABLE_NO_KEY + * ]| + * + * Returns: The command line format command. It must be freed with + * g_free() when no longer needed. + */ +gchar * +ggrn_command_to_command_line(GGrnCommand *command) +{ + GGrnCommandPrivate *priv = GGRN_COMMAND_GET_PRIVATE(command); + GString *command_line; + + command_line = g_string_new(NULL); + g_string_append(command_line, priv->name); + g_hash_table_foreach(priv->arguments, + to_command_line_append_argument, + command_line); + + return g_string_free(command_line, FALSE); +} Added: groonga-gobject/ggrn-command.h (+71 -0) 100644 =================================================================== --- /dev/null +++ groonga-gobject/ggrn-command.h 2014-01-22 00:22:09 +0900 (d1a8f75) @@ -0,0 +1,71 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2014 Kouhei Sutou <kou �� clear-code.com> + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GGRN_COMMAND_H +#define GGRN_COMMAND_H + +#include <groonga-gobject/ggrn-context.h> + +G_BEGIN_DECLS + +#define GGRN_TYPE_COMMAND \ + (ggrn_command_get_type()) +#define GGRN_COMMAND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GGRN_TYPE_COMMAND, GGrnCommand)) +#define GGRN_COMMAND_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GGRN_TYPE_COMMAND, GGrnCommandClass)) +#define GGRN_IS_COMMAND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GGRN_TYPE_COMMAND)) +#define GGRN_IS_COMMAND_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GGRN_TYPE_COMMAND)) +#define GGRN_COMMAND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), GGRN_TYPE_COMMAND, GGrnCommandClass)) + +typedef struct _GGrnCommand GGrnCommand; +typedef struct _GGrnCommandClass GGrnCommandClass; + +/** + * GGrnCommand: + * + * A GGrnCommand is an object to create a Groonga command string. It + * is executable by ggrn_context_execute_command(). + */ +struct _GGrnCommand +{ + /*< private >*/ + GObject parent_instance; +}; + +struct _GGrnCommandClass +{ + GObjectClass parent_class; +}; + +GType ggrn_command_get_type (void) G_GNUC_CONST; +GGrnCommand *ggrn_command_new (GGrnContext *context, + const gchar *name); +void ggrn_command_add_argument (GGrnCommand *command, + const gchar *name, + const gchar *value); +gchar *ggrn_command_execute (GGrnCommand *command); +gchar *ggrn_command_to_path (GGrnCommand *command); +gchar *ggrn_command_to_command_line (GGrnCommand *command); + +G_END_DECLS + +#endif Modified: groonga-gobject/ggrn-context.c (+8 -1) =================================================================== --- groonga-gobject/ggrn-context.c 2014-01-22 00:21:13 +0900 (85b4c9d) +++ groonga-gobject/ggrn-context.c 2014-01-22 00:22:09 +0900 (d262ce0) @@ -1,6 +1,6 @@ /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* - * Copyright (C) 2013 Kouhei Sutou <kou �� clear-code.com> + * Copyright (C) 2013-2014 Kouhei Sutou <kou �� clear-code.com> * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -119,6 +119,13 @@ ggrn_context_new(void) return context; } +grn_ctx * +_ggrn_context_get_ctx(GGrnContext *context) +{ + GGrnContextPrivate *priv = GGRN_CONTEXT_GET_PRIVATE(context); + return priv->ctx; +} + /** * ggrn_context_open_database: * @context: A #GGrnContext. Modified: groonga-gobject/ggrn-internal.h (+4 -0) =================================================================== --- groonga-gobject/ggrn-internal.h 2014-01-22 00:21:13 +0900 (474efb5) +++ groonga-gobject/ggrn-internal.h 2014-01-22 00:22:09 +0900 (8fe0f5b) @@ -22,10 +22,14 @@ #include <glib.h> #include <groonga.h> +#include "ggrn-context.h" + G_BEGIN_DECLS G_GNUC_INTERNAL gboolean _ggrn_rc_check (grn_rc rc, GError **error); +G_GNUC_INTERNAL grn_ctx *_ggrn_context_get_ctx (GGrnContext *context); + G_END_DECLS #endif Modified: groonga-gobject/ggrn.h (+1 -2) =================================================================== --- groonga-gobject/ggrn.h 2014-01-22 00:21:13 +0900 (db8fed8) +++ groonga-gobject/ggrn.h 2014-01-22 00:22:09 +0900 (39b489c) @@ -19,9 +19,8 @@ #ifndef GGRN_H #define GGRN_H -#include <glib.h> - #include <groonga-gobject/ggrn-context.h> +#include <groonga-gobject/ggrn-command.h> G_BEGIN_DECLS Modified: test/Makefile.am (+4 -1) =================================================================== --- test/Makefile.am 2014-01-22 00:21:13 +0900 (86d8a02) +++ test/Makefile.am 2014-01-22 00:22:09 +0900 (443dca1) @@ -32,10 +32,13 @@ LIBS = \ if WITH_CUTTER noinst_LTLIBRARIES = \ - suite-groonga-gobject-test.la + suite-groonga-gobject-test.la \ + test-command.la endif suite_groonga_gobject_test_la_SOURCES = suite-groonga-gobject-test.c +test_command_la_SOURCES = test-command.c + echo-abs-top-builddir: @echo $(abs_top_builddir) Added: test/test-command.c (+59 -0) 100644 =================================================================== --- /dev/null +++ test/test-command.c 2014-01-22 00:22:09 +0900 (9a5f878) @@ -0,0 +1,59 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2014 Kouhei Sutou <kou �� clear-code.com> + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <groonga-gobject/ggrn.h> + +#include <gcutter.h> + +CUT_EXPORT void test_to_path(void); +CUT_EXPORT void test_to_command_line(void); + +static GGrnContext *context; +static GGrnCommand *command; + +void +cut_setup(void) +{ + context = ggrn_context_new(); + command = ggrn_command_new(context, "select"); +} + +void +cut_teardown(void) +{ + g_object_unref(command); + g_object_unref(context); +} + +void +test_to_path(void) +{ + cut_assert_equal_string_with_free("/d/select", + ggrn_command_to_path(command)); +} + +void +test_to_command_line(void) +{ + cut_assert_equal_string_with_free("select", + ggrn_command_to_command_line(command)); +} -------------- next part -------------- HTML����������������������������...Download