<commit_before>/*
 * Copyright (C) 2008-2010, Nokia <<EMAIL>>
 * Copyright (C) 2010, Codeminded BVBA <<EMAIL>>
 *
 * 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#include "config.h"

#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>

#include <libtracker-common/tracker-common.h>

#include <libtracker-sparql/tracker-sparql.h>

#include "tracker-bus.h"
#include "tracker-bus-fd-cursor.h"

#define TRACKER_TYPE_BUS_FD_CURSOR           (tracker_bus_fd_cursor_get_type ())
#define TRACKER_BUS_FD_CURSOR(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRACKER_TYPE_BUS_FD_CURSOR, TrackerBusFDCursor))
#define TRACKER_BUS_FD_CURSOR_CLASS(c)       (G_TYPE_CHECK_CLASS_CAST ((c),      TRACKER_TYPE_BUS_FD_CURSOR, TrackerBusFDCursorClass))
#define TRACKER_IS_BUS_FD_CURSOR(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRACKER_TYPE_BUS_FD_CURSOR))
#define TRACKER_IS_BUS_FD_CURSOR_CLASS(c)    (G_TYPE_CHECK_CLASS_TYPE ((o),      TRACKER_TYPE_BUS_FD_CURSOR))
#define TRACKER_BUS_FD_CURSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),  TRACKER_TYPE_BUS_FD_CURSOR, TrackerBusFDCursorClass))

typedef struct TrackerBusFDCursor TrackerBusFDCursor;
typedef struct TrackerBusFDCursorClass TrackerBusFDCursorClass;

struct TrackerBusFDCursor {
	TrackerSparqlCursor parent_instance;

	char *buffer;
	int buffer_index;
	long buffer_size;

	guint n_columns;
	int *offsets;
	int *types;
	char *data;
	GStrv variable_names;
};

struct TrackerBusFDCursorClass {
	TrackerSparqlCursorClass parent_class;
};

GType tracker_bus_fd_cursor_get_type (void);
void  tracker_bus_fd_cursor_finalize (GObject *object);

G_DEFINE_TYPE (TrackerBusFDCursor, tracker_bus_fd_cursor, TRACKER_SPARQL_TYPE_CURSOR)

static void
tracker_bus_fd_cursor_rewind (TrackerBusFDCursor *cursor)
{
	cursor->buffer_index = 0;
	cursor->data = cursor->buffer;
}

static inline int
buffer_read_int (TrackerBusFDCursor *cursor)
{
	int v = *((int *)(cursor->buffer + cursor->buffer_index));

	cursor->buffer_index += 4;

	return v;
}


static gboolean
tracker_bus_fd_cursor_iter_next (TrackerBusFDCursor  *cursor,
                                 GCancellable        *cancellable,
                                 GError             **error)
{
	int last_offset;

	if (cursor->buffer_index >= cursor->buffer_size) {
		return FALSE;
	}

	/* So, the make up on each cursor segment is:
	 *
	 * iteration = [4 bytes for number of columns,
	 *              columns x 4 bytes for types
	 *              columns x 4 bytes for offsets]
	 */

	cursor->n_columns = buffer_read_int (cursor);

	/* Storage of ints that will be casted to TrackerSparqlValueType enums,
	 * also see tracker_bus_fd_cursor_get_value_type */
	cursor->types = (int *)(cursor->buffer + cursor->buffer_index);
	cursor->buffer_index += sizeof (int) * (cursor->n_columns);

	cursor->offsets = (int *)(cursor->buffer + cursor->buffer_index);
	cursor->buffer_index += sizeof (int) * (cursor->n_columns - 1);
	last_offset = buffer_read_int (cursor);

	cursor->data = cursor->buffer + cursor->buffer_index;

	cursor->buffer_index += last_offset + 1;

	return TRUE;
}

static void
tracker_bus_fd_cursor_iter_next_thread (GSimpleAsyncResult *res,
                                        GObject            *object,
                                        GCancellable       *cancellable)
{
	/* This is stolen from the direct access work, 
	 * do we REALLY need to do this in the next thread? 
	 */

	GError *error = NULL;
	gboolean result;

	result = tracker_bus_fd_cursor_iter_next (TRACKER_BUS_FD_CURSOR (object), cancellable, &error);
	if (error) {
		g_simple_async_result_set_from_error (res, error);
	} else {
		g_simple_async_result_set_op_res_gboolean (res, result);
	}
}

