diff options
author | hwspeedy <ns@bigbear.dk> | 2024-02-16 01:15:43 +0100 |
---|---|---|
committer | hwspeedy <ns@bigbear.dk> | 2024-02-16 01:15:43 +0100 |
commit | c362d03622401c6ea39bae828b7e24cb1f75a6bf (patch) | |
tree | 87d76f889011d2a1f090a2606fc01fd795863b54 /deps | |
parent | 0ce19608f1b7ba6e280d5969cbb1a4990af86365 (diff) |
FIX better implementation for low GLIB
Diffstat (limited to 'deps')
-rw-r--r-- | deps/sysobj_early/src/util_edid.c | 62 | ||||
-rw-r--r-- | deps/sysobj_early/src/util_sysobj.c | 125 |
2 files changed, 179 insertions, 8 deletions
diff --git a/deps/sysobj_early/src/util_edid.c b/deps/sysobj_early/src/util_edid.c index 06c5534e..906aeff0 100644 --- a/deps/sysobj_early/src/util_edid.c +++ b/deps/sysobj_early/src/util_edid.c @@ -31,17 +31,55 @@ #include "util_edid_svd_table.c" -// TODO: find a better fix, I've seen a few EDID strings with bogus chars -#if !GLIB_CHECK_VERSION(2,52,0) -__attribute__ ((weak)) -gchar *g_utf8_make_valid(const gchar *s, const gssize l) { - if (l < 0) - return g_strdup(s); - else - return g_strndup(s, (gsize)l); +#if GLIB_CHECK_VERSION(2,52,0) +#else +gchar * +g2_utf8_make_valid (const gchar *str, + gssize len) +{ + GString *string; + const gchar *remainder, *invalid; + gsize remaining_bytes, valid_bytes; + + g_return_val_if_fail (str != NULL, NULL); + + if (len < 0) + len = strlen (str); + + string = NULL; + remainder = str; + remaining_bytes = len; + + while (remaining_bytes != 0) + { + if (g_utf8_validate (remainder, remaining_bytes, &invalid)) + break; + valid_bytes = invalid - remainder; + + if (string == NULL) + string = g_string_sized_new (remaining_bytes); + + g_string_append_len (string, remainder, valid_bytes); + /* append U+FFFD REPLACEMENT CHARACTER */ + g_string_append (string, "\357\277\275"); + + remaining_bytes -= valid_bytes + 1; + remainder = invalid + 1; + } + + if (string == NULL) + return g_strndup (str, len); + + g_string_append_len (string, remainder, remaining_bytes); + g_string_append_c (string, '\0'); + + g_assert (g_utf8_validate (string->str, -1, NULL)); + + return g_string_free (string, FALSE); } #endif + #define NOMASK (~0U) #define BFMASK(LSB, MASK) (MASK << LSB) @@ -89,7 +127,11 @@ char *rstr(edid *e, uint32_t offset, uint32_t len) { char *raw = malloc(len+1), *ret = NULL; strncpy(raw, (char*)&e->u8[offset], len); raw[len] = 0; +#if GLIB_CHECK_VERSION(2,52,0) ret = g_utf8_make_valid(raw, len); +#else + ret = g2_utf8_make_valid(raw, len); +#endif g_free(raw); return ret; } @@ -100,7 +142,11 @@ char *rstr_strip(edid *e, uint32_t offset, uint32_t len) { char *raw = malloc(len+1), *ret = NULL; strncpy(raw, (char*)&e->u8[offset], len); raw[len] = 0; +#if GLIB_CHECK_VERSION(2,52,0) ret = g_strstrip(g_utf8_make_valid(raw, len)); +#else + ret = g_strstrip(g2_utf8_make_valid(raw, len)); +#endif g_free(raw); return ret; } diff --git a/deps/sysobj_early/src/util_sysobj.c b/deps/sysobj_early/src/util_sysobj.c index 94f71944..d0f09a68 100644 --- a/deps/sysobj_early/src/util_sysobj.c +++ b/deps/sysobj_early/src/util_sysobj.c @@ -177,12 +177,137 @@ gchar *util_strchomp_float(gchar* str_float) { return str_float; } + +#if GLIB_CHECK_VERSION(2, 58, 0) +#else +gchar * +g2_canonicalize_filename (const gchar *filename, + const gchar *relative_to) +{ + gchar *canon, *input, *output, *after_root, *output_start; + + g_return_val_if_fail (relative_to == NULL || g_path_is_absolute (relative_to), NULL); + + if (!g_path_is_absolute (filename)) + { + gchar *cwd_allocated = NULL; + const gchar *cwd; + + if (relative_to != NULL) + cwd = relative_to; + else + cwd = cwd_allocated = g_get_current_dir (); + + canon = g_build_filename (cwd, filename, NULL); + g_free (cwd_allocated); + } + else + { + canon = g_strdup (filename); + } + + after_root = (char *)g_path_skip_root (canon); + + if (after_root == NULL) + { + /* This shouldn't really happen, as g_get_current_dir() should + return an absolute pathname, but bug 573843 shows this is + not always happening */ + g_free (canon); + return g_build_filename (G_DIR_SEPARATOR_S, filename, NULL); + } + + /* Find the first dir separator and use the canonical dir separator. */ + for (output = after_root - 1; + (output >= canon) && G_IS_DIR_SEPARATOR (*output); + output--) + *output = G_DIR_SEPARATOR; + + /* 1 to re-increment after the final decrement above (so that output >= canon), + * and 1 to skip the first `/`. There might not be a first `/` if + * the @canon is a Windows `//server/share` style path with no + * trailing directories. @after_root will be '\0' in that case. */ + output++; + if (*output == G_DIR_SEPARATOR) + output++; + + /* POSIX allows double slashes at the start to mean something special + * (as does windows too). So, "//" != "/", but more than two slashes + * is treated as "/". + */ + if (after_root - output == 1) + output++; + + input = after_root; + output_start = output; + while (*input) + { + /* input points to the next non-separator to be processed. */ + /* output points to the next location to write to. */ + g_assert (input > canon && G_IS_DIR_SEPARATOR (input[-1])); + g_assert (output > canon && G_IS_DIR_SEPARATOR (output[-1])); + g_assert (input >= output); + + /* Ignore repeated dir separators. */ + while (G_IS_DIR_SEPARATOR (input[0])) + input++; + + /* Ignore single dot directory components. */ + if (input[0] == '.' && (input[1] == 0 || G_IS_DIR_SEPARATOR (input[1]))) + { + if (input[1] == 0) + break; + input += 2; + } + /* Remove double-dot directory components along with the preceding + * path component. */ + else if (input[0] == '.' && input[1] == '.' && + (input[2] == 0 || G_IS_DIR_SEPARATOR (input[2]))) + { + if (output > output_start) + { + do + { + output--; + } + while (!G_IS_DIR_SEPARATOR (output[-1]) && output > output_start); + } + if (input[2] == 0) + break; + input += 3; + } + /* Copy the input to the output until the next separator, + * while converting it to canonical separator */ + else + { + while (*input && !G_IS_DIR_SEPARATOR (*input)) + *output++ = *input++; + if (input[0] == 0) + break; + input++; + *output++ = G_DIR_SEPARATOR; + } + } + + /* Remove a potentially trailing dir separator */ + if (output > output_start && G_IS_DIR_SEPARATOR (output[-1])) + output--; + + *output = '\0'; + + return canon; +} +#endif + /* resolve . and .., but not symlinks */ gchar *util_normalize_path(const gchar *path, const gchar *relto) { gchar *resolved = NULL; #if GLIB_CHECK_VERSION(2, 58, 0) resolved = g_canonicalize_filename(path, relto); #else + resolved = g2_canonicalize_filename(path, relto); +#endif +#if NOT_DEFINED /* burt's hack version */ gchar *frt = relto ? g_strdup(relto) : NULL; util_null_trailing_slash(frt); |