From 6b3866607129111ea1e1e9b9642fe2623e33fcc6 Mon Sep 17 00:00:00 2001 From: Brad Roberts Date: Mon, 10 Sep 2007 00:54:53 +0000 Subject: [PATCH] phobos 0.4 --- filename.d | 91 ----------- makefile | 9 +- path.d | 473 +++++++++++++++++++++++++++++++++++++++++++++++++++++ string.d | 82 ++++++++++ 4 files changed, 560 insertions(+), 95 deletions(-) delete mode 100644 filename.d create mode 100644 path.d diff --git a/filename.d b/filename.d deleted file mode 100644 index 9ede04124a0..00000000000 --- a/filename.d +++ /dev/null @@ -1,91 +0,0 @@ - -// Copyright (c) 2001 by Digital Mars -// All Rights Reserved -// www.digitalmars.com - -// File name parsing - -class FileName -{ - /************************** - * Get extension. - * For example, "d:\path\foo.bat" returns "bat". - */ - - static char[] getExt(char[] fullname) - { - uint i; - - i = fullname.length; - while (i > 0) - { - i--; - if (fullname[i] == '.') - break; - version(Win32) - { - if (fullname[i] == ':' || fullname[i] == '\') - return null; - } - version(linux) - { - if (fullname[i] == '/') - return null; - } - } - return fullname[i .. fullname.length]; - } - - /************************** - * Get name. - * For example, "d:\path\foo.bat" returns "foo.bat". - */ - - static char[] getName(char[] fullname) - out (result) - { - assert(result.length <= fullname.length); - } - body - { - uint i; - - for (i = fullname.length; i > 0; i--) - { - version(Win32) - { - if (fullname[i - 1] == ':' || fullname[i - 1] == '\') - return null; - } - version(linux) - { - if (fullname[i - 1] == '/') - return null; - } - } - return fullname[i .. fullname.length]; - } - - - /**************************** - * Put a default extension on fullname if it doesn't already - * have an extension. - */ - - static char[] defaultExt(char[] fullname, char[] ext) - { - char[] existing; - - existing = getExt(fullname); - if (existing.length == 0) - { - // Check for fullname ending in '.' - if (fullname.length && fullname[fullname.length - 1] == '.') - fullname ~= ext; - else - fullname = fullname ~ '.' ~ ext; - } - return fullname; - } - -} diff --git a/makefile b/makefile index ab25193410f..854f856ace2 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,6 @@ CFLAGS=-g -mn -6 -r -Igc +DFLAGS=-unittest CC=sc .c.obj: @@ -9,7 +10,7 @@ CC=sc $(CC) -c $(CFLAGS) $* .d.obj: - ..\mars $* + ..\mars $(DFLAGS) $* .asm.obj: $(CC) -c $* @@ -26,7 +27,7 @@ OBJS= assert.obj deh.obj modulo.obj new.obj switch.obj complex.obj \ critical.obj interface.obj object.obj monitor.obj arraycat.obj invariant.obj \ dmain2.obj outofmemory.obj achar.obj aaAh4.obj adi.obj file.obj \ compiler.obj system.obj arraysetlength.obj minit.obj moduleinit.obj \ - cast.obj syserror.obj filename.obj string.obj + cast.obj syserror.obj path.obj string.obj HDR=mars.h @@ -34,7 +35,7 @@ SRC= modulo.c new.cpp switch.d complex.c critical.c fpu.d \ aa.c vaa.c interface.c arraysetlength.cpp minit.asm SRC2=deh.c object.d gc.d math.d stdio.d stdlib.d time.d monitor.c arraycat.d \ - string.d windows.d filename.d + string.d windows.d path.d SRC3=winbase.d windef.d invariant.d assert.d RegExp.d dmain2.d dateparse.d \ outofmemory.d syserror.d @@ -48,7 +49,7 @@ phobos.lib : $(OBJS) gc\dmgc.lib makefile lib phobos /noi +interface+modulo+new+switch+monitor+string; lib phobos /noi +arraycat+invariant+dmain2+achar+outofmemory; lib phobos /noi +aaAh4+adi+file+compiler+system+syserror; - lib phobos /noi +minit+moduleinit+cast+filename+gc\dmgc.lib; + lib phobos /noi +minit+moduleinit+cast+path+gc\dmgc.lib; aaAh4.obj : aaAh4.d diff --git a/path.d b/path.d new file mode 100644 index 00000000000..0abb930a50e --- /dev/null +++ b/path.d @@ -0,0 +1,473 @@ + +// Copyright (c) 2001 by Digital Mars +// All Rights Reserved +// www.digitalmars.com + +// File name parsing + +//debug=path; // uncomment to turn on debugging printf's + +debug(path) +{ + import stdio; // for printf() +} + +import string; + +version(Win32) +{ + const char[1] sep = '\'; + const char[1] altsep = '/'; + const char[1] pathsep = ';'; + const char[2] linesep = "\r\n"; + const char[1] curdir = '.'; + const char[1] pardir = '..'; +} +version(linux) +{ + const char[1] sep = '/'; + const char[0] altsep; + const char[1] pathsep = ':'; + const char[1] linesep = "\n"; + const char[1] curdir = '.'; + const char[1] pardir = '..'; +} + +/************************** + * Get extension. + * For example, "d:\path\foo.bat" returns "bat". + */ + +char[] getExt(char[] fullname) +{ + uint i; + + i = fullname.length; + while (i > 0) + { + i--; + if (fullname[i] == '.') + break; + version(Win32) + { + if (fullname[i] == ':' || fullname[i] == '\') + return null; + } + version(linux) + { + if (fullname[i] == '/') + return null; + } + } + return fullname[i .. fullname.length]; +} + +/************************** + * Get base name. + * For example, "d:\path\foo.bat" returns "foo.bat". + */ + +char[] getBaseName(char[] fullname) + out (result) + { + assert(result.length <= fullname.length); + } + body + { + uint i; + + for (i = fullname.length; i > 0; i--) + { + version(Win32) + { + if (fullname[i - 1] == ':' || fullname[i - 1] == '\') + return null; + } + version(linux) + { + if (fullname[i - 1] == '/') + return null; + } + } + return fullname[i .. fullname.length]; + } + + +/************************** + * Get directory name. + * For example, "d:\path\foo.bat" returns "d:\path". + */ + +char[] getDirName(char[] fullname) + out (result) + { + assert(result.length <= fullname.length); + } + body + { + uint i; + + for (i = fullname.length; i > 0; i--) + { + version(Win32) + { + if (fullname[i - 1] == ':') + break; + if (fullname[i - 1] == '\') + { i--; + break; + } + } + version(linux) + { + if (fullname[i - 1] == '/') + { i--; + break; + } + } + } + return fullname[0 .. i]; + } + + +/******************************** + * Get drive. + * For example, "d:\path\foo.bat" returns "d:". + */ + +char[] getDrive(char[] fullname) + out (result) + { + assert(result.length <= fullname.length); + } + body + { + version(Win32) + { + int i; + + for (i = 0; i < fullname.length; i++) + { + if (fullname[i] == ':') + return fullname[0 .. i + 1]; + } + return null; + } + version(linux) + { + return null; + } + } + +/**************************** + * Put a default extension on fullname if it doesn't already + * have an extension. + */ + +char[] defaultExt(char[] fullname, char[] ext) +{ + char[] existing; + + existing = getExt(fullname); + if (existing.length == 0) + { + // Check for fullname ending in '.' + if (fullname.length && fullname[fullname.length - 1] == '.') + fullname ~= ext; + else + fullname = fullname ~ '.' ~ ext; + } + return fullname; +} + + +/************************************* + * Determine if absolute path name. + */ + +int isabs(char[] path) +{ + char[] d = getDrive(path); + + return d.length < path.length && path[d.length] == sep[0]; +} + +/************************************* + * Join two path components. + */ + +char[] join(char[] p1, char[] p2) +{ + if (!p2.length) + return p1; + if (!p1.length) + return p2; + + char[] p; + char[] d1; + + version(Win32) + { + if (getDrive(p2)) + { + p = p2; + } + else + { + d1 = getDrive(p1); + if (p1.length == d1.length) + { + p = p1 ~ p2; + } + else if (p2[0] == '\') + { + if (d1.length == 0) + p = p2; + else if (p1[p1.length - 1] == '\') + p = p1 ~ p2[1 .. p2.length]; + else + p = p1 ~ p2; + } + else if (p1[p1.length - 1] == '\') + { + p = p1 ~ p2; + } + else + { + p = p1 ~ sep ~ p2; + } + } + } + version(linux) + { + if (p2[0] == sep[0]) + { + p = p2; + } + else if (p1[p1.length - 1] == sep[0]) + { + p = p1 ~ p2; + } + else + { + p = p1 ~ sep ~ p2; + } + } + return p; +} + +unittest +{ + debug(path) printf("path.join.unittest\n"); + + char[] p; + int i; + + p = join("foo", "bar"); + i = cmp(p, 'foo\bar'); + assert(i == 0); + + p = join('foo\', 'bar'); + i = cmp(p, 'foo\bar'); + assert(i == 0); + + p = join('foo', '\bar'); + i = cmp(p, '\bar'); + assert(i == 0); + + p = join('foo\', '\bar'); + i = cmp(p, '\bar'); + assert(i == 0); + + version(Win32) + { + p = join('d:', 'bar'); + i = cmp(p, 'd:bar'); + assert(i == 0); + + p = join('d:\', 'bar'); + i = cmp(p, 'd:\bar'); + assert(i == 0); + + p = join('d:\', '\bar'); + i = cmp(p, 'd:\bar'); + assert(i == 0); + + p = join('d:\foo', 'bar'); + i = cmp(p, 'd:\foo\bar'); + assert(i == 0); + + p = join('d:', '\bar'); + i = cmp(p, 'd:\bar'); + assert(i == 0); + + p = join('foo', 'd:'); + i = cmp(p, 'd:'); + assert(i == 0); + + p = join('foo', 'd:\'); + i = cmp(p, 'd:\'); + assert(i == 0); + + p = join('foo', 'd:\bar'); + i = cmp(p, 'd:\bar'); + assert(i == 0); + } +} + + +/********************************* + * Match file name characters. + * Case sensitivity depends on the operating system. + */ + +int fncharmatch(char c1, char c2) +{ + if (c1 != c2) + { + if ('A' <= c1 && c1 <= 'Z') + c1 += cast(char)'a' - 'A'; + if ('A' <= c2 && c2 <= 'Z') + c2 += cast(char)'a' - 'A'; + return c1 == c2; + } + return true; +} + +/************************************ + * Match filename strings with pattern[], using the following wildcards: + * * match 0 or more characters + * ? match any character + * [chars] match any character that appears between the [] + * [!chars] match any character that does not appear between the [! ] + * + * Matching is case sensitive on a file system that is case sensitive. + * + * Returns: + * true match + * false no match + */ + +int fnmatch(char[] name, char[] pattern) + in + { + // Verify that pattern[] is valid + int i; + int inbracket = false; + + for (i = 0; i < pattern.length; i++) + { + switch (pattern[i]) + { + case '[': + assert(!inbracket); + inbracket = true; + break; + + case ']': + assert(inbracket); + inbracket = false; + break; + } + } + } + body + { + int pi; + int ni; + char pc; + char nc; + int j; + int not; + int anymatch; + + ni = 0; + for (pi = 0; pi < pattern.length; pi++) + { + pc = pattern[pi]; + switch (pc) + { + case '*': + if (pi + 1 == pattern.length) + goto match; + for (j = ni; j < name.length; j++) + { + if (fnmatch(name[j .. name.length], pattern[pi + 1 .. pattern.length])) + goto match; + } + goto nomatch; + + case '?': + if (ni == name.length) + goto nomatch; + ni++; + break; + + case '[': + if (ni == name.length) + goto nomatch; + nc = name[ni]; + ni++; + not = 0; + pi++; + if (pattern[pi] == '!') + { not = 1; + pi++; + } + anymatch = 0; + while (1) + { + pc = pattern[pi]; + if (pc == ']') + break; + if (!anymatch && fncharmatch(nc, pc)) + anymatch = 1; + pi++; + } + if (!(anymatch ^ not)) + goto nomatch; + break; + + default: + if (ni == name.length) + goto nomatch; + nc = name[ni]; + if (!fncharmatch(pc, nc)) + goto nomatch; + ni++; + break; + } + } + if (ni < name.length) + goto nomatch; + + match: + return true; + + nomatch: + return false; + } + +unittest +{ + debug(path) printf("path.fnmatch.unittest\n"); + + assert(fnmatch("foo", "Foo")); + assert(fnmatch("foo", "*")); + assert(fnmatch("foo.bar", "*")); + assert(fnmatch("foo.bar", "*.*")); + assert(fnmatch("foo.bar", "foo*")); + assert(fnmatch("foo.bar", "f*bar")); + assert(fnmatch("foo.bar", "f*b*r")); + assert(fnmatch("foo.bar", "f???bar")); + assert(fnmatch("foo.bar", "[fg]???bar")); + assert(fnmatch("foo.bar", "[!gh]*bar")); + + assert(!fnmatch("foo", "bar")); + assert(!fnmatch("foo", "*.*")); + assert(!fnmatch("foo.bar", "f*baz")); + assert(!fnmatch("foo.bar", "f*b*x")); + assert(!fnmatch("foo.bar", "[gh]???bar")); + assert(!fnmatch("foo.bar", "[!fg]*bar")); + assert(!fnmatch("foo.bar", "[fg]???baz")); +} diff --git a/string.d b/string.d index 0d356d102cb..e19904b8290 100644 --- a/string.d +++ b/string.d @@ -1042,4 +1042,86 @@ unittest } +/************************************ + * Construct translation table for translate(). + */ + +char[] maketrans(char[] from, char[] to) + in + { + assert(from.length == to.length); + } + body + { + char[] t = new char[256]; + int i; + + for (i = 0; i < 256; i++) + t[i] = cast(char)i; + + for (i = 0; i < from.length; i++) + t[from[i]] = to[i]; + + return t; + } + +/****************************************** + * Translate characters in s[] using table created by maketrans(). + * Delete chars in delchars[]. + */ + +char[] translate(char[] s, char[] transtab, char[] delchars) + in + { + assert(transtab.length == 256); + } + body + { + char[] r; + int i; + int count; + bit[256] deltab; + + deltab[] = 0; + for (i = 0; i < delchars.length; i++) + deltab[delchars[i]] = 1; + + count = 0; + for (i = 0; i < s.length; i++) + { + if (!deltab[s[i]]) + count++; + } + + r = new char[count]; + count = 0; + for (i = 0; i < s.length; i++) + { char c = s[i]; + + if (!deltab[c]) + { + r[count] = transtab[c]; + count++; + } + } + return r; + } + +unittest +{ + debug(string) printf("string.translate.unittest\n"); + + char[] from = "abcdef"; + char[] to = "ABCDEF"; + char[] s = "The quick dog fox"; + char[] t; + char[] r; + int i; + + t = maketrans(from, to); + r = translate(s, t, "kg"); + //printf("r = '%.*s'\n", r); + i = cmp(r, "ThE quiC Do Fox"); + assert(i == 0); +}