|
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 |
}
|