/* Tux Commander VFS: String utilities * Copyright (C) 2007 Tomas Bzatek * Check for updates on tuxcmd.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "strutils.h" char * include_trailing_path_sep (const char *APath) { if (APath == NULL) return NULL; if (g_strcmp0 (APath + strlen (APath) - 1, "/") != 0) return g_strdup_printf ("%s/", APath); else return g_strdup (APath); } char * exclude_trailing_path_sep (const char *APath) { if (APath == NULL) return NULL; if (strlen (APath) > 1 && g_strcmp0 (APath + strlen (APath) - 1, "/") == 0) return g_strndup (APath, strlen (APath) - 1); else return g_strdup(APath); } char * include_leading_path_sep (const char *APath) { if (APath == NULL) return NULL; if (! g_path_is_absolute (APath)) return g_strdup_printf ("/%s", APath); else return g_strdup (APath); } char * exclude_leading_path_sep (const char *APath) { if (APath == NULL) return NULL; if (g_path_is_absolute (APath)) return g_strdup (APath + 1); else return g_strdup (APath); } /* -------------------------------------------------------------------------------------- */ char * resolve_relative (const char *source, const char *point_to) { char *rel; char *canon; if (source == NULL) return NULL; if (point_to == NULL) return g_strdup (source); if (g_path_is_absolute (point_to)) return g_strdup (point_to); rel = g_build_filename (source, point_to, NULL); log ("resolve_relative: rel = '%s'\n", rel); canon = canonicalize_filename (rel); log ("resolve_relative: canon = '%s'\n", canon); g_free (rel); return canon; } void split_path (const char *path, char **first_part, char **last_part) { const char *pos; pos = strstr (path, "/"); if (pos) { *first_part = g_strndup (path, pos - path); *last_part = g_strdup (pos + 1); } else { *first_part = g_strdup (path); *last_part = NULL; } } /* -------------------------------------------------------------------------------------- */ /* canonicalize_filename() has been stolen from glib-2.16 */ /* Copyright (C) 2006-2007 Alexander Larsson */ char * canonicalize_filename (const char *filename) { char *canon, *start, *p, *q; int i; canon = g_strdup (filename); start = (char *)g_path_skip_root (canon); if (start == NULL) start = canon; /* POSIX allows double slashes at the start to * mean something special (as does windows too). * So, "//" != "/", but more than two slashes * is treated as "/". */ i = 0; for (p = start - 1; (p >= canon) && G_IS_DIR_SEPARATOR (*p); p--) i++; if (i > 2) { i -= 1; start -= i; memmove (start, start+i, strlen (start+i)+1); } p = start; while (*p != 0) { if (p[0] == '.' && (p[1] == 0 || G_IS_DIR_SEPARATOR (p[1]))) { memmove (p, p+1, strlen (p+1)+1); } else if (p[0] == '.' && p[1] == '.' && (p[2] == 0 || G_IS_DIR_SEPARATOR (p[2]))) { q = p + 2; /* Skip previous separator */ p = p - 2; if (p < start) p = start; while (p > start && !G_IS_DIR_SEPARATOR (*p)) p--; if (G_IS_DIR_SEPARATOR (*p)) *p++ = G_DIR_SEPARATOR; memmove (p, q, strlen (q)+1); } else { /* Skip until next separator */ while (*p != 0 && !G_IS_DIR_SEPARATOR (*p)) p++; if (*p != 0) { /* Canonicalize one separator */ *p++ = G_DIR_SEPARATOR; } } /* Remove additional separators */ q = p; while (*q && G_IS_DIR_SEPARATOR (*q)) q++; if (p != q) memmove (p, q, strlen (q)+1); } /* Remove trailing slashes */ if (p > start && G_IS_DIR_SEPARATOR (*(p-1))) *(p-1) = 0; return canon; } /* -------------------------------------------------------------------------------------- */ /* stolen from wine-0.9.19, utf8.c */ /* Copyright 2000 Alexandre Julliard */ char * wide_to_utf8 (const wchar_t *src) { #define CONV_BUFF_MAX 32768 int len; char *buf, *dst, *ret; buf = (char *) g_malloc0 (CONV_BUFF_MAX); dst = buf; if (src) for (len = CONV_BUFF_MAX; *src; src++) { wchar_t ch = *src; if (ch < 0x80) /* 0x00-0x7f: 1 byte */ { if (!len--) { log ("wide_to_utf8: error converting input string, overflow.\n"); break; /* overflow */ } *dst++ = ch; continue; } if (ch < 0x800) /* 0x80-0x7ff: 2 bytes */ { if ((len -= 2) < 0) { log ("wide_to_utf8: error converting input string, overflow.\n"); break; /* overflow */ } dst[1] = 0x80 | (ch & 0x3f); ch >>= 6; dst[0] = 0xc0 | ch; dst += 2; continue; } /* 0x800-0xffff: 3 bytes */ if ((len -= 3) < 0) { log ("wide_to_utf8: error converting input string, overflow.\n"); break; /* overflow */ } dst[2] = 0x80 | (ch & 0x3f); ch >>= 6; dst[1] = 0x80 | (ch & 0x3f); ch >>= 6; dst[0] = 0xe0 | ch; dst += 3; } ret = g_strdup (buf); g_free (buf); return ret; }