static void
tracker_bus_fd_cursor_iter_next_async (TrackerBusFDCursor    *cursor,
                                       GCancellable          *cancellable,
                                       GAsyncReadyCallback    callback,
                                       gpointer               user_data)
{
	GSimpleAsyncResult *res;

	res = g_simple_async_result_new (G_OBJECT (cursor), callback, user_data, tracker_bus_fd_cursor_iter_next_async);
	g_simple_async_result_run_in_thread (res, tracker_bus_fd_cursor_iter_next_thread, 0, cancellable);
}

static gboolean
tracker_bus_fd_cursor_iter_next_finish (TrackerBusFDCursor *cursor,
                                        GAsyncResult       *res,
                                        GError            **error)
{
	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) {
		return FALSE;
	}
	return g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (res));
}

static guint
tracker_bus_fd_cursor_get_n_columns (TrackerBusFDCursor *cursor)
{
	return cursor->n_columns;
}

static TrackerSparqlValueType
tracker_bus_fd_cursor_get_value_type (TrackerBusFDCursor *cursor,  guint column)
{
	/* Cast from int to enum */
	return (TrackerSparqlValueType) cursor->types[column];
}

static const gchar*
tracker_bus_fd_cursor_get_variable_name (TrackerBusFDCursor *cursor,  guint column)
{
	if (!cursor->variable_names)
		return NULL;

	return cursor->variable_names[column];
}

static const gchar *
tracker_bus_fd_cursor_get_string (TrackerBusFDCursor *cursor,
                                  guint               column,
                                  glong              *length)
{
	const gchar *str = NULL;

	if (length) {
		*length = 0;
	}
<commit_msg>libtracker-bus: Use g_return_val_if_fail instead of if(fail)return;<commit_after>/*
 * Copyright (C) 2008-2010, Nokia <<EMAIL>>
 * Copyright (C) 2010, Codeminded BVBA <<EMAIL>>
 *
 * 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#include "config.h"

#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>

#include <libtracker-common/tracker-common.h>

#include <libtracker-sparql/tracker-sparql.h>

#include "tracker-bus.h"
#include "tracker-bus-fd-cursor.h"

#define TRACKER_TYPE_BUS_FD_CURSOR           (tracker_bus_fd_cursor_get_type ())
#define TRACKER_BUS_FD_CURSOR(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRACKER_TYPE_BUS_FD_CURSOR, TrackerBusFDCursor))
#define TRACKER_BUS_FD_CURSOR_CLASS(c)       (G_TYPE_CHECK_CLASS_CAST ((c),      TRACKER_TYPE_BUS_FD_CURSOR, TrackerBusFDCursorClass))
#define TRACKER_IS_BUS_FD_CURSOR(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRACKER_TYPE_BUS_FD_CURSOR))
#define TRACKER_IS_BUS_FD_CURSOR_CLASS(c)    (G_TYPE_CHECK_CLASS_TYPE ((o),      TRACKER_TYPE_BUS_FD_CURSOR))
#define TRACKER_BUS_FD_CURSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),  TRACKER_TYPE_BUS_FD_CURSOR, TrackerBusFDCursorClass))

typedef struct TrackerBusFDCursor TrackerBusFDCursor;
typedef struct TrackerBusFDCursorClass TrackerBusFDCursorClass;

struct TrackerBusFDCursor {
	TrackerSparqlCursor parent_instance;

	char *buffer;
	int buffer_index;
	long buffer_size;

	guint n_columns;
	int *offsets;
	int *types;
	char *data;
	GStrv variable_names;
};

struct TrackerBusFDCursorClass {
	TrackerSparqlCursorClass parent_class;
};

GType tracker_bus_fd_cursor_get_type (void);
void  tracker_bus_fd_cursor_finalize (GObject *object);

G_DEFINE_TYPE (TrackerBusFDCursor, tracker_bus_fd_cursor, TRACKER_SPARQL_TYPE_CURSOR)

static void
tracker_bus_fd_cursor_rewind (TrackerBusFDCursor *cursor)
{
	cursor->buffer_index = 0;
	cursor->data = cursor->buffer;
}

static inline int
buffer_read_int (TrackerBusFDCursor *cursor)
{
	int v = *((int *)(cursor->buffer + cursor->buffer_index));

	cursor->buffer_index += 4;

	return v;
}


static gboolean
tracker_bus_fd_cursor_iter_next (TrackerBusFDCursor  *cursor,
                                 GCancellable        *cancellable,
                                 GError             **error)
{
	int last_offset;

	if (cursor->buffer_index >= cursor->buffer_size) {
		return FALSE;
	}

	/* So, the make up on each cursor segment is:
	 *
	 * iteration = [4 bytes for number of columns,
	 *              columns x 4 bytes for types
	 *              columns x 4 bytes for offsets]
	 */

	cursor->n_columns = buffer_read_int (cursor);

	/* Storage of ints that will be casted to TrackerSparqlValueType enums,
	 * also see tracker_bus_fd_cursor_get_value_type */
	cursor->types = (int *)(cursor->buffer + cursor->buffer_index);
	cursor->buffer_index += sizeof (int) * (cursor->n_columns);

	cursor->offsets = (int *)(cursor->buffer + cursor->buffer_index);
	cursor->buffer_index += sizeof (int) * (cursor->n_columns - 1);
	last_offset = buffer_read_int (cursor);

	cursor->data = cursor->buffer + cursor->buffer_index;

	cursor->buffer_index += last_offset + 1;

	return TRUE;
}

