[cairo] [PATCH 5/5] util: Added a basename library which can be used on Windows builds.
Zoxc
zoxc32 at gmail.com
Thu Jun 24 11:31:55 PDT 2010
---
util/basename.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
util/basename.h | 7 ++
2 files changed, 172 insertions(+), 0 deletions(-)
create mode 100644 util/basename.c
create mode 100644 util/basename.h
diff --git a/util/basename.c b/util/basename.c
new file mode 100644
index 0000000..8d034cf
--- /dev/null
+++ b/util/basename.c
@@ -0,0 +1,165 @@
+/* basename.c
+ *
+ * $Id: basename.c,v 1.2 2007/03/08 23:15:58 keithmarshall Exp $
+ *
+ * Provides an implementation of the "basename" function, conforming
+ * to SUSv3, with extensions to accommodate Win32 drive designators,
+ * and suitable for use on native Microsoft(R) Win32 platforms.
+ *
+ * Written by Keith Marshall <keithmarshall at users.sourceforge.net>
+ *
+ * This is free software. You may redistribute and/or modify it as you
+ * see fit, without restriction of copyright.
+ *
+ * This software is provided "as is", in the hope that it may be useful,
+ * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of
+ * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no
+ * time will the author accept any form of liability for any damages,
+ * however caused, resulting from the use of this software.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+
+char *basename( char *path )
+{
+ size_t len;
+ static char *retfail = NULL;
+
+ /* to handle path names for files in multibyte character locales,
+ * we need to set up LC_CTYPE to match the host file system locale
+ */
+
+ char *locale = setlocale( LC_CTYPE, NULL );
+ if( locale != NULL ) locale = strdup( locale );
+ setlocale( LC_CTYPE, "" );
+
+ if( path && *path )
+ {
+ /* allocate sufficient local storage space,
+ * in which to create a wide character reference copy of path
+ */
+
+ wchar_t * refcopy, * refpath;
+ len = mbstowcs( NULL, path, 0 );
+ refcopy = malloc((1 + len) * sizeof(wchar_t));
+
+ /* create the wide character reference copy of path,
+ * and step over the drive designator, if present ...
+ */
+
+ refpath = refcopy;
+ if( ((len = mbstowcs( refpath, path, len )) > 1) && (refpath[1] == L':') )
+ {
+ /* FIXME: maybe should confirm *refpath is a valid drive designator */
+
+ refpath += 2;
+ }
+
+ /* ensure that our wide character reference path is NUL terminated */
+
+ refcopy[ len ] = L'\0';
+
+ /* check again, just to ensure we still have a non-empty path name ... */
+
+ if( *refpath )
+ {
+ /* and, when we do, process it in the wide character domain ...
+ * scanning from left to right, to the char after the final dir separator
+ */
+
+ wchar_t *refname;
+ for( refname = refpath ; *refpath ; ++refpath )
+ {
+ if( (*refpath == L'/') || (*refpath == L'\\') )
+ {
+ /* we found a dir separator ...
+ * step over it, and any others which immediately follow it
+ */
+
+ while( (*refpath == L'/') || (*refpath == L'\\') )
+ ++refpath;
+
+ /* if we didn't reach the end of the path string ... */
+
+ if( *refpath )
+
+ /* then we have a new candidate for the base name */
+
+ refname = refpath;
+
+ /* otherwise ...
+ * strip off any trailing dir separators which we found
+ */
+
+ else while( (refpath > refname)
+ && ((*--refpath == L'/') || (*refpath == L'\\')) )
+ *refpath = L'\0';
+ }
+ }
+
+ /* in the wide character domain ...
+ * refname now points at the resolved base name ...
+ */
+
+ if( *refname )
+ {
+ /* if it's not empty,
+ * then we transform the full normalised path back into
+ * the multibyte character domain, and skip over the dirname,
+ * to return the resolved basename.
+ */
+
+ if( (len = wcstombs( path, refcopy, len )) != (size_t)(-1) )
+ path[ len ] = '\0';
+ *refname = L'\0';
+ if( (len = wcstombs( NULL, refcopy, 0 )) != (size_t)(-1) )
+ path += len;
+ }
+
+ else
+ {
+ /* the basename is empty, so return the default value of "/",
+ * transforming from wide char to multibyte char domain, and
+ * returning it in our own buffer.
+ */
+
+ retfail = realloc( retfail, len = 1 + wcstombs( NULL, L"/", 0 ));
+ wcstombs( path = retfail, L"/", len );
+ }
+
+ /* restore the caller's locale, clean up, and return the result */
+
+ setlocale( LC_CTYPE, locale );
+ free( locale );
+ return( path );
+ }
+
+ free(refcopy);
+ /* or we had an empty residual path name, after the drive designator,
+ * in which case we simply fall through ...
+ */
+ }
+
+ /* and, if we get to here ...
+ * the path name is either NULL, or it decomposes to an empty string;
+ * in either case, we return the default value of "." in our own buffer,
+ * reloading it with the correct value, transformed from the wide char
+ * to the multibyte char domain, just in case the caller trashed it
+ * after a previous call.
+ */
+
+ retfail = realloc( retfail, len = 1 + wcstombs( NULL, L".", 0 ));
+ wcstombs( retfail, L".", len );
+
+ /* restore the caller's locale, clean up, and return the result */
+
+ setlocale( LC_CTYPE, locale );
+ free( locale );
+ return( retfail );
+}
+
+/* $RCSfile: basename.c,v $$Revision: 1.2 $: end of file */
diff --git a/util/basename.h b/util/basename.h
new file mode 100644
index 0000000..0392a29
--- /dev/null
+++ b/util/basename.h
@@ -0,0 +1,7 @@
+
+#ifndef BASENAME_H
+#define BASENAME_H
+
+char *basename (char *path);
+
+#endif /* BASENAME_H */
--
1.7.0.2.msysgit.0
More information about the cairo
mailing list