Blame src/xb-stack.c

Packit Service a3c5fa
/*
Packit Service a3c5fa
 * Copyright (C) 2018 Richard Hughes <richard@hughsie.com>
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * SPDX-License-Identifier: LGPL-2.1+
Packit Service a3c5fa
 */
Packit Service a3c5fa
Packit Service a3c5fa
#define G_LOG_DOMAIN				"XbMachine"
Packit Service a3c5fa
Packit Service a3c5fa
#include "config.h"
Packit Service a3c5fa
Packit Service a3c5fa
#include <gio/gio.h>
Packit Service a3c5fa
Packit Service a3c5fa
#include "xb-opcode-private.h"
Packit Service a3c5fa
#include "xb-stack-private.h"
Packit Service a3c5fa
Packit Service a3c5fa
struct _XbStack {
Packit Service a3c5fa
	gint		 ref;
Packit Service a3c5fa
	guint		 pos;
Packit Service a3c5fa
	guint		 max_size;
Packit Service a3c5fa
	XbOpcode	*opcodes[];	/* allocated as part of XbStack */
Packit Service a3c5fa
};
Packit Service a3c5fa
Packit Service a3c5fa
/**
Packit Service a3c5fa
 * xb_stack_unref:
Packit Service a3c5fa
 * @self: a #XbStack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Decrements the reference count of the stack, freeing the object when the
Packit Service a3c5fa
 * refcount drops to zero.
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Since: 0.1.3
Packit Service a3c5fa
 **/