static void
tracker_bus_fd_cursor_iter_next_thread (GSimpleAsyncResult *res,
                                        GObject            *object,
                                        GCancellable       *cancellable)
{
	/* This is stolen from the direct access work, 
	 * do we REALLY need to do this in the next thread? 
	 */

	GError *error = NULL;
	gboolean result;

	result = tracker_bus_fd_cursor_iter_next (TRACKER_BUS_FD_CURSOR (object), cancellable, &error);
	if (error) {
		g_simple_async_result_set_from_error (res, error);
	} else {
		g_simple_async_result_set_op_res_gboolean (res, result);
	}
}

static void
tracker_bus_fd_cursor_iter_next_async (TrackerBusFDCursor    *cursor,
                                       GCancellable          *cancellable,
                                       GAsyncReadyCallback    callback,
                                       gpointer               user_data)
{
	GSimpleAsyncResult *res;

	res = g_simple_async_result_new (G_OBJECT (cursor), callback, user_data, tracker_bus_fd_cursor_iter_next_async);
	g_simple_async_result_run_in_thread (res, tracker_bus_fd_cursor_iter_next_thread, 0, cancellable);
}

static gboolean
tracker_bus_fd_cursor_iter_next_finish (TrackerBusFDCursor *cursor,
                                        GAsyncResult       *res,
                                        GError            **error)
{
	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) {
		return FALSE;
	}
	return g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (res));
}

static guint
tracker_bus_fd_cursor_get_n_columns (TrackerBusFDCursor *cursor)
{
	return cursor->n_columns;
}

static TrackerSparqlValueType
tracker_bus_fd_cursor_get_value_type (TrackerBusFDCursor *cursor,  guint column)
{
	g_return_val_if_fail (cursor->types != NULL, TRACKER_SPARQL_VALUE_TYPE_UNBOUND);

	/* Cast from int to enum */
	return (TrackerSparqlValueType) cursor->types[column];
}

static const gchar*
tracker_bus_fd_cursor_get_variable_name (TrackerBusFDCursor *cursor,  guint column)
{
	g_return_val_if_fail (cursor->variable_names != NULL, NULL);

	return cursor->variable_names[column];
}

static const gchar *
tracker_bus_fd_cursor_get_string (TrackerBusFDCursor *cursor,
                                  guint               column,
                                  glong              *length)
{
	const gchar *str = NULL;

	if (length) {
		*length = 0;
	}

{'fraction_non_alphanumeric': 0.08412189254210105, 'fraction_numerical': 0.00545308740978348, 'mean_word_length': 3.5086767895878523, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 80, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6877192', 'n_tokens_mistral': 4203, 'n_tokens_neox': 4031, 'n_words': 967}