[libgda] GdaMysqlPStmt: ported to G_DECLARE/G_DEFINE
- From: Daniel Espinosa Ortiz <despinosa src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] GdaMysqlPStmt: ported to G_DECLARE/G_DEFINE
- Date: Fri, 5 Apr 2019 23:00:57 +0000 (UTC)
commit ee73258591b3c35bb1347185403078f58e4e9f41
Author: Daniel Espinosa <esodan gmail com>
Date: Fri Apr 5 14:13:40 2019 -0600
GdaMysqlPStmt: ported to G_DECLARE/G_DEFINE
providers/mysql/gda-mysql-provider.c | 26 +++---
providers/mysql/gda-mysql-pstmt.c | 153 +++++++++++++++++++---------------
providers/mysql/gda-mysql-pstmt.h | 34 +++-----
providers/mysql/gda-mysql-recordset.c | 36 ++++----
providers/mysql/gda-mysql-recordset.h | 1 +
5 files changed, 126 insertions(+), 124 deletions(-)
---
diff --git a/providers/mysql/gda-mysql-provider.c b/providers/mysql/gda-mysql-provider.c
index e674343ac..3c72ffa20 100644
--- a/providers/mysql/gda-mysql-provider.c
+++ b/providers/mysql/gda-mysql-provider.c
@@ -2171,7 +2171,7 @@ gda_mysql_provider_statement_execute (GdaServerProvider *provider,
g_object_ref (ps);
g_assert (ps);
- if (ps->stmt_used) {
+ if (gda_mysql_pstmt_get_stmt_used (ps)) {
/* Don't use @ps => prepare stmt again */
GdaMysqlPStmt *nps;
nps = real_prepare (provider, cnc, stmt, error);
@@ -2593,9 +2593,9 @@ gda_mysql_provider_statement_execute (GdaServerProvider *provider,
}
}
- if (!event && mysql_bind_param && mysql_stmt_bind_param (ps->mysql_stmt, mysql_bind_param)) {
- //g_warning ("mysql_stmt_bind_param failed: %s\n", mysql_stmt_error (ps->mysql_stmt));
- event = _gda_mysql_make_error (cnc, cdata->mysql, ps->mysql_stmt, error);
+ if (!event && mysql_bind_param && mysql_stmt_bind_param (gda_mysql_pstmt_get_mysql_stmt (ps),
mysql_bind_param)) {
+ //g_warning ("mysql_stmt_bind_param failed: %s\n", mysql_stmt_error
(gda_mysql_pstmt_get_mysql_stmt (ps)));
+ event = _gda_mysql_make_error (cnc, cdata->mysql, gda_mysql_pstmt_get_mysql_stmt (ps), error);
}
if (event) {
@@ -2611,8 +2611,8 @@ gda_mysql_provider_statement_execute (GdaServerProvider *provider,
gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT) {
#if MYSQL_VERSION_ID >= 50002
const unsigned long cursor_type = CURSOR_TYPE_READ_ONLY;
- if (mysql_stmt_attr_set (ps->mysql_stmt, STMT_ATTR_CURSOR_TYPE, (void *) &cursor_type)) {
- _gda_mysql_make_error (cnc, NULL, ps->mysql_stmt, NULL);
+ if (mysql_stmt_attr_set (gda_mysql_pstmt_get_mysql_stmt (ps), STMT_ATTR_CURSOR_TYPE, (void *)
&cursor_type)) {
+ _gda_mysql_make_error (cnc, NULL, gda_mysql_pstmt_get_mysql_stmt (ps), NULL);
g_object_unref (ps);
free_bind_param_data (mem_to_free);
return NULL;
@@ -2653,8 +2653,8 @@ gda_mysql_provider_statement_execute (GdaServerProvider *provider,
/* This is a re-prepare of the statement. The function mysql_stmt_prepare
* will handle this on the server side. */
- if (mysql_stmt_prepare (ps->mysql_stmt, sql_for_empty, strlen (sql_for_empty))) {
- _gda_mysql_make_error (cdata->cnc, NULL, ps->mysql_stmt, error);
+ if (mysql_stmt_prepare (gda_mysql_pstmt_get_mysql_stmt (ps), sql_for_empty, strlen
(sql_for_empty))) {
+ _gda_mysql_make_error (cdata->cnc, NULL, gda_mysql_pstmt_get_mysql_stmt (ps), error);
g_object_unref (ps);
free_bind_param_data (mem_to_free);
return NULL;
@@ -2666,22 +2666,22 @@ gda_mysql_provider_statement_execute (GdaServerProvider *provider,
GObject *return_value = NULL;
- if (mysql_stmt_execute (ps->mysql_stmt)) {
- event = _gda_mysql_make_error (cnc, NULL, ps->mysql_stmt, error);
+ if (mysql_stmt_execute (gda_mysql_pstmt_get_mysql_stmt (ps))) {
+ event = _gda_mysql_make_error (cnc, NULL, gda_mysql_pstmt_get_mysql_stmt (ps), error);
gda_connection_add_event (cnc, event);
}
else {
/* execute prepared statement using C API depending on its kind */
my_ulonglong affected_rows;
- affected_rows = mysql_stmt_affected_rows (ps->mysql_stmt);
+ affected_rows = mysql_stmt_affected_rows (gda_mysql_pstmt_get_mysql_stmt (ps));
if ((affected_rows == (my_ulonglong)~0) ||
!g_ascii_strncasecmp (gda_pstmt_get_sql (_GDA_PSTMT (ps)), "SELECT", 6) ||
!g_ascii_strncasecmp (gda_pstmt_get_sql (_GDA_PSTMT (ps)), "SHOW", 4) ||
!g_ascii_strncasecmp (gda_pstmt_get_sql (_GDA_PSTMT (ps)), "DESCRIBE", 8) ||
!g_ascii_strncasecmp (gda_pstmt_get_sql (_GDA_PSTMT (ps)), "EXECUTE", 7) ||
!g_ascii_strncasecmp (gda_pstmt_get_sql (_GDA_PSTMT (ps)), "EXPLAIN", 7)) {
- if (mysql_stmt_store_result (ps->mysql_stmt)) {
- _gda_mysql_make_error (cnc, NULL, ps->mysql_stmt, error);
+ if (mysql_stmt_store_result (gda_mysql_pstmt_get_mysql_stmt (ps))) {
+ _gda_mysql_make_error (cnc, NULL, gda_mysql_pstmt_get_mysql_stmt (ps), error);
}
else {
GdaDataModelAccessFlags flags;
diff --git a/providers/mysql/gda-mysql-pstmt.c b/providers/mysql/gda-mysql-pstmt.c
index a6e1de643..32bf6596c 100644
--- a/providers/mysql/gda-mysql-pstmt.c
+++ b/providers/mysql/gda-mysql-pstmt.c
@@ -22,92 +22,66 @@
#include <glib/gi18n-lib.h>
#include "gda-mysql-pstmt.h"
-static void
-gda_mysql_pstmt_class_init (GdaMysqlPStmtClass *klass);
-static void
-gda_mysql_pstmt_init (GdaMysqlPStmt *pstmt,
- GdaMysqlPStmtClass *klass);
-static void
-gda_mysql_pstmt_finalize (GObject *object);
+static void gda_mysql_pstmt_class_init (GdaMysqlPStmtClass *klass);
+static void gda_mysql_pstmt_init (GdaMysqlPStmt *pstmt);
+static void gda_mysql_pstmt_dispose (GObject *object);
-static GObjectClass *parent_class = NULL;
+typedef struct {
+ GdaConnection *cnc;
-/**
- * gda_mysql_pstmt_get_type
- *
- * Returns: the #GType of GdaMysqlPStmt.
- */
-GType
-gda_mysql_pstmt_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0)) {
- static GMutex registering;
- static const GTypeInfo info = {
- sizeof (GdaMysqlPStmtClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) gda_mysql_pstmt_class_init,
- NULL,
- NULL,
- sizeof (GdaMysqlPStmt),
- 0,
- (GInstanceInitFunc) gda_mysql_pstmt_init,
- NULL
- };
-
- g_mutex_lock (®istering);
- if (type == 0)
- type = g_type_register_static (GDA_TYPE_PSTMT, "GdaMysqlPStmt", &info, 0);
- g_mutex_unlock (®istering);
- }
- return type;
-}
+ MYSQL *mysql;
+ MYSQL_STMT *mysql_stmt;
+ gboolean stmt_used; /* TRUE if a recorset already uses this prepared statement,
+ * necessary because only one recordset can use mysql_stmt at a time */
+ MYSQL_BIND *mysql_bind_result;
+} GdaMysqlPStmtPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE(GdaMysqlPStmt, gda_mysql_pstmt, GDA_TYPE_PSTMT)
static void
gda_mysql_pstmt_class_init (GdaMysqlPStmtClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- parent_class = g_type_class_peek_parent (klass);
-
/* virtual functions */
- object_class->finalize = gda_mysql_pstmt_finalize;
+ object_class->dispose = gda_mysql_pstmt_dispose;
}
static void
-gda_mysql_pstmt_init (GdaMysqlPStmt *pstmt,
- G_GNUC_UNUSED GdaMysqlPStmtClass *klass)
+gda_mysql_pstmt_init (GdaMysqlPStmt *pstmt)
{
g_return_if_fail (GDA_IS_PSTMT (pstmt));
-
- /* initialize specific parts of @pstmt */
- // TO_IMPLEMENT;
- pstmt->mysql_bind_result = NULL;
+ GdaMysqlPStmtPrivate *priv = gda_mysql_pstmt_get_instance_private (pstmt);
+ priv->cnc = NULL;
+ priv->mysql = NULL;
+ priv->mysql_stmt = NULL;
+ priv->stmt_used = FALSE;
+ priv->mysql_bind_result = NULL;
+ priv->mysql_bind_result = NULL;
}
static void
-gda_mysql_pstmt_finalize (GObject *object)
+gda_mysql_pstmt_dispose (GObject *object)
{
GdaMysqlPStmt *pstmt = (GdaMysqlPStmt *) object;
g_return_if_fail (GDA_IS_PSTMT (pstmt));
+ GdaMysqlPStmtPrivate *priv = gda_mysql_pstmt_get_instance_private (pstmt);
+ if (priv->cnc != NULL) {
+ g_object_unref (priv->cnc);
+ priv->cnc = NULL;
+ }
/* free memory */
- if (pstmt->mysql_stmt)
- mysql_stmt_close (pstmt->mysql_stmt);
-
- gint i;
- for (i = 0; i < gda_pstmt_get_ncols ((GdaPStmt *) pstmt); ++i) {
- g_free (pstmt->mysql_bind_result[i].buffer);
- g_free (pstmt->mysql_bind_result[i].is_null);
- g_free (pstmt->mysql_bind_result[i].length);
- }
- g_free (pstmt->mysql_bind_result);
- pstmt->mysql_bind_result = NULL;
+ if (priv->mysql_stmt) {
+ mysql_stmt_close (priv->mysql_stmt);
+ priv->mysql_stmt = NULL;
+ }
+ if (priv->mysql_bind_result != NULL) {
+ gda_mysql_pstmt_free_mysql_bind_result (pstmt);
+ }
/* chain to parent class */
- parent_class->finalize (object);
+ G_OBJECT_CLASS (gda_mysql_pstmt_parent_class)->dispose (object);
}
/*
@@ -120,11 +94,58 @@ gda_mysql_pstmt_new (GdaConnection *cnc,
{
GdaMysqlPStmt *ps = (GdaMysqlPStmt *) g_object_new (GDA_TYPE_MYSQL_PSTMT,
NULL);
- ps->cnc = cnc;
- ps->mysql = mysql;
- ps->mysql_stmt = mysql_stmt;
- ps->stmt_used = FALSE;
+ GdaMysqlPStmtPrivate *priv = gda_mysql_pstmt_get_instance_private (ps);
+ priv->cnc = g_object_ref (cnc);
+ priv->mysql = mysql;
+ priv->mysql_stmt = mysql_stmt;
+ priv->stmt_used = FALSE;
return ps;
}
+
+gboolean
+gda_mysql_pstmt_get_stmt_used (GdaMysqlPStmt *stmt)
+{
+ GdaMysqlPStmtPrivate *priv = gda_mysql_pstmt_get_instance_private (stmt);
+ return priv->stmt_used;
+}
+void
+gda_mysql_pstmt_set_stmt_used (GdaMysqlPStmt *stmt, gboolean used)
+{
+ GdaMysqlPStmtPrivate *priv = gda_mysql_pstmt_get_instance_private (stmt);
+ priv->stmt_used = used;
+}
+MYSQL_STMT*
+gda_mysql_pstmt_get_mysql_stmt (GdaMysqlPStmt *stmt)
+{
+ GdaMysqlPStmtPrivate *priv = gda_mysql_pstmt_get_instance_private (stmt);
+ return priv->mysql_stmt;
+}
+
+MYSQL_BIND*
+gda_mysql_pstmt_get_mysql_bind_result (GdaMysqlPStmt *stmt)
+{
+ GdaMysqlPStmtPrivate *priv = gda_mysql_pstmt_get_instance_private (stmt);
+ return priv->mysql_bind_result;
+}
+void
+gda_mysql_pstmt_free_mysql_bind_result (GdaMysqlPStmt *stmt)
+{
+ GdaMysqlPStmtPrivate *priv = gda_mysql_pstmt_get_instance_private (stmt);
+ gint i;
+ for (i = 0; i < gda_pstmt_get_ncols ((GdaPStmt *) stmt); ++i) {
+ g_free (priv->mysql_bind_result[i].buffer);
+ g_free (priv->mysql_bind_result[i].is_null);
+ g_free (priv->mysql_bind_result[i].length);
+ }
+ g_free (priv->mysql_bind_result);
+ priv->mysql_bind_result = NULL;
+}
+
+void
+gda_mysql_pstmt_set_mysql_bind_result (GdaMysqlPStmt *stmt, MYSQL_BIND *bind)
+{
+ GdaMysqlPStmtPrivate *priv = gda_mysql_pstmt_get_instance_private (stmt);
+ priv->mysql_bind_result = bind;
+}
diff --git a/providers/mysql/gda-mysql-pstmt.h b/providers/mysql/gda-mysql-pstmt.h
index fcce8fe86..b3c7de329 100644
--- a/providers/mysql/gda-mysql-pstmt.h
+++ b/providers/mysql/gda-mysql-pstmt.h
@@ -26,38 +26,24 @@
G_BEGIN_DECLS
#define GDA_TYPE_MYSQL_PSTMT (gda_mysql_pstmt_get_type())
-#define GDA_MYSQL_PSTMT(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GDA_TYPE_MYSQL_PSTMT,
GdaMysqlPStmt))
-#define GDA_MYSQL_PSTMT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST (klass, GDA_TYPE_MYSQL_PSTMT,
GdaMysqlPStmtClass))
-#define GDA_IS_MYSQL_PSTMT(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GDA_TYPE_MYSQL_PSTMT))
-#define GDA_IS_MYSQL_PSTMT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GDA_TYPE_MYSQL_PSTMT))
-typedef struct _GdaMysqlPStmt GdaMysqlPStmt;
-typedef struct _GdaMysqlPStmtClass GdaMysqlPStmtClass;
-
-struct _GdaMysqlPStmt {
- GdaPStmt object;
-
- GdaConnection *cnc;
-
- MYSQL *mysql;
- MYSQL_STMT *mysql_stmt;
- gboolean stmt_used; /* TRUE if a recorset already uses this prepared statement,
- * necessary because only one recordset can use mysql_stmt at a time */
- MYSQL_BIND *mysql_bind_result;
-};
+G_DECLARE_DERIVABLE_TYPE (GdaMysqlPStmt, gda_mysql_pstmt, GDA, MYSQL_PSTMT, GdaPStmt)
struct _GdaMysqlPStmtClass {
GdaPStmtClass parent_class;
};
-GType
-gda_mysql_pstmt_get_type (void) G_GNUC_CONST;
/* TO_ADD: helper function to create a GdaMysqlPStmt such as gda_mysql_pstmt_new() with some specific
arguments */
-GdaMysqlPStmt *
-gda_mysql_pstmt_new (GdaConnection *cnc,
- MYSQL *mysql,
- MYSQL_STMT *mysql_stmt);
+GdaMysqlPStmt *gda_mysql_pstmt_new (GdaConnection *cnc,
+ MYSQL *mysql,
+ MYSQL_STMT *mysql_stmt);
+gboolean gda_mysql_pstmt_get_stmt_used (GdaMysqlPStmt *stmt);
+void gda_mysql_pstmt_set_stmt_used (GdaMysqlPStmt *stmt, gboolean used);
+MYSQL_STMT *gda_mysql_pstmt_get_mysql_stmt (GdaMysqlPStmt *stmt);
+MYSQL_BIND *gda_mysql_pstmt_get_mysql_bind_result (GdaMysqlPStmt *stmt);
+void gda_mysql_pstmt_set_mysql_bind_result (GdaMysqlPStmt *stmt, MYSQL_BIND *bind);
+void gda_mysql_pstmt_free_mysql_bind_result (GdaMysqlPStmt *stmt);
G_END_DECLS
diff --git a/providers/mysql/gda-mysql-recordset.c b/providers/mysql/gda-mysql-recordset.c
index 62ab5eaae..8a783b803 100644
--- a/providers/mysql/gda-mysql-recordset.c
+++ b/providers/mysql/gda-mysql-recordset.c
@@ -13,6 +13,7 @@
* Copyright (C) 2005 Mike Fisk <mfisk woozle org>
* Copyright (C) 2005 Álvaro Peña <alvaropg telefonica net>
* Copyright (C) 2011 Murray Cumming <murrayc murrayc com>
+ * Copyright (C) 2019 Daniel Espinosa <esodan gmail com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -260,7 +261,7 @@ gda_mysql_recordset_dispose (GObject *object)
g_return_if_fail (GDA_IS_MYSQL_RECORDSET (recset));
GdaMysqlRecordsetPrivate *priv = gda_mysql_recordset_get_instance_private (recset);
- GDA_MYSQL_PSTMT (gda_data_select_get_prep_stmt (GDA_DATA_SELECT (object)))->stmt_used = FALSE;
+ gda_mysql_pstmt_set_stmt_used (GDA_MYSQL_PSTMT (gda_data_select_get_prep_stmt (GDA_DATA_SELECT
(object))), FALSE);
if (priv->cnc) {
g_object_unref (G_OBJECT(priv->cnc));
@@ -522,15 +523,15 @@ gda_mysql_recordset_new (GdaConnection *cnc,
if (!cdata)
return NULL;
- g_assert (ps->mysql_stmt);
+ g_assert (gda_mysql_pstmt_get_mysql_stmt(ps));
/* make sure @ps reports the correct number of columns using the API*/
if (gda_pstmt_get_ncols (_GDA_PSTMT (ps)) < 0)
- gda_pstmt_set_cols (_GDA_PSTMT(ps), mysql_stmt_field_count (ps->mysql_stmt),
gda_pstmt_get_types (_GDA_PSTMT(ps)));
+ gda_pstmt_set_cols (_GDA_PSTMT(ps), mysql_stmt_field_count
(gda_mysql_pstmt_get_mysql_stmt(ps)), gda_pstmt_get_types (_GDA_PSTMT(ps)));
/* completing @ps if not yet done */
- g_assert (! ps->stmt_used);
- ps->stmt_used = TRUE;
+ g_assert (! gda_mysql_pstmt_get_stmt_used (ps));
+ gda_mysql_pstmt_set_stmt_used (ps, TRUE);
if (!gda_pstmt_get_types (_GDA_PSTMT (ps)) && (gda_pstmt_get_ncols (_GDA_PSTMT (ps)) > 0)) {
/* create prepared statement's columns */
for (i = 0; i < gda_pstmt_get_ncols (_GDA_PSTMT (ps)); i++)
@@ -561,19 +562,12 @@ gda_mysql_recordset_new (GdaConnection *cnc,
}
/* get rid of old bound result if any */
- if (ps->mysql_bind_result) {
- gint i;
- for (i = 0; i < gda_pstmt_get_ncols (_GDA_PSTMT (ps)); ++i) {
- g_free (ps->mysql_bind_result[i].buffer);
- g_free (ps->mysql_bind_result[i].is_null);
- g_free (ps->mysql_bind_result[i].length);
- }
- g_free (ps->mysql_bind_result);
- ps->mysql_bind_result = NULL;
+ if (gda_mysql_pstmt_get_mysql_bind_result (ps)) {
+ gda_mysql_pstmt_free_mysql_bind_result (ps);
}
/* fill bind result */
- MYSQL_RES *mysql_res = mysql_stmt_result_metadata (ps->mysql_stmt);
+ MYSQL_RES *mysql_res = mysql_stmt_result_metadata (gda_mysql_pstmt_get_mysql_stmt(ps));
MYSQL_FIELD *mysql_fields = mysql_fetch_fields (mysql_res);
MYSQL_BIND *mysql_bind_result = g_new0 (MYSQL_BIND, gda_pstmt_get_ncols (_GDA_PSTMT (ps)));
@@ -650,13 +644,13 @@ gda_mysql_recordset_new (GdaConnection *cnc,
field->flags & UNSIGNED_FLAG);*/
}
- if (mysql_stmt_bind_result (ps->mysql_stmt, mysql_bind_result)) {
+ if (mysql_stmt_bind_result (gda_mysql_pstmt_get_mysql_stmt(ps), mysql_bind_result)) {
g_warning ("mysql_stmt_bind_result failed: %s\n",
- mysql_stmt_error (ps->mysql_stmt));
+ mysql_stmt_error (gda_mysql_pstmt_get_mysql_stmt(ps)));
}
mysql_free_result (mysql_res);
- ps->mysql_bind_result = mysql_bind_result;
+ gda_mysql_pstmt_set_mysql_bind_result (ps, mysql_bind_result);
/* determine access mode: RANDOM or CURSOR FORWARD are the only supported */
if (flags & GDA_DATA_MODEL_ACCESS_RANDOM)
@@ -675,9 +669,9 @@ gda_mysql_recordset_new (GdaConnection *cnc,
priv->cnc = cnc;
g_object_ref (G_OBJECT(cnc));
- priv->mysql_stmt = ps->mysql_stmt;
+ priv->mysql_stmt = gda_mysql_pstmt_get_mysql_stmt(ps);
- gda_data_select_set_advertized_nrows ((GdaDataSelect *) model, mysql_stmt_affected_rows
(ps->mysql_stmt));
+ gda_data_select_set_advertized_nrows ((GdaDataSelect *) model, mysql_stmt_affected_rows
(gda_mysql_pstmt_get_mysql_stmt(ps)));
return GDA_DATA_MODEL (model);
}
@@ -711,7 +705,7 @@ new_row_from_mysql_stmt (GdaMysqlRecordset *imodel, G_GNUC_UNUSED gint rownum, G
GdaMysqlRecordsetPrivate *priv = gda_mysql_recordset_get_instance_private (imodel);
g_return_val_if_fail (priv->mysql_stmt != NULL, NULL);
- mysql_bind_result = ((GdaMysqlPStmt *) gda_data_select_get_prep_stmt ((GdaDataSelect *)
imodel))->mysql_bind_result;
+ mysql_bind_result = gda_mysql_pstmt_get_mysql_bind_result ((GdaMysqlPStmt *)
gda_data_select_get_prep_stmt ((GdaDataSelect *) imodel));
g_assert (mysql_bind_result);
res = mysql_stmt_fetch (priv->mysql_stmt);
diff --git a/providers/mysql/gda-mysql-recordset.h b/providers/mysql/gda-mysql-recordset.h
index d57ffe43d..8fa16644d 100644
--- a/providers/mysql/gda-mysql-recordset.h
+++ b/providers/mysql/gda-mysql-recordset.h
@@ -5,6 +5,7 @@
* Copyright (C) 2001 - 2012 Vivien Malerba <malerba gnome-db org>
* Copyright (C) 2002 - 2003 Gonzalo Paniagua Javier <gonzalo ximian com>
* Copyright (C) 2005 Bas Driessen <bas driessen xobas com>
+ * Copyright (C) 2019 Daniel Espinosa <esodan gmail com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]