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 (®istering);
70 if (type == 0)
71 type = g_type_register_static (GDA_TYPE_BLOB_OP, "GdaCapiBlobOp", &info, 0);
72 g_mutex_unlock (®istering);
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