/
githubmirror
/
libxmlb
Обзор
Документация
Войти
/
githubmirror
/
libxmlb
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
0.3.22
src/xb-stack.c
269 строк
5 KB
Richard Hughes
trivial: Sprinkle some G_UNLIKELY macros in the fast path
30 янв 2025, 18:30
30 янв 2025, 18:30
f3e0971
Код
Авторство
О чём код?
/* * Copyright 2018 Richard Hughes <richard@hughsie.com> * * SPDX-License-Identifier: LGPL-2.1-or-later */ #define G_LOG_DOMAIN "XbMachine" #include "config.h" #include <gio/gio.h> #include "xb-opcode-private.h" #include "xb-stack-private.h" /** * xb_stack_unref: * @self: a #XbStack * * Decrements the reference count of the stack, freeing the object when the * refcount drops to zero. * * Since: 0.1.3 **/ void xb_stack_unref(XbStack *self) { g_assert(self->ref > 0); if (G_UNLIKELY(--self->ref > 0)) return; for (guint i = 0; i < self->pos; i++) xb_opcode_clear(&self->opcodes[i]); if (!self->stack_allocated) g_free(self); } /** * xb_stack_ref: * @self: a #XbStack * * Increments the refcount of the stack. * * Returns: (transfer none): the original @self #XbStack instance * * Since: 0.1.3 **/ XbStack * xb_stack_ref(XbStack *self) { self->ref++; return self; } /** * xb_stack_pop: * @self: a #XbStack * @opcode_out: (out caller-allocates) (optional): return location for the popped #XbOpcode * @error: a #GError, or %NULL * * Pops an opcode off the stack. * * Returns: %TRUE if popping succeeded, %FALSE if the stack was empty already * * Since: 0.2.0 **/ gboolean xb_stack_pop(XbStack *self, XbOpcode *opcode_out, GError **error) { if (G_UNLIKELY(self->pos == 0)) { g_set_error(error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "stack is empty"); return FALSE; } self->pos--; if (opcode_out != NULL) *opcode_out = self->opcodes[self->pos]; return TRUE; } /** * xb_stack_pop_two: (skip): **/ gboolean xb_stack_pop_two(XbStack *self, XbOpcode *opcode1_out, XbOpcode *opcode2_out, GError **error) { if (G_UNLIKELY(self->pos < 2)) { g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "stack is not full enough"); return FALSE; } if (opcode1_out != NULL) *opcode1_out = self->opcodes[self->pos - 1]; if (opcode2_out != NULL) *opcode2_out = self->opcodes[self->pos - 2]; self->pos -= 2; return TRUE; } /** * xb_stack_peek: * @self: a #XbStack * @idx: index * * Peeks an opcode from the stack. * * Returns: (transfer none): a #XbOpcode * * Since: 0.1.3 **/ XbOpcode * xb_stack_peek(XbStack *self, guint idx) { if (G_UNLIKELY(idx >= self->pos)) return NULL; return &self->opcodes[idx]; } /* private */ gboolean xb_stack_push_bool(XbStack *self, gboolean val, GError **error) { XbOpcode *op; if (!xb_stack_push(self, &op, error)) return FALSE; xb_opcode_bool_init(op, val); return TRUE; } /* private */ XbOpcode * xb_stack_peek_head(XbStack *self) { if (self->pos == 0) return NULL; return &self->opcodes[0]; } /* private */ XbOpcode * xb_stack_peek_tail(XbStack *self) { if (self->pos == 0) return NULL; return &self->opcodes[self->pos - 1]; } /** * xb_stack_push: * @self: a #XbStack * @opcode_out: (out) (nullable): return location for the new #XbOpcode * @error: a #GError, or %NULL * * Pushes a new empty opcode onto the end of the stack. A pointer to the opcode * is returned in @opcode_out so that the caller can initialise it. This must be * done before the stack is next used as, for performance reasons, the newly * pushed opcode is not zero-initialised. * * Returns: %TRUE if a new empty opcode was returned, or %FALSE if the stack has * reached its maximum size * Since: 0.2.0 **/ gboolean xb_stack_push(XbStack *self, XbOpcode **opcode_out, GError **error) { if (G_UNLIKELY(self->pos >= self->max_size)) { *opcode_out = NULL; g_set_error(error, G_IO_ERROR, G_IO_ERROR_NO_SPACE, "stack is already at maximum size of %u", self->max_size); return FALSE; } *opcode_out = &self->opcodes[self->pos++]; return TRUE; } /** * xb_stack_get_size: * @self: a #XbStack * * Gets the current size of the stack. * * Returns: integer, where 0 is "empty" * * Since: 0.1.3 **/ guint xb_stack_get_size(XbStack *self) { return self->pos; } /** * xb_stack_get_max_size: * @self: a #XbStack * * Gets the maximum size of the stack. * * Returns: integer * * Since: 0.1.3 **/ guint xb_stack_get_max_size(XbStack *self) { return self->max_size; } /** * xb_stack_to_string: * @self: a #XbStack * * Returns a string representing a stack. * * Returns: text * * Since: 0.1.4 **/ gchar * xb_stack_to_string(XbStack *self) { GString *str = g_string_new(NULL); for (guint i = 0; i < self->pos; i++) { g_autofree gchar *tmp = xb_opcode_to_string(&self->opcodes[i]); g_string_append_printf(str, "%s,", tmp); } if (str->len > 0) g_string_truncate(str, str->len - 1); return g_string_free(str, FALSE); } /** * xb_stack_new: * @max_size: maximum size of the stack * * Creates a stack for the XbMachine request. Only #XbOpcode's can be pushed and * popped from the stack. * * Unlike with xb_stack_new_inline(), this stack will be allocated on the heap. * * Returns: (transfer full): a #XbStack * * Since: 0.1.3 **/ XbStack * xb_stack_new(guint max_size) { XbStack *self = g_malloc(sizeof(XbStack) + max_size * sizeof(XbOpcode)); self->ref = 1; self->stack_allocated = FALSE; self->pos = 0; self->max_size = max_size; return self; } GType xb_stack_get_type(void) { static GType type = 0; if (G_UNLIKELY(!type)) { type = g_boxed_type_register_static("XbStack", (GBoxedCopyFunc)xb_stack_ref, (GBoxedFreeFunc)xb_stack_unref); } return type; }