GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 45.3% 43 / 0 / 95
Functions: 47.1% 8 / 0 / 17
Branches: 25.0% 13 / 0 / 52

shumate/shumate-data-source.c
Line Branch Exec Source
1 /*
2 * Copyright (C) 2021 James Westman <james@jwestman.net>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
16 */
17
18 typedef struct {
19 int min_zoom_level;
20 int max_zoom_level;
21 } ShumateDataSourcePrivate;
22
23 #include "shumate-data-source.h"
24 #include "shumate-data-source-request.h"
25
26 /**
27 * ShumateDataSource:
28 *
29 * The base class used to retrieve tiles as [struct@GLib.Bytes].
30 */
31
32
4/6
shumate_data_source_class_intern_init:
✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 5 not taken.
shumate_data_source_get_type:
✓ Branch 2 → 3 taken 7 times.
✓ Branch 2 → 7 taken 64 times.
✓ Branch 4 → 5 taken 7 times.
✗ Branch 4 → 7 not taken.
145 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ShumateDataSource, shumate_data_source, G_TYPE_OBJECT)
33
34 enum {
35 PROP_0,
36 PROP_MIN_ZOOM_LEVEL,
37 PROP_MAX_ZOOM_LEVEL,
38 N_PROPS,
39 };
40
41 static GParamSpec *properties[N_PROPS];
42
43 enum
44 {
45 RECEIVED_DATA,
46 LAST_SIGNAL
47 };
48 static guint signals[LAST_SIGNAL] = { 0, };
49
50
51 static void
52 ✗ shumate_data_source_get_property (GObject *object,
53 guint prop_id,
54 GValue *value,
55 GParamSpec *pspec)
56 {
57 ✗ ShumateDataSource *data_source = SHUMATE_DATA_SOURCE (object);
58
59 ✗ switch (prop_id)
60 {
61 ✗ case PROP_MIN_ZOOM_LEVEL:
62 ✗ g_value_set_uint (value, shumate_data_source_get_min_zoom_level (data_source));
63 ✗ break;
64
65 ✗ case PROP_MAX_ZOOM_LEVEL:
66 ✗ g_value_set_uint (value, shumate_data_source_get_max_zoom_level (data_source));
67 ✗ break;
68
69 ✗ default:
70 ✗ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
71 }
72 ✗ }
73
74 static void
75 48 shumate_data_source_set_property (GObject *object,
76 guint prop_id,
77 const GValue *value,
78 GParamSpec *pspec)
79 {
80 48 ShumateDataSource *data_source = SHUMATE_DATA_SOURCE (object);
81
82
2/3
✓ Branch 2 → 3 taken 24 times.
✓ Branch 2 → 6 taken 24 times.
✗ Branch 2 → 9 not taken.
48 switch (prop_id)
83 {
84 24 case PROP_MIN_ZOOM_LEVEL:
85 24 shumate_data_source_set_min_zoom_level (data_source,
86 g_value_get_uint (value));
87 24 break;
88
89 24 case PROP_MAX_ZOOM_LEVEL:
90 24 shumate_data_source_set_max_zoom_level (data_source,
91 g_value_get_uint (value));
92 24 break;
93
94 ✗ default:
95 ✗ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
96 }
97 48 }
98
99 static GBytes *
100 ✗ shumate_data_source_real_get_tile_data_finish (ShumateDataSource *self,
101 GAsyncResult *result,
102 GError **error)
103 {
104 ✗ g_return_val_if_fail (SHUMATE_IS_DATA_SOURCE (self), FALSE);
105 ✗ g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
106
107 ✗ return g_task_propagate_pointer (G_TASK (result), error);
108 }
109
110 static void
111 ✗ on_get_tile_data_done (GObject *source,
112 GAsyncResult *result,
113 gpointer user_data)
114 {
115 ✗ ShumateDataSource *self = (ShumateDataSource *)source;
116 ✗ g_autoptr(ShumateDataSourceRequest) req = user_data;
117 ✗ g_autoptr(GError) error = NULL;
118 ✗ g_autoptr(GBytes) data = NULL;
119
120 ✗ data = shumate_data_source_get_tile_data_finish (self, result, &error);
121
122 ✗ if (data)
123 ✗ shumate_data_source_request_emit_data (req, data, TRUE);
124 else
125 ✗ shumate_data_source_request_emit_error (req, error);
126 ✗ }
127
128 static ShumateDataSourceRequest *
129 ✗ shumate_data_source_real_start_request (ShumateDataSource *self,
130 int x,
131 int y,
132 int zoom_level,
133 GCancellable *cancellable)
134 {
135 ✗ ShumateDataSourceRequest *req = shumate_data_source_request_new (x, y, zoom_level);
136 ✗ shumate_data_source_get_tile_data_async (self,
137 x, y, zoom_level,
138 cancellable,
139 on_get_tile_data_done,
140 g_object_ref (req));
141 ✗ return req;
142 }
143
144 static void
145 7 shumate_data_source_class_init (ShumateDataSourceClass *klass)
146 {
147 7 GObjectClass *object_class = G_OBJECT_CLASS (klass);
148
149 7 object_class->get_property = shumate_data_source_get_property;
150 7 object_class->set_property = shumate_data_source_set_property;
151
152 7 klass->get_tile_data_async = NULL;
153 7 klass->get_tile_data_finish = shumate_data_source_real_get_tile_data_finish;
154 7 klass->start_request = shumate_data_source_real_start_request;
155
156 /**
157 * ShumateDataSource:min-zoom-level:
158 *
159 * The minimum zoom level
160 *
161 * Since: 1.1
162 */
163 14 properties[PROP_MIN_ZOOM_LEVEL] =
164 7 g_param_spec_uint ("min-zoom-level", NULL, NULL,
165 0, 30, 0,
166 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY);
167
168 /**
169 * ShumateDataSource:max-zoom-level:
170 *
171 * The maximum zoom level
172 *
173 * Since: 1.1
174 */
175 14 properties[PROP_MAX_ZOOM_LEVEL] =
176 7 g_param_spec_uint ("max-zoom-level", NULL, NULL,
177 0, 30, 30,
178 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY);
179
180 7 g_object_class_install_properties (object_class,
181 N_PROPS,
182 properties);
183
184 /**
185 * ShumateDataSource::received-data:
186 * @self: the [class@DataSource] emitting the signal
187 * @x: the X coordinate of the tile
188 * @y: the Y coordinate of the tile
189 * @zoom_level: the zoom level of the tile
190 * @bytes: the received data
191 *
192 * Emitted when data is received for any tile. This includes any intermediate
193 * steps, such as data from the file cache, as well as the final result.
194 *
195 * Deprecated: 1.1: Use [method@DataSource.start_request] and connect to the
196 * notify signals of the resulting [class@DataSourceRequest].
197 */
198 14 signals[RECEIVED_DATA] =
199 7 g_signal_new ("received-data",
200 G_OBJECT_CLASS_TYPE (object_class),
201 G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED,
202 0, NULL, NULL,
203 NULL,
204 G_TYPE_NONE,
205 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_BYTES);
206 7 }
207
208 static void
209 24 shumate_data_source_init (ShumateDataSource *self)
210 {
211 24 }
212
213
214 /**
215 * shumate_data_source_get_tile_data_async:
216 * @self: a [class@DataSource]
217 * @x: the X coordinate to fetch
218 * @y: the Y coordinate to fetch
219 * @zoom_level: the Z coordinate to fetch
220 * @cancellable: a #GCancellable
221 * @callback: a #GAsyncReadyCallback to execute upon completion
222 * @user_data: closure data for @callback
223 *
224 * Gets the data for the tile at the given coordinates.
225 *
226 * Some data sources may return data multiple times. For example,
227 * [class@TileDownloader] may return data from a cache, then return updated
228 * data from the network. [signal@ShumateDataSource::received-data] is emitted
229 * each time data is received, then @callback is called after the last update.
230 */
231 void
232 ✗ shumate_data_source_get_tile_data_async (ShumateDataSource *self,
233 int x,
234 int y,
235 int zoom_level,
236 GCancellable *cancellable,
237 GAsyncReadyCallback callback,
238 gpointer user_data)
239 {
240 ✗ g_return_if_fail (SHUMATE_IS_DATA_SOURCE (self));
241 ✗ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
242
243 ✗ return SHUMATE_DATA_SOURCE_GET_CLASS (self)->get_tile_data_async (self, x, y, zoom_level, cancellable, callback, user_data);
244 }
245
246
247 /**
248 * shumate_data_source_get_tile_data_finish:
249 * @self: a [class@DataSource]
250 * @result: a #GAsyncResult provided to callback
251 * @error: a location for a #GError, or %NULL
252 *
253 * Gets the final result of a request started with
254 * shumate_data_source_get_tile_data_async().
255 *
256 * Returns: (transfer full) (nullable): The requested data, or %NULL if an
257 * error occurred
258 */
259 GBytes *
260 ✗ shumate_data_source_get_tile_data_finish (ShumateDataSource *self,
261 GAsyncResult *result,
262 GError **error)
263 {
264 ✗ g_return_val_if_fail (SHUMATE_IS_DATA_SOURCE (self), FALSE);
265
266 ✗ return SHUMATE_DATA_SOURCE_GET_CLASS (self)->get_tile_data_finish (self, result, error);
267 }
268
269
270 /**
271 * shumate_data_source_start_request:
272 * @self: a [class@DataSource]
273 * @x: X coordinate to request
274 * @y: Y coordinate to request
275 * @zoom_level: zoom level to request
276 * @cancellable: for cancelling the request
277 *
278 * Begins a request for a tile.
279 *
280 * Returns: (transfer full): a [class@DataSourceRequest] object for tracking
281 * the request.
282 *
283 * Since: 1.1
284 */
285 ShumateDataSourceRequest *
286 ✗ shumate_data_source_start_request (ShumateDataSource *self,
287 int x,
288 int y,
289 int zoom_level,
290 GCancellable *cancellable)
291 {
292 ✗ g_return_val_if_fail (SHUMATE_IS_DATA_SOURCE (self), NULL);
293
294 ✗ return SHUMATE_DATA_SOURCE_GET_CLASS (self)->start_request (self, x, y, zoom_level, cancellable);
295 }
296
297
298 /**
299 * shumate_data_source_get_min_zoom_level:
300 * @self: a [class@DataSource]
301 *
302 * Gets the data source's minimum zoom level.
303 *
304 * Returns: the minimum zoom level this data source supports
305 *
306 * Since: 1.1
307 */
308 guint
309 ✗ shumate_data_source_get_min_zoom_level (ShumateDataSource *self)
310 {
311 ✗ ShumateDataSourcePrivate *priv = shumate_data_source_get_instance_private (self);
312
313 ✗ g_return_val_if_fail (SHUMATE_IS_DATA_SOURCE (self), 0);
314
315 ✗ return priv->min_zoom_level;
316 }
317
318 /**
319 * shumate_data_source_set_min_zoom_level:
320 * @self: a [class@DataSource]
321 * @zoom_level: the minimum zoom level
322 *
323 * Sets the data source's minimum zoom level.
324 *
325 * Since: 1.1
326 */
327 void
328 30 shumate_data_source_set_min_zoom_level (ShumateDataSource *self,
329 guint zoom_level)
330 {
331 30 ShumateDataSourcePrivate *priv = shumate_data_source_get_instance_private (self);
332
333
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 30 times.
30 g_return_if_fail (SHUMATE_IS_DATA_SOURCE (self));
334
1/2
✓ Branch 5 → 6 taken 30 times.
✗ Branch 5 → 7 not taken.
30 g_return_if_fail (zoom_level <= 30u);
335
336
1/2
✗ Branch 6 → 8 not taken.
✓ Branch 6 → 9 taken 30 times.
30 if (priv->min_zoom_level != zoom_level)
337 {
338 ✗ priv->min_zoom_level = zoom_level;
339
340 ✗ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MIN_ZOOM_LEVEL]);
341 }
342 }
343
344 /**
345 * shumate_data_source_get_max_zoom_level:
346 * @self: a [class@DataSource]
347 *
348 * Gets the data source's maximum zoom level.
349 *
350 * Returns: the maximum zoom level this data source supports
351 *
352 * Since: 1.1
353 */
354 guint
355 ✗ shumate_data_source_get_max_zoom_level (ShumateDataSource *self)
356 {
357 ✗ ShumateDataSourcePrivate *priv = shumate_data_source_get_instance_private (self);
358
359 ✗ g_return_val_if_fail (SHUMATE_IS_DATA_SOURCE (self), 0);
360
361 ✗ return priv->max_zoom_level;
362 }
363
364 /**
365 * shumate_data_source_set_max_zoom_level:
366 * @self: a [class@DataSource]
367 * @zoom_level: the maximum zoom level
368 *
369 * Sets the data source's maximum zoom level.
370 *
371 * Since: 1.1
372 */
373 void
374 30 shumate_data_source_set_max_zoom_level (ShumateDataSource *self,
375 guint zoom_level)
376 {
377 30 ShumateDataSourcePrivate *priv = shumate_data_source_get_instance_private (self);
378
379
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 30 times.
30 g_return_if_fail (SHUMATE_IS_DATA_SOURCE (self));
380
1/2
✓ Branch 5 → 6 taken 30 times.
✗ Branch 5 → 7 not taken.
30 g_return_if_fail (zoom_level <= 30u);
381
382
2/2
✓ Branch 6 → 8 taken 24 times.
✓ Branch 6 → 9 taken 6 times.
30 if (priv->max_zoom_level != zoom_level)
383 {
384 24 priv->max_zoom_level = zoom_level;
385
386 24 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MAX_ZOOM_LEVEL]);
387 }
388 }
389
390