<html><head><style type="text/css"><!-- DIV {margin:0px;} --></style></head><body><div style="font-family:times new roman, new york, times, serif;font-size:12pt"><P>Hi John,</P>
<P>&nbsp;</P>
<P><FONT size=2>Here is my code that I have, this is the first method I attemepted since this is one of the interesting logic. I thought I post my code for you to review as well. This passed most of the test as well</FONT></P>
<P><FONT size=2></FONT>&nbsp;</P><FONT size=2><FONT size=2><FONT size=2>
<P>[</FONT><FONT color=#2b91af size=2>RubyMethod</FONT><FONT size=2>(</FONT><FONT color=#a31515 size=2>"basename"</FONT><FONT size=2>, </FONT><FONT color=#2b91af size=2>RubyMethodAttributes</FONT><FONT size=2>.PublicSingleton)]</P>
<P></FONT><FONT color=#0000ff size=2>public</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>static</FONT><FONT size=2> </FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT size=2> Basename(</FONT><FONT color=#2b91af size=2>CodeContext</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> context, </FONT><FONT color=#0000ff size=2>object</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> self, [</FONT><FONT color=#2b91af size=2>NotNull</FONT><FONT size=2>]</FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> path)</P>
<P>{</P>
<P></FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT size=2>[] tokens = path.Split(</FONT><FONT color=#a31515 size=2>@"\/"</FONT><FONT size=2>.ToCharArray(), </FONT><FONT color=#2b91af size=2>Int32</FONT><FONT size=2>.MaxValue, </FONT><FONT color=#2b91af size=2>StringSplitOptions</FONT><FONT size=2>.RemoveEmptyEntries);</P>
<P></FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT size=2> returnString = (tokens.GetLength(0) &gt; 0) ? tokens[tokens.GetLength(0) - 1] : path; </P>
<P></FONT><FONT color=#0000ff size=2>if</FONT><FONT size=2> ((tokens.GetLength(0) &gt; 0) &amp;&amp; (returnString.GetChar(returnString.Length - 1).Equals(</FONT><FONT color=#a31515 size=2>':'</FONT><FONT size=2>)))</P>
<P>returnString = path;</P>
<P></FONT><FONT color=#0000ff size=2>return</FONT><FONT size=2> returnString;</P>
<P>}</P>
<P>[</FONT><FONT color=#2b91af size=2>RubyMethod</FONT><FONT size=2>(</FONT><FONT color=#a31515 size=2>"basename"</FONT><FONT size=2>, </FONT><FONT color=#2b91af size=2>RubyMethodAttributes</FONT><FONT size=2>.PublicSingleton)]</P>
<P></FONT><FONT color=#0000ff size=2>public</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>static</FONT><FONT size=2> </FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT size=2> Basename(</FONT><FONT color=#2b91af size=2>CodeContext</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> context, </FONT><FONT color=#0000ff size=2>object</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> self, </FONT><FONT color=#0000ff size=2>object</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> path)</P>
<P>{</P>
<P></FONT><FONT color=#0000ff size=2>return</FONT><FONT size=2> Basename(context, self, </FONT><FONT color=#2b91af size=2>Protocols</FONT><FONT size=2>.CastToString(context, path));</P>
<P>}</P>
<P>[</FONT><FONT color=#2b91af size=2>RubyMethod</FONT><FONT size=2>(</FONT><FONT color=#a31515 size=2>"basename"</FONT><FONT size=2>, </FONT><FONT color=#2b91af size=2>RubyMethodAttributes</FONT><FONT size=2>.PublicSingleton)]</P>
<P></FONT><FONT color=#0000ff size=2>public</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>static</FONT><FONT size=2> </FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT size=2> Basename(</FONT><FONT color=#2b91af size=2>CodeContext</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> context, </FONT><FONT color=#0000ff size=2>object</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> self, [</FONT><FONT color=#2b91af size=2>NotNull</FONT><FONT size=2>]</FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> path, [</FONT><FONT color=#2b91af size=2>NotNull</FONT><FONT size=2>]</FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> filter)</P>
<P>{</P>
<P></FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT size=2> filename = Basename(context, self, path);</P>
<P></P>
<P></FONT><FONT color=#008000 size=2>//Treat ? specially</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>if</FONT><FONT size=2> (filter.IndexOf(</FONT><FONT color=#a31515 size=2>'?'</FONT><FONT size=2>) &gt;= 0)</P>
<P></FONT><FONT color=#0000ff size=2>return</FONT><FONT size=2> filename;</P>
<P></FONT><FONT color=#008000 size=2>//Treat .* and exetions specially using regex</P></FONT><FONT size=2>
<P></FONT><FONT color=#0000ff size=2>if</FONT><FONT size=2> (filter.Equals(</FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT size=2>.Create(</FONT><FONT color=#a31515 size=2>".*"</FONT><FONT size=2>)))</P>
<P>{</P>
<P>filter.Clear();</P>
<P>filter.Append(</FONT><FONT color=#a31515 size=2>@"(?x)(\.[^.]*$|$)"</FONT><FONT size=2>);</P>
<P>}</P>
<P></FONT><FONT color=#0000ff size=2>else</P></FONT><FONT size=2>
<P>{</P>
<P>filter.Append(</FONT><FONT color=#a31515 size=2>"$"</FONT><FONT size=2>);</P>
<P>}</P>
<P></FONT><FONT color=#2b91af size=2>RubyRegex</FONT><FONT size=2> reg = </FONT><FONT color=#0000ff size=2>new</FONT><FONT size=2> </FONT><FONT color=#2b91af size=2>RubyRegex</FONT><FONT size=2>(filter, System.Text.RegularExpressions.</FONT><FONT color=#2b91af size=2>RegexOptions</FONT><FONT size=2>.Singleline);</P>
<P>System.Text.RegularExpressions.</FONT><FONT color=#2b91af size=2>Match</FONT><FONT size=2> mat = reg.Match(filename);</P>
<P></FONT><FONT color=#0000ff size=2>if</FONT><FONT size=2> (mat.Success)</P>
<P>filename.Replace(mat.Index, mat.Length, </FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT size=2>.Create(</FONT><FONT color=#a31515 size=2>""</FONT><FONT size=2>));</P>
<P></FONT><FONT color=#0000ff size=2>return</FONT><FONT size=2> filename;</P>
<P>}</P>
<P>[</FONT><FONT color=#2b91af size=2>RubyMethod</FONT><FONT size=2>(</FONT><FONT color=#a31515 size=2>"basename"</FONT><FONT size=2>, </FONT><FONT color=#2b91af size=2>RubyMethodAttributes</FONT><FONT size=2>.PublicSingleton)]</P>
<P></FONT><FONT color=#0000ff size=2>public</FONT><FONT size=2> </FONT><FONT color=#0000ff size=2>static</FONT><FONT size=2> </FONT><FONT color=#2b91af size=2>MutableString</FONT><FONT size=2> Basename(</FONT><FONT color=#2b91af size=2>CodeContext</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> context, </FONT><FONT color=#0000ff size=2>object</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> self, </FONT><FONT color=#0000ff size=2>object</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> path, </FONT><FONT color=#0000ff size=2>object</FONT><FONT color=#008000 size=2>/*!*/</FONT><FONT size=2> filter)</P>
<P>{</P>
<P></FONT><FONT color=#0000ff size=2>return</FONT><FONT size=2> Basename(context, self, </FONT><FONT color=#2b91af size=2>Protocols</FONT><FONT size=2>.CastToString(context, path), </FONT><FONT color=#2b91af size=2>Protocols</FONT><FONT size=2>.CastToString(context, filter));</P>
<P>}</P>
<P>&nbsp;</P>
<P>Let me know what do you think? Yes, I found some problems with test spec as well, (bar.txt should be baz)</P>
<P>&nbsp;</P>
<P>Thanks.</P></FONT></FONT><FONT size=2>
<P>&nbsp;</P></FONT></FONT>
<DIV style="FONT-SIZE: 12pt; FONT-FAMILY: times new roman, new york, times, serif"><BR><BR>
<DIV style="FONT-SIZE: 12pt; FONT-FAMILY: times new roman, new york, times, serif">----- Original Message ----<BR>From: John Lam (IRONRUBY) &lt;jflam@microsoft.com&gt;<BR>To: "ironruby-core@rubyforge.org" &lt;ironruby-core@rubyforge.org&gt;<BR>Sent: Saturday, May 10, 2008 3:25:16 PM<BR>Subject: Re: [Ironruby-core] RubyForge bug fixes<BR><BR>Unnikrishnan Nair:<BR><BR>&gt; Quick question, are these following assertions are correct?<BR>&gt;<BR>&gt;&nbsp; &nbsp; should_raise(TypeError){ File.basename(1) }<BR>&gt;&nbsp; &nbsp; should_raise(TypeError){ File.basename("bar.txt", 1) }<BR>&gt;&nbsp; &nbsp; should_raise(TypeError){ File.basename(true) }<BR><BR>Yes they are. You can easily verify this in MRI yourself.<BR><BR>In first and third cases, it hits the overload that accepts a nullable object as the first parameter. The TypeError is raised via Protocols.CastToString().<BR><BR>In the second case, it also hits an overload that accepts a nullable object as its
 second parameter, which raises TypeError via Protocols.CastToString().<BR><BR>FYI, this is the implementation of #basename that I have in my shelveset. It passes all of the (valid) specs - there are some legitimate bugs in our old copy of the specs (I haven't checked with the latest version of the rubinius specs - I'll do that next week). I'm a bit worried about how I'm handling the special cases for Windows.<BR><BR>[RubyMethod("basename", RubyMethodAttributes.PublicSingleton)]<BR>public static MutableString/*!*/ Basename(CodeContext/*!*/ context, object/*!*/ self, [NotNull]MutableString/*!*/ path, [NotNull]MutableString/*!*/ extensionFilter) {<BR>&nbsp; &nbsp; if (path.Length == 0)<BR>&nbsp; &nbsp; &nbsp; &nbsp; return path;<BR><BR>&nbsp; &nbsp; MutableString trimmedPath = TrimTrailingSlashes(path);<BR><BR>&nbsp; &nbsp; // Special cases of drive letters C:\\ or C:/<BR>&nbsp; &nbsp; if (trimmedPath.Length == 2)<BR>&nbsp; &nbsp; &nbsp; &nbsp; if
 (Char.IsLetter(trimmedPath.GetChar(0)) &amp;&amp; trimmedPath.GetChar(1) == ':')<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Kernel.FlowTaint(context, path, (path.Length &gt; 2 ? MutableString.Create(path.GetChar(2).ToString()) : MutableString.Create(String.Empty)));<BR><BR>&nbsp; &nbsp; string trimmedPathAsString = trimmedPath.ConvertToString();<BR>&nbsp; &nbsp; if (trimmedPathAsString == "/")<BR>&nbsp; &nbsp; &nbsp; &nbsp; return trimmedPath;<BR><BR>&nbsp; &nbsp; string filename = <A href="http://system.io.path.ge/" target=_blank>System.IO</A>.Path.GetFileName(trimmedPath.ConvertToString());<BR><BR>&nbsp; &nbsp; // Handle UNC host names correctly<BR>&nbsp; &nbsp; string root = <A href="http://system.io.path.ge/" target=_blank>System.IO</A>.Path.GetPathRoot(trimmedPath.ConvertToString());<BR>&nbsp; &nbsp; if (extensionFilter.Length == 0)<BR>&nbsp; &nbsp; &nbsp; &nbsp; return trimmedPathAsString == root ? MutableString.Create(root) :
 MutableString.Create(filename);<BR><BR>&nbsp; &nbsp; string fileExtension = <A href="http://system.io.path.ge/" target=_blank>System.IO</A>.Path.GetExtension(filename);<BR>&nbsp; &nbsp; string basename = <A href="http://system.io.path.ge/" target=_blank>System.IO</A>.Path.GetFileNameWithoutExtension(filename);<BR><BR>&nbsp; &nbsp; string result = WildcardExtensionMatch(fileExtension, extensionFilter.ConvertToString()) ? basename : filename;<BR>&nbsp; &nbsp; return Kernel.FlowTaint(context, self, (result.Equals(root) ? MutableString.Create(root) : MutableString.Create(result)));<BR>}<BR><BR>[RubyMethod("basename", RubyMethodAttributes.PublicSingleton)]<BR>public static MutableString/*!*/ Basename(CodeContext/*!*/ context, object/*!*/ self, [NotNull]MutableString/*!*/ path) {<BR>&nbsp; &nbsp; return Basename(context, self, path, MutableString.Empty);<BR>}<BR><BR>[RubyMethod("basename", RubyMethodAttributes.PublicSingleton)]<BR>public static
 MutableString/*!*/ Basename(CodeContext/*!*/ context, object/*!*/ self, object path, object extension) {<BR>&nbsp; &nbsp; return Basename(context, self, Protocols.CastToString(context, path), Protocols.CastToString(context, extension));<BR>}<BR><BR>[RubyMethod("basename", RubyMethodAttributes.PublicSingleton)]<BR>public static MutableString/*!*/ Basename(CodeContext/*!*/ context, object/*!*/ self, object path) {<BR>&nbsp; &nbsp; return Basename(context, self, Protocols.CastToString(context, path));<BR>}<BR><BR>&gt; Also, in the basename_spec the test setup has wrong parameter on<BR>&gt; File.open(@name, 'w+'), if I change it to 'w', the test runs fine<BR>&gt; otherwise none of the test works.<BR><BR>This is correct. There is a bug in how we map the semantics of 'w+' to .NET IO. It's fixed in my shelveset.<BR><BR>Thanks,<BR>-John<BR><BR><BR><BR>_______________________________________________<BR>Ironruby-core mailing list<BR><A
 href="mailto:Ironruby-core@rubyforge.org" ymailto="mailto:Ironruby-core@rubyforge.org">Ironruby-core@rubyforge.org</A><BR><A href="http://rubyforge.org/mailman/listinfo/ironruby-core" target=_blank>http://rubyforge.org/mailman/listinfo/ironruby-core</A><BR></DIV></DIV></div></body></html>