/* * Copyright 2021 Hans-Kristian Arntzen for Valve Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API #include "vkd3d_string.h" #include "vkd3d_memory.h" STATIC_ASSERT(sizeof(WCHAR) == sizeof(uint16_t)); char *vkd3d_strdup(const char *str) { /* strdup() is actually not standard. */ char *duped; size_t len; len = strlen(str) + 1; duped = vkd3d_malloc(len); if (duped) memcpy(duped, str, len); return duped; } char *vkd3d_strdup_n(const char *str, size_t n) { char *duped; size_t len; len = strnlen(str, n); duped = vkd3d_malloc(len + 1); if (duped) { memcpy(duped, str, len); duped[len] = '\0'; } return duped; } WCHAR *vkd3d_wstrdup(const WCHAR *str) { WCHAR *duped; size_t len; len = vkd3d_wcslen(str) + 1; duped = vkd3d_malloc(len * sizeof(WCHAR)); if (duped) memcpy(duped, str, len * sizeof(WCHAR)); return duped; } bool vkd3d_export_strequal(const WCHAR *a, const WCHAR *b) { if (!a || !b) return false; while (*a != '\0' && *b != '\0') { if (*a != *b) return false; a++; b++; } return *a == *b; } bool vkd3d_export_strequal_substr(const WCHAR *a, size_t expected_n, const WCHAR *b) { size_t n = 0; if (!a || !b) return false; while (*a != '\0' && *b != '\0' && n < expected_n) { if (*a != *b) return false; a++; b++; n++; } return n == expected_n && *b == '\0'; } WCHAR *vkd3d_dup_entry_point(const char *str) { return vkd3d_dup_entry_point_n(str, strlen(str)); } WCHAR *vkd3d_dup_entry_point_n(const char *str, size_t len) { WCHAR *duped; size_t i; duped = vkd3d_malloc((len + 1) * sizeof(WCHAR)); if (!duped) return NULL; for (i = 0; i < len; i++) duped[i] = (unsigned char)str[i]; duped[len] = 0; return duped; } static bool is_valid_identifier_character(char v) { return (v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z') || v == '_' || (v >= '0' && v <= '9'); } static const char *vkd3d_manged_entry_point_scan(const char *entry, const char **out_end_entry) { const char *end_entry; while (*entry != '\0' && !is_valid_identifier_character(*entry)) entry++; end_entry = entry; while (*end_entry != '\0' && is_valid_identifier_character(*end_entry)) end_entry++; if (entry == end_entry) return NULL; *out_end_entry = end_entry; return entry; } WCHAR *vkd3d_dup_demangled_entry_point(const char *entry) { const char *end_entry; if (!(entry = vkd3d_manged_entry_point_scan(entry, &end_entry))) return NULL; return vkd3d_dup_entry_point_n(entry, end_entry - entry); } char *vkd3d_dup_demangled_entry_point_ascii(const char *entry) { const char *end_entry; if (!(entry = vkd3d_manged_entry_point_scan(entry, &end_entry))) return NULL; return vkd3d_strdup_n(entry, end_entry - entry); }