/* Tux Commandern 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 #include "strutils.h" char* include_trailing_path_sep(const char *APath) { if (APath == NULL) return NULL; char *ANewPath; // log("xxx = %s\n", (APath + strlen(APath) - 1)); if (strcmp(APath + strlen(APath) - 1, "/") != 0) { ANewPath = (char*)malloc(strlen(APath) + 2); snprintf(ANewPath, strlen(APath) + 2, "%s/", APath); } else ANewPath = strdup(APath); return ANewPath; } char* exclude_trailing_path_sep(const char *APath) { if (APath == NULL) return NULL; char *ANewPath; // log("orig = %s, len = %d, xxx = %s\n", APath, (int)strlen(APath), (APath + strlen(APath) - 1)); if ((strcmp(APath + strlen(APath) - 1, "/") == 0) && (strlen(APath) > 1)) { ANewPath = (char*)malloc(strlen(APath)); snprintf(ANewPath, strlen(APath), "%s", APath); // The number of bytes copied includes the trailing \0 } else ANewPath = strdup(APath); return ANewPath; } char* include_leading_path_sep(const char *APath) { if (APath == NULL) return NULL; char *ANewPath; // log("xxx = %s, %lu, strlen(APath) = %d, index() = %ld\n", APath, (unsigned long int)APath, (int)strlen(APath), (unsigned long int)index(APath, 0x2f)); if (index(APath, 0x2f) != APath) { ANewPath = (char*)malloc(strlen(APath) + 2); snprintf(ANewPath, strlen(APath) + 2, "/%s", APath); // The number of bytes copied includes the trailing \0 } else ANewPath = strdup(APath); return ANewPath; } char* exclude_leading_path_sep(const char* APath) { if (APath == NULL) return NULL; char *s = strdup(APath); char *ss; if (IS_DIR_SEP(*s)) ss = strdup(s + 1); else ss = strdup(s); free(s); return ss; } char* extract_file_name(const char *APath) { if (APath == NULL) return NULL; // log("xxx = %s\n", (APath + strlen(APath) - 1)); char *file_part = rindex(APath, 0x2f); // returns NULL if not found or if the file is in the root ( / ) if (file_part == NULL) return NULL; return strdup(file_part + 1); } // Extracts file path starting with "/" and ending with "/" char* extract_file_path(const char *APath) { if (APath == NULL) return NULL; // log("xxx = %s\n", (APath + strlen(APath) - 1)); char *file_part = rindex(APath, 0x2f); // returns NULL if not found or if the file is in the root ( / ) if (file_part == NULL) return NULL; char *ANewPath = (char*)malloc(file_part - APath + 2); snprintf(ANewPath, file_part - APath + 2, "%s", APath); return ANewPath; } // canonicalize_filename() is 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; } char* resolve_relative(const char *source, const char *point_to) { if (source == NULL) return NULL; if (point_to == NULL) return strdup(source); if (g_path_is_absolute(point_to)) return strdup(point_to); char *rel = g_build_filename(source, point_to, NULL); log("resolve_relative: rel = '%s'\n", rel); char *canon = canonicalize_filename(rel); log("resolve_relative: canon = '%s'\n", canon); free(rel); return canon; } // Originally 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 *) malloc (CONV_BUFF_MAX); memset (&buf[0], 0, 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); free (buf); return ret; }