/
githubmirror
/
libxmlb
Обзор
Документация
Войти
/
githubmirror
/
libxmlb
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
0.3.19
src/xb-string.c
310 строк
7 KB
Richard Hughes
trivial: Reformat with clang-format
29 дек 2021, 12:43
29 дек 2021, 12:43
8836e41
Код
Авторство
О чём код?
/* * Copyright (C) 2018 Richard Hughes <richard@hughsie.com> * * SPDX-License-Identifier: LGPL-2.1+ */ #define G_LOG_DOMAIN "XbSilo" #include "config.h" #include <gio/gio.h> #include <string.h> #include "xb-string-private.h" /** * xb_string_replace: (skip) * @str: The #GString to operate on * @search: The text to search for * @replace: The text to use for substitutions * * Performs multiple search and replace operations on the given string. * * Returns: the number of replacements done, or 0 if @search is not found. **/ guint xb_string_replace(GString *str, const gchar *search, const gchar *replace) { gchar *tmp; guint count = 0; gsize search_idx = 0; gsize replace_len; gsize search_len; g_return_val_if_fail(str != NULL, 0); g_return_val_if_fail(search != NULL, 0); g_return_val_if_fail(replace != NULL, 0); /* nothing to do */ if (str->len == 0) return 0; search_len = strlen(search); replace_len = strlen(replace); do { tmp = g_strstr_len(str->str + search_idx, -1, search); if (tmp == NULL) break; /* advance the counter in case @replace contains @search */ search_idx = (gsize)(tmp - str->str); /* reallocate the string if required */ if (search_len > replace_len) { g_string_erase(str, (gssize)search_idx, (gssize)(search_len - replace_len)); memcpy(tmp, replace, replace_len); } else if (search_len < replace_len) { g_string_insert_len(str, (gssize)search_idx, replace, (gssize)(replace_len - search_len)); /* we have to treat this specially as it could have * been reallocated when the insertion happened */ memcpy(str->str + search_idx, replace, replace_len); } else { /* just memcmp in the new string */ memcpy(tmp, replace, replace_len); } search_idx += replace_len; count++; } while (TRUE); return count; } /** * xb_string_append_union: * @xpath: The #GString to operate on * @fmt: The format string * @...: varargs for @fmt * * Appends an XPath query into the string, automatically adding the union * operator (`|`) if required. * * Since: 0.1.2 **/ void xb_string_append_union(GString *xpath, const gchar *fmt, ...) { va_list args; g_return_if_fail(xpath != NULL); g_return_if_fail(fmt != NULL); if (xpath->len > 0) g_string_append(xpath, "|"); va_start(args, fmt); #pragma clang diagnostic ignored "-Wformat-nonliteral" g_string_append_vprintf(xpath, fmt, args); #pragma clang diagnostic pop va_end(args); } /** * xb_string_contains: (skip) * @text: The source string * @search: The text to search for * * Searches for a substring match. * * Returns: %TRUE if the string @search is contained in @text. **/ gboolean xb_string_contains(const gchar *text, const gchar *search) { guint search_sz; guint text_sz; /* can't possibly match */ if (text == NULL || search == NULL) return FALSE; /* sanity check */ text_sz = strlen(text); search_sz = strlen(search); if (search_sz > text_sz) return FALSE; for (guint i = 0; i < text_sz - search_sz + 1; i++) { if (strncmp(text + i, search, search_sz) == 0) return TRUE; } return FALSE; } /** * xb_string_search: (skip) * @text: The source string * @search: The text to search for * * Searches for a fuzzy search match, ignoring search matches that are not at * the start of the token. * * For example, `foo` and `baz` would match `foobar baz` but `bar` would not * match the same string. * * Returns: %TRUE if the string @search is contained in @text. * * Since: 0.3.0 **/ gboolean xb_string_search(const gchar *text, const gchar *search) { guint search_sz; guint text_sz; gboolean is_sow = TRUE; /* can't possibly match */ if (text == NULL || text[0] == '\0') return FALSE; if (search == NULL || search[0] == '\0') return FALSE; /* sanity check */ text_sz = strlen(text); search_sz = strlen(search); if (search_sz > text_sz) return FALSE; for (guint i = 0; i < text_sz - search_sz + 1; i++) { if (!g_ascii_isalnum(text[i])) { is_sow = TRUE; continue; } if (!is_sow) continue; if (g_ascii_strncasecmp(text + i, search, search_sz) == 0) return TRUE; /* no longer the start of the word */ is_sow = FALSE; } return FALSE; } /** * xb_string_searchv: (skip) * @text: NULL-terminated source strings * @search: NULL-terminated text tokens to search for * * Searches for a fuzzy search match, ignoring search matches that are not at * the start of the token. * * For example `{"foo", "baz"}` would match with `{"wizz", "foobar"}` but * `{"baz"}` would not match the same set of strings. * * Returns: %TRUE if the string @search is contained in @text. * * Since: 0.3.0 **/ gboolean xb_string_searchv(const gchar **text, const gchar **search) { if (text == NULL || text[0] == NULL || text[0][0] == '\0') return FALSE; if (search == NULL || search[0] == NULL || search[0][0] == '\0') return FALSE; for (guint j = 0; text[j] != NULL; j++) { for (guint i = 0; search[i] != NULL; i++) { if (g_str_has_prefix(text[j], search[i])) return TRUE; } } return FALSE; } /** * xb_string_token_valid: (skip) * @text: The potential token * @see_also: xb_builder_node_tokenize_text(), xb_builder_node_get_tokens() * * This is typically used to eliminate tokens which are not useful for search * matching. * * For instance, tokens like `in` and `at` are less than three characters in * size and should be rejected. * * Returns: %TRUE if the token should be used for searching. **/ gboolean xb_string_token_valid(const gchar *text) { if (text == NULL) return FALSE; if (text[0] == '\0' || text[1] == '\0' || text[2] == '\0') return FALSE; return TRUE; } /** * xb_string_escape: * @str: string, e.g. `app/org.gnome.ghex/x86_64/stable` * * Escapes XPath control sequences such as newlines, tabs, and forward slashes. * * Returns: (transfer full): new string that is safe to use for queries * * Since: 0.1.2 **/ gchar * xb_string_escape(const gchar *str) { GString *tmp = g_string_new(str); xb_string_replace(tmp, "/", "\\/"); xb_string_replace(tmp, "\t", "\\t"); xb_string_replace(tmp, "\n", "\\n"); return g_string_free(tmp, FALSE); } gchar * xb_string_xml_escape(const gchar *str) { GString *tmp = g_string_new(str); xb_string_replace(tmp, "&", "&"); xb_string_replace(tmp, "<", "<"); xb_string_replace(tmp, ">", ">"); xb_string_replace(tmp, "\"", """); return g_string_free(tmp, FALSE); } /* private */ gboolean xb_string_isspace(const gchar *str, gssize strsz) { gsize strsz_safe; if (str == NULL) return TRUE; strsz_safe = strsz >= 0 ? (gsize)strsz : strlen(str); for (gsize i = 0; i < strsz_safe; i++) { if (!g_ascii_isspace(str[i])) return FALSE; } return TRUE; } void xb_guid_compute_for_data(XbGuid *out, const guint8 *buf, gsize bufsz) { guint8 buf_tmp[20] = {0x0}; gsize buf_tmpsz = sizeof(buf_tmp); g_autoptr(GChecksum) checksum = g_checksum_new(G_CHECKSUM_SHA1); if (buf != NULL && bufsz != 0) g_checksum_update(checksum, (const guchar *)buf, bufsz); g_checksum_get_digest(checksum, buf_tmp, &buf_tmpsz); memcpy(out, buf_tmp, sizeof(XbGuid)); } gchar * xb_guid_to_string(XbGuid *guid) { return g_strdup_printf("%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", (guint)GUINT32_TO_BE(guid->tlo), (guint)GUINT16_TO_BE(guid->tmi), (guint)GUINT16_TO_BE(guid->thi), (guint)GUINT16_TO_BE(guid->clo), guid->nde[0], guid->nde[1], guid->nde[2], guid->nde[3], guid->nde[4], guid->nde[5]); }