1 /*
2  * Copyright (C) YEAR The GNOME Foundation
3  *
4  * AUTHORS:
5  *      TO_ADD: your name and email
6  *      Vivien Malerba <malerba@gnome-db.org>
7  *
8  * This Library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This Library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this Library; see the file COPYING.LIB.  If not,
20  * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA  02110-1301, USA.
22  */
23 
24 #include <glib/gi18n-lib.h>
25 #include <string.h>
26 #include <libgda/libgda.h>
27 #include "gda-capi.h"
28 #include "gda-capi-blob-op.h"
29 #include <libgda/gda-debug-macros.h>
30 
31 struct _GdaCapiBlobOpPrivate {
32 	GdaConnection *cnc;
33 	/* TO_ADD: specific information describing a Blob in the C API */
34 };
35 
36 static void gda_capi_blob_op_class_init (GdaCapiBlobOpClass *klass);
37 static void gda_capi_blob_op_init       (GdaCapiBlobOp *blob,
38 					 GdaCapiBlobOpClass *klass);
39 static void gda_capi_blob_op_finalize   (GObject *object);
40 
41 static glong gda_capi_blob_op_get_length (GdaBlobOp *op);
42 static glong gda_capi_blob_op_read       (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size);
43 static glong gda_capi_blob_op_write      (GdaBlobOp *op, GdaBlob *blob, glong offset);
44 
45 static GObjectClass *parent_class = NULL;
46 
47 /*
48  * Object init and finalize
49  */
50 GType
gda_capi_blob_op_get_type(void)51 gda_capi_blob_op_get_type (void)
52 {
53 	static GType type = 0;
54 
55 	if (G_UNLIKELY (type == 0)) {
56 		static GMutex registering;
57 		static const GTypeInfo info = {
58 			sizeof (GdaCapiBlobOpClass),
59 			(GBaseInitFunc) NULL,
60 			(GBaseFinalizeFunc) NULL,
61 			(GClassInitFunc) gda_capi_blob_op_class_init,
62 			NULL,
63 			NULL,
64 			sizeof (GdaCapiBlobOp),
65 			0,
66 			(GInstanceInitFunc) gda_capi_blob_op_init,
67 			0
68 		};
69 		g_mutex_lock (&registering);
70 		if (type == 0)
71 			type = g_type_register_static (GDA_TYPE_BLOB_OP, "GdaCapiBlobOp", &info, 0);
72 		g_mutex_unlock (&registering);
73 	}
74 	return type;
75 }
76 
77 static void
gda_capi_blob_op_init(GdaCapiBlobOp * op,G_GNUC_UNUSED GdaCapiBlobOpClass * klass)78 gda_capi_blob_op_init (GdaCapiBlobOp *op,
79 			   G_GNUC_UNUSED GdaCapiBlobOpClass *klass)
80 {
81 	g_return_if_fail (GDA_IS_CAPI_BLOB_OP (op));
82 
83 	op->priv = g_new0 (GdaCapiBlobOpPrivate, 1);
84 
85 	/* initialize specific structure */
86 	TO_IMPLEMENT;
87 }
88 
89 static void
gda_capi_blob_op_class_init(GdaCapiBlobOpClass * klass)90 gda_capi_blob_op_class_init (GdaCapiBlobOpClass *klass)
91 {
92 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
93 	GdaBlobOpClass *blob_class = GDA_BLOB_OP_CLASS (klass);
94 
95 	parent_class = g_type_class_peek_parent (klass);
96 
97 	object_class->finalize = gda_capi_blob_op_finalize;
98 	blob_class->get_length = gda_capi_blob_op_get_length;
99 	blob_class->read = gda_capi_blob_op_read;
100 	blob_class->write = gda_capi_blob_op_write;
101 }
102 
103 static void
gda_capi_blob_op_finalize(GObject * object)104 gda_capi_blob_op_finalize (GObject * object)
105 {
106 	GdaCapiBlobOp *bop = (GdaCapiBlobOp *) object;
107 
108 	g_return_if_fail (GDA_IS_CAPI_BLOB_OP (bop));
109 
110 	/* free specific information */
111 	TO_IMPLEMENT;
112 
113 	g_free (bop->priv);
114 	bop->priv = NULL;
115 
116 	parent_class->finalize (object);
117 }
118 
119 GdaBlobOp *
gda_capi_blob_op_new(GdaConnection * cnc)120 gda_capi_blob_op_new (GdaConnection *cnc)
121 {
122 	GdaCapiBlobOp *bop;
123 
124 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
125 
126 	bop = g_object_new (GDA_TYPE_CAPI_BLOB_OP, NULL);
127 	bop->priv->cnc = cnc;
128 
129 	return GDA_BLOB_OP (bop);
130 }
131 
132 /*
133  * Get length request
134  */
135 static glong
gda_capi_blob_op_get_length(GdaBlobOp * op)136 gda_capi_blob_op_get_length (GdaBlobOp *op)
137 {
138 	GdaCapiBlobOp *bop;
139 
140 	g_return_val_if_fail (GDA_IS_CAPI_BLOB_OP (op), -1);
141 	bop = GDA_CAPI_BLOB_OP (op);
142 	g_return_val_if_fail (bop->priv, -1);
143 	g_return_val_if_fail (GDA_IS_CONNECTION (bop->priv->cnc), -1);
144 
145 	TO_IMPLEMENT;
146 	return -1;
147 }
148 
149 /*
150  * Blob read request
151  */
152 static glong
gda_capi_blob_op_read(GdaBlobOp * op,GdaBlob * blob,glong offset,glong size)153 gda_capi_blob_op_read (GdaBlobOp *op, GdaBlob *blob, glong offset, glong size)
154 {
155 	GdaCapiBlobOp *bop;
156 	GdaBinary *bin;
157 
158 	g_return_val_if_fail (GDA_IS_CAPI_BLOB_OP (op), -1);
159 	bop = GDA_CAPI_BLOB_OP (op);
160 	g_return_val_if_fail (bop->priv, -1);
161 	g_return_val_if_fail (GDA_IS_CONNECTION (bop->priv->cnc), -1);
162 	if (offset >= G_MAXINT)
163 		return -1;
164 	g_return_val_if_fail (blob, -1);
165 
166 	bin = (GdaBinary *) blob;
167 	if (bin->data)
168 		g_free (bin->data);
169 	bin->data = g_new0 (guchar, size);
170 	bin->binary_length = 0;
171 
172 	/* fetch blob data using C API into bin->data, and set bin->binary_length */
173 	TO_IMPLEMENT;
174 
175 	return bin->binary_length;
176 }
177 
178 /*
179  * Blob write request
180  */
181 static glong
gda_capi_blob_op_write(GdaBlobOp * op,GdaBlob * blob,G_GNUC_UNUSED glong offset)182 gda_capi_blob_op_write (GdaBlobOp *op, GdaBlob *blob, G_GNUC_UNUSED glong offset)
183 {
184 	GdaCapiBlobOp *bop;
185 	GdaBinary *bin = NULL;
186 	glong nbwritten = -1;
187 
188 	g_return_val_if_fail (GDA_IS_CAPI_BLOB_OP (op), -1);
189 	bop = GDA_CAPI_BLOB_OP (op);
190 	g_return_val_if_fail (bop->priv, -1);
191 	g_return_val_if_fail (GDA_IS_CONNECTION (bop->priv->cnc), -1);
192 	g_return_val_if_fail (blob, -1);
193 
194 	if (blob->op && (blob->op != op)) {
195 		/* use data through blob->op */
196 		#define buf_size 16384
197 		gint nread = 0;
198 		GdaBlob *tmpblob = g_new0 (GdaBlob, 1);
199 		gda_blob_set_op (tmpblob, blob->op);
200 
201 		nbwritten = 0;
202 
203 		for (nread = gda_blob_op_read (tmpblob->op, tmpblob, nbwritten, buf_size);
204 		     nread > 0;
205 		     nread = gda_blob_op_read (tmpblob->op, tmpblob, nbwritten, buf_size)) {
206 			glong tmp_written;
207 
208 			tmp_written = -1; TO_IMPLEMENT;
209 
210 			if (tmp_written < 0) {
211 				/* treat error */
212 				gda_blob_free ((gpointer) tmpblob);
213 				return -1;
214 			}
215 			nbwritten += tmp_written;
216 			if (nread < buf_size)
217 				/* nothing more to read */
218 				break;
219 		}
220 		gda_blob_free ((gpointer) tmpblob);
221 	}
222 	else {
223 		/* write blob using bin->data and bin->binary_length */
224 		bin = (GdaBinary *) blob;
225     		g_warning("bin not used. length=%ld", bin->binary_length); /* Avoids a compiler warning. */
226 		nbwritten = -1; TO_IMPLEMENT;
227 	}
228 
229 	return nbwritten;
230 }
231