Packit Service a3c5fa
void
Packit Service a3c5fa
xb_stack_unref (XbStack *self)
Packit Service a3c5fa
{
Packit Service a3c5fa
	g_assert (self->ref > 0);
Packit Service a3c5fa
	if (--self->ref > 0)
Packit Service a3c5fa
		return;
Packit Service a3c5fa
	for (guint i = 0; i < self->pos; i++)
Packit Service a3c5fa
		xb_opcode_unref (self->opcodes[i]);
Packit Service a3c5fa
	g_free (self);
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/**
Packit Service a3c5fa
 * xb_stack_ref:
Packit Service a3c5fa
 * @self: a #XbStack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Increments the refcount of the stack.
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Returns: (transfer none): the original @self #XbStack instance
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Since: 0.1.3
Packit Service a3c5fa
 **/
Packit Service a3c5fa
XbStack *
Packit Service a3c5fa
xb_stack_ref (XbStack *self)
Packit Service a3c5fa
{
Packit Service a3c5fa
	self->ref++;
Packit Service a3c5fa
	return self;
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
Packit Service a3c5fa
/**
Packit Service a3c5fa
 * xb_stack_pop:
Packit Service a3c5fa
 * @self: a #XbStack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Pops an opcode off the stack.
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Returns: (transfer full): a #XbOpcode
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Since: 0.1.3
Packit Service a3c5fa
 **/
Packit Service a3c5fa
XbOpcode *
Packit Service a3c5fa
xb_stack_pop (XbStack *self)
Packit Service a3c5fa
{
Packit Service a3c5fa
	if (self->pos == 0)
Packit Service a3c5fa
		return NULL;
Packit Service a3c5fa
	return self->opcodes[--self->pos];
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/* private */
Packit Service a3c5fa
GPtrArray *
Packit Service a3c5fa
xb_stack_steal_all (XbStack *self)
Packit Service a3c5fa
{
Packit Service a3c5fa
	GPtrArray *array;
Packit Service a3c5fa
Packit Service a3c5fa
	/* array takes ownership of the opcodes */
Packit Service a3c5fa
	array = g_ptr_array_new_with_free_func ((GDestroyNotify) xb_opcode_unref);
Packit Service a3c5fa
	for (guint i = 0; i < self->pos; i++)
Packit Service a3c5fa
		g_ptr_array_add (array, self->opcodes[i]);
Packit Service a3c5fa
	self->pos = 0;
Packit Service a3c5fa
	return array;
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/**
Packit Service a3c5fa
 * xb_stack_peek:
Packit Service a3c5fa
 * @self: a #XbStack
Packit Service a3c5fa
 * @idx: index
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Peeks an opcode from the stack.
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Returns: (transfer none): a #XbOpcode
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Since: 0.1.3
Packit Service a3c5fa
 **/
Packit Service a3c5fa
XbOpcode *
Packit Service a3c5fa
xb_stack_peek (XbStack *self, guint idx)
Packit Service a3c5fa
{
Packit Service a3c5fa
	if (idx >= self->pos)
Packit Service a3c5fa
		return NULL;
Packit Service a3c5fa
	return self->opcodes[idx];
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/* private */
Packit Service a3c5fa
gboolean
Packit Service a3c5fa
xb_stack_push_bool (XbStack *self, gboolean val)
Packit Service a3c5fa
{
Packit Service a3c5fa
	return xb_stack_push_steal (self, xb_opcode_bool_new (val));
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/* private */
Packit Service a3c5fa
XbOpcode *
Packit Service a3c5fa
xb_stack_peek_head (XbStack *self)
Packit Service a3c5fa
{
Packit Service a3c5fa
	if (self->pos == 0)
Packit Service a3c5fa
		return NULL;
Packit Service a3c5fa
	return self->opcodes[0];
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/* private */
Packit Service a3c5fa
XbOpcode *
Packit Service a3c5fa
xb_stack_peek_tail (XbStack *self)
Packit Service a3c5fa
{
Packit Service a3c5fa
	if (self->pos == 0)
Packit Service a3c5fa
		return NULL;
Packit Service a3c5fa
	return self->opcodes[self->pos - 1];
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/**
Packit Service a3c5fa
 * xb_stack_push:
Packit Service a3c5fa
 * @self: a #XbStack
Packit Service a3c5fa
 * @opcode: a #XbOpcode
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Pushes a new opcode onto the end of the stack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Returns: %TRUE if the opcode was stored on the stack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Since: 0.1.3
Packit Service a3c5fa
 **/
Packit Service a3c5fa
gboolean
Packit Service a3c5fa
xb_stack_push (XbStack *self, XbOpcode *opcode)
Packit Service a3c5fa
{
Packit Service a3c5fa
	if (self->pos >= self->max_size)
Packit Service a3c5fa
		return FALSE;
Packit Service a3c5fa
	self->opcodes[self->pos++] = xb_opcode_ref (opcode);
Packit Service a3c5fa
	return TRUE;
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/**
Packit Service a3c5fa
 * xb_stack_push_steal:
Packit Service a3c5fa
 * @self: a #XbStack
Packit Service a3c5fa
 * @opcode: a #XbOpcode, which is consumed
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Pushes a new opcode onto the end of the stack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Returns: %TRUE if the opcode was stored on the stack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Since: 0.1.3
Packit Service a3c5fa
 **/
Packit Service a3c5fa
gboolean
Packit Service a3c5fa
xb_stack_push_steal (XbStack *self, XbOpcode *opcode)
Packit Service a3c5fa
{
Packit Service a3c5fa
	if (self->pos >= self->max_size)
Packit Service a3c5fa
		return FALSE;
Packit Service a3c5fa
	self->opcodes[self->pos++] = opcode;
Packit Service a3c5fa
	return TRUE;
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/**
Packit Service a3c5fa
 * xb_stack_get_size:
Packit Service a3c5fa
 * @self: a #XbStack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Gets the current size of the stack.
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Returns: integer, where 0 is "empty"
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Since: 0.1.3
Packit Service a3c5fa
 **/
Packit Service a3c5fa
guint
Packit Service a3c5fa
xb_stack_get_size (XbStack *self)
Packit Service a3c5fa
{
Packit Service a3c5fa
	return self->pos;
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/**
Packit Service a3c5fa
 * xb_stack_get_max_size:
Packit Service a3c5fa
 * @self: a #XbStack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Gets the maximum size of the stack.
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Returns: integer
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Since: 0.1.3
Packit Service a3c5fa
 **/
Packit Service a3c5fa
guint
Packit Service a3c5fa
xb_stack_get_max_size (XbStack *self)
Packit Service a3c5fa
{
Packit Service a3c5fa
	return self->max_size;
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/**
Packit Service a3c5fa
 * xb_stack_to_string:
Packit Service a3c5fa
 * @self: a #XbStack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Returns a string representing a stack.
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Returns: text
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Since: 0.1.4
Packit Service a3c5fa
 **/
Packit Service a3c5fa
gchar *
Packit Service a3c5fa
xb_stack_to_string (XbStack *self)
Packit Service a3c5fa
{
Packit Service a3c5fa
	GString *str = g_string_new (NULL);
Packit Service a3c5fa
	for (guint i = 0; i < self->pos; i++) {
Packit Service a3c5fa
		g_autofree gchar *tmp = xb_opcode_to_string (self->opcodes[i]);
Packit Service a3c5fa
		g_string_append_printf (str, "%s,", tmp);
Packit Service a3c5fa
	}
Packit Service a3c5fa
	if (str->len > 0)
Packit Service a3c5fa
		g_string_truncate (str, str->len - 1);
Packit Service a3c5fa
	return g_string_free (str, FALSE);
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
/**
Packit Service a3c5fa
 * xb_stack_new:
Packit Service a3c5fa
 * @max_size: maximum size of the stack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Creates a stack for the XbMachine request. Only #XbOpcode's can be pushed and
Packit Service a3c5fa
 * popped from the stack.
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Returns: (transfer full): a #XbStack
Packit Service a3c5fa
 *
Packit Service a3c5fa
 * Since: 0.1.3
Packit Service a3c5fa
 **/
Packit Service a3c5fa
XbStack *
Packit Service a3c5fa
xb_stack_new (guint max_size)
Packit Service a3c5fa
{
Packit Service a3c5fa
	XbStack *self = g_malloc0 (sizeof(XbStack) + max_size * sizeof(XbOpcode*));
Packit Service a3c5fa
	self->ref = 1;
Packit Service a3c5fa
	self->max_size = max_size;
Packit Service a3c5fa
	return self;
Packit Service a3c5fa
}
Packit Service a3c5fa
Packit Service a3c5fa
GType
Packit Service a3c5fa
xb_stack_get_type (void)
Packit Service a3c5fa
{
Packit Service a3c5fa
	static GType type = 0;
Packit Service a3c5fa
	if (G_UNLIKELY (!type)) {
Packit Service a3c5fa
		type = g_boxed_type_register_static ("XbStack",
Packit Service a3c5fa
						     (GBoxedCopyFunc) xb_stack_ref,
Packit Service a3c5fa
						     (GBoxedFreeFunc) xb_stack_unref);
Packit Service a3c5fa
	}
Packit Service a3c5fa
	return type;
Packit Service a3c5fa
}