/
githubmirror
/
libxmlb
Обзор
Документация
Войти
/
githubmirror
/
libxmlb
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
0.3.15
src/xb-opcode.c
500 строк
11 KB
Chun-wei Fan
Do not inline shared code
26 сен 2023, 17:04
26 сен 2023, 17:04
0826b18
Код
Авторство
О чём код?
/* * Copyright (C) 2018 Richard Hughes <richard@hughsie.com> * * SPDX-License-Identifier: LGPL-2.1+ */ #define G_LOG_DOMAIN "XbMachine" #include "config.h" #include <gio/gio.h> #include "xb-opcode-private.h" /** * xb_opcode_kind_to_string: * @kind: a #XbOpcodeKind, e.g. %XB_OPCODE_KIND_FUNCTION * * Converts the opcode kind to a string. * * Returns: opcode kind, e.g. `FUNC` * * Since: 0.1.1 **/ const gchar * xb_opcode_kind_to_string(XbOpcodeKind kind) { /* special cases */ if (kind == XB_OPCODE_KIND_INTEGER) return "INTE"; if (kind == XB_OPCODE_KIND_BOUND_UNSET) return "BIND"; if (kind == XB_OPCODE_KIND_BOUND_TEXT) return "?TXT"; if (kind == XB_OPCODE_KIND_BOUND_INDEXED_TEXT) return "?ITX"; if (kind == XB_OPCODE_KIND_BOUND_INTEGER) return "?INT"; if (kind == XB_OPCODE_KIND_INDEXED_TEXT) return "TEXI"; if (kind == XB_OPCODE_KIND_BOOLEAN) return "BOOL"; /* bitwise fallbacks */ if (kind & XB_OPCODE_FLAG_FUNCTION) return "FUNC"; if (kind & XB_OPCODE_FLAG_TEXT) return "TEXT"; return NULL; } /** * xb_opcode_kind_from_string: * @str: a string, e.g. `FUNC` * * Converts a string to an opcode kind. * * Returns: a #XbOpcodeKind, e.g. %XB_OPCODE_KIND_TEXT * * Since: 0.1.1 **/ XbOpcodeKind xb_opcode_kind_from_string(const gchar *str) { if (g_strcmp0(str, "FUNC") == 0) return XB_OPCODE_KIND_FUNCTION; if (g_strcmp0(str, "TEXT") == 0) return XB_OPCODE_KIND_TEXT; if (g_strcmp0(str, "INTE") == 0) return XB_OPCODE_KIND_INTEGER; if (g_strcmp0(str, "BIND") == 0) return XB_OPCODE_KIND_BOUND_INTEGER; if (g_strcmp0(str, "?TXT") == 0) return XB_OPCODE_KIND_BOUND_TEXT; if (g_strcmp0(str, "?ITX") == 0) return XB_OPCODE_KIND_BOUND_INDEXED_TEXT; if (g_strcmp0(str, "?INT") == 0) return XB_OPCODE_KIND_BOUND_INTEGER; if (g_strcmp0(str, "TEXI") == 0) return XB_OPCODE_KIND_INDEXED_TEXT; if (g_strcmp0(str, "BOOL") == 0) return XB_OPCODE_KIND_BOOLEAN; return XB_OPCODE_KIND_UNKNOWN; } /* private */ gchar * xb_opcode_get_sig(XbOpcode *self) { GString *str = g_string_new(xb_opcode_kind_to_string(self->kind)); if (self->kind == XB_OPCODE_KIND_FUNCTION) { g_string_append_printf(str, ":%s", self->ptr != NULL ? (gchar *)self->ptr : "???"); } return g_string_free(str, FALSE); } static const gchar * xb_opcode_get_str_for_display(XbOpcode *self) { if (self->ptr == NULL) return "(null)"; return self->ptr; } void xb_opcode_set_level(XbOpcode *self, guint8 level) { self->level = level; } static gchar * xb_opcode_to_string_internal(XbOpcode *self) { g_autoptr(GString) str = g_string_new(NULL); /* special cases then bitwise fallbacks */ if (self->kind == XB_OPCODE_KIND_INDEXED_TEXT) g_string_append_printf(str, "$'%s'", xb_opcode_get_str_for_display(self)); else if (self->kind == XB_OPCODE_KIND_INTEGER) g_string_append_printf(str, "%u", xb_opcode_get_val(self)); else if (self->kind == XB_OPCODE_KIND_BOUND_TEXT || self->kind == XB_OPCODE_KIND_BOUND_INDEXED_TEXT) g_string_append_printf(str, "?'%s'", xb_opcode_get_str_for_display(self)); else if (self->kind == XB_OPCODE_KIND_BOUND_INTEGER) g_string_append_printf(str, "?%u", xb_opcode_get_val(self)); else if (self->kind == XB_OPCODE_KIND_BOOLEAN) return g_strdup(xb_opcode_get_val(self) ? "True" : "False"); else if (self->kind & XB_OPCODE_FLAG_FUNCTION) g_string_append_printf(str, "%s()", xb_opcode_get_str_for_display(self)); else if (self->kind & XB_OPCODE_FLAG_TEXT) g_string_append_printf(str, "'%s'", xb_opcode_get_str_for_display(self)); else g_string_append_printf(str, "kind:0x%x", self->kind); /* add level */ if (self->level > 0) g_string_append_printf(str, "^%u", self->level); return g_string_free(g_steal_pointer(&str), FALSE); } /** * xb_opcode_to_string: * @self: a #XbOpcode * * Returns a string representing the specific opcode. * * Returns: text * * Since: 0.1.4 **/ gchar * xb_opcode_to_string(XbOpcode *self) { g_autofree gchar *tmp = xb_opcode_to_string_internal(self); if (self->kind & XB_OPCODE_FLAG_TOKENIZED) { g_autofree gchar *tokens = NULL; /* Ensure the array is NULL-terminated */ self->tokens[self->tokens_len] = NULL; tokens = g_strjoinv(",", (gchar **)self->tokens); return g_strdup_printf("%s[%s]", tmp, tokens); } return g_steal_pointer(&tmp); } /** * xb_opcode_get_kind: * @self: a #XbOpcode * * Gets the opcode kind. * * Returns: a #XbOpcodeKind, e.g. %XB_OPCODE_KIND_INTEGER * * Since: 0.1.1 **/ XbOpcodeKind xb_opcode_get_kind(XbOpcode *self) { return self->kind & ~XB_OPCODE_FLAG_TOKENIZED; } /** * xb_opcode_has_flag: * @self: a #XbOpcode * @flag: a #XbOpcodeFlags, e.g. #XB_OPCODE_FLAG_TOKENIZED * * Finds out if an opcode has a flag set. * * Returns: %TRUE if the flag is set * * Since: 0.3.1 **/ gboolean xb_opcode_has_flag(XbOpcode *self, XbOpcodeFlags flag) { return (self->kind & flag) > 0; } /** * xb_opcode_add_flag: * @self: a #XbOpcode * @flag: a #XbOpcodeFlags, e.g. #XB_OPCODE_FLAG_TOKENIZED * * Adds a flag to the opcode. * * Since: 0.3.1 **/ void xb_opcode_add_flag(XbOpcode *self, XbOpcodeFlags flag) { self->kind |= flag; } /** * xb_opcode_cmp_val: * @self: a #XbOpcode * * Checks if the opcode can be compared using the integer value. * * Returns: #%TRUE if this opcode can be compared as an integer * * Since: 0.1.1 **/ gboolean xb_opcode_cmp_val(XbOpcode *self) { return _xb_opcode_cmp_int(self) || _xb_opcode_cmp_itx(self); } /** * xb_opcode_cmp_str: * @self: a #XbOpcode * * Checks if the opcode can be compared using the string value. * * Returns: #%TRUE if this opcode can be compared as an string * * Since: 0.1.1 **/ gboolean xb_opcode_cmp_str(XbOpcode *self) { return xb_opcode_has_flag(self, XB_OPCODE_FLAG_TEXT); } /* private */ gboolean xb_opcode_is_binding(XbOpcode *self) { return xb_opcode_has_flag(self, XB_OPCODE_FLAG_BOUND); } /** * xb_opcode_get_val: * @self: a #XbOpcode * * Gets the integer value stored in the opcode. This may be a function ID, * a index into the string table or a literal integer. * * Returns: value, or 0 for unset. * * Since: 0.1.1 **/ guint32 xb_opcode_get_val(XbOpcode *self) { return self->val; } /** * xb_opcode_get_str: * @self: a #XbOpcode * * Gets the string value stored on the opcode. * * Returns: a string, or %NULL if unset * * Since: 0.1.1 **/ const gchar * xb_opcode_get_str(XbOpcode *self) { return _xb_opcode_get_str(self); } /** * xb_opcode_get_tokens: * @self: a #XbOpcode * * Gets the tokenized string stored on the opcode. * * Returns: a #GStrv, which is always %NULL terminated * * Since: 0.3.1 **/ const gchar ** xb_opcode_get_tokens(XbOpcode *self) { return self->tokens; } /** * xb_opcode_clear: * @self: a #XbOpcode * * Clears any allocated data inside the opcode, but does not free the #XbOpcode * itself. This is suitable for calling on stack-allocated #XbOpcodes. * * Since: 0.2.0 */ void xb_opcode_clear(XbOpcode *self) { if (self->destroy_func) self->destroy_func(self->ptr); self->destroy_func = NULL; } /** * xb_opcode_text_init: * @self: a stack allocated #XbOpcode to initialise * @str: a string * * Initialises a stack allocated #XbOpcode to contain a text literal. * The @str argument is copied internally and is not tied to the lifecycle of * the #XbOpcode. * * Since: 0.2.0 **/ void xb_opcode_text_init(XbOpcode *self, const gchar *str) { xb_opcode_init(self, XB_OPCODE_KIND_TEXT, g_strdup(str), 0, g_free); } /** * xb_opcode_init: * @self: allocated opcode to fill * @kind: a #XbOpcodeKind, e.g. %XB_OPCODE_KIND_INTEGER * @str: a string * @val: a integer value * @destroy_func: (nullable): a #GDestroyNotify, e.g. g_free() * * Initialises a stack allocated #XbOpcode. * * Since: 0.2.0 **/ void xb_opcode_init(XbOpcode *self, XbOpcodeKind kind, const gchar *str, guint32 val, GDestroyNotify destroy_func) { self->level = G_MAXUINT8; self->kind = kind; self->ptr = (gpointer)str; self->val = val; self->tokens_len = 0; self->destroy_func = destroy_func; memset(self->tokens, 0, sizeof(self->tokens)); } /** * xb_opcode_text_init_static: * @self: a stack allocated #XbOpcode to initialise * @str: a string * * Initialises a stack allocated #XbOpcode to contain a text literal, where * @str is either static text or will outlive the #XbOpcode lifecycle. * * Since: 0.2.0 **/ void xb_opcode_text_init_static(XbOpcode *self, const gchar *str) { xb_opcode_init(self, XB_OPCODE_KIND_TEXT, str, 0, NULL); } /** * xb_opcode_text_init_steal: * @self: a stack allocated #XbOpcode to initialise * @str: a string * * Initialises a stack allocated #XbOpcode to contain a text literal, stealing * the @str. Once the opcode is finalized g_free() will be called on @str. * * Since: 0.2.0 **/ void xb_opcode_text_init_steal(XbOpcode *self, gchar *str) { xb_opcode_init(self, XB_OPCODE_KIND_TEXT, g_steal_pointer(&str), 0, g_free); } /** * xb_opcode_func_init: * @self: a stack allocated #XbOpcode to initialise * @func: a function index * * Initialises a stack allocated #XbOpcode to contain a specific function. * Custom functions can be registered using xb_machine_add_func() and retrieved * using xb_machine_opcode_func_new(). * * Since: 0.2.0 **/ void xb_opcode_func_init(XbOpcode *self, guint32 func) { xb_opcode_init(self, XB_OPCODE_KIND_FUNCTION, NULL, func, NULL); } /** * xb_opcode_bind_init: * @self: a stack allocated #XbOpcode to initialise * * Initialises a stack allocated #XbOpcode to contain a bind variable. A value * needs to be assigned to this opcode at runtime using * xb_value_bindings_bind_str() or xb_value_bindings_bind_val(). * * Since: 0.2.0 **/ void xb_opcode_bind_init(XbOpcode *self) { xb_opcode_init(self, XB_OPCODE_KIND_BOUND_INTEGER, NULL, 0, NULL); } /* private */ void xb_opcode_bind_str(XbOpcode *self, gchar *str, GDestroyNotify destroy_func) { if (self->destroy_func) { self->destroy_func(self->ptr); self->destroy_func = NULL; } self->kind = XB_OPCODE_KIND_BOUND_TEXT; self->ptr = (gpointer)str; self->destroy_func = (gpointer)destroy_func; } /* private */ void xb_opcode_bind_val(XbOpcode *self, guint32 val) { if (self->destroy_func) { self->destroy_func(self->ptr); self->destroy_func = NULL; } self->kind = XB_OPCODE_KIND_BOUND_INTEGER; self->val = val; } /* private */ void xb_opcode_set_val(XbOpcode *self, guint32 val) { self->val = val; } /* private */ gboolean xb_opcode_append_token(XbOpcode *self, const gchar *val) { g_return_val_if_fail(val != NULL, FALSE); g_return_val_if_fail(val[0] != '\0', FALSE); if (self->tokens_len >= XB_OPCODE_TOKEN_MAX) return FALSE; self->tokens[self->tokens_len++] = val; self->kind |= XB_OPCODE_FLAG_TOKENIZED; return TRUE; } /* private */ void xb_opcode_set_kind(XbOpcode *self, XbOpcodeKind kind) { self->kind = kind; } /** * xb_opcode_integer_init: * @self: a stack allocated #XbOpcode to initialise * @val: a integer value * * Initialises a stack allocated #XbOpcode to contain an integer literal. * * Since: 0.2.0 **/ void xb_opcode_integer_init(XbOpcode *self, guint32 val) { xb_opcode_init(self, XB_OPCODE_KIND_INTEGER, NULL, val, NULL); } /* private */ void xb_opcode_bool_init(XbOpcode *self, gboolean val) { xb_opcode_init(self, XB_OPCODE_KIND_BOOLEAN, NULL, !!val, NULL); }