ShowUsYour<Blog>

Irregular expressions regularly

September 2003 - Posts

Rss + Northwind disconnected = Developer Friendlies

I've noticed a couple of developer-friendlies floating around recently, namely:

The Northwind disconnected article talks about some of the real issues faced when building these kinds of apps and gives special insight into some problems that you might encounter unexpectedly.  For example, if you do an Asynch call to a webservice and need to marshall the result back to the main thread in a Windows app, you could be asking for unexpected behaviour.  This article probably opened my eyes some of the issues that are faced in multi-threaded programming more than anything else that I've ever read!  For that reason alone I consider this to be essential reading.

Both of these resources will undoubtedly prove their worth to me in the not too distant future :)

Posted: Sep 30 2003, 09:23 AM by digory | with no comments
Filed under:
Windows Authentication with Role based authorization

I've done a fair bit with ASP.NET security using the FormsAuthentication provider but not much at all with Windows authentication.  I'm currently building an app. “out-of-hours” that needed to use integrated Windows authentication and also use Role based authorization based on the users Windows Group membership.  Here is a little piece of code that I put together to hook the Windows groups into the roles of the IPrincipal in the application:

[snipped from Global.asax]


Sub WindowsAuthentication_Authenticate(ByVal sender As Object, ByVal e As WindowsAuthenticationEventArgs) Dim roleStrng() As String = GetUserRoles()
    e.User = New GenericPrincipal(e.Identity, roleStrng)
End Sub Private Function GetUserRoles() As String()
    Dim myDomain As AppDomain = Thread.GetDomain()
    myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
    Dim al As New ArrayList

    Dim myPrincipal As WindowsPrincipal = CType(Thread.CurrentPrincipal, WindowsPrincipal)
    Dim wbirFields As Array = [Enum].GetValues(GetType(WindowsBuiltInRole))
    Dim roleName As Object

    For Each roleName In wbirFields
        Try
            If myPrincipal.IsInRole(CType(roleName, WindowsBuiltInRole)) Then
                al.Add(roleName.ToString())
            End If
        Catch

        End Try
    Next roleName

    Return CType(al.ToArray(GetType(String)), String())
End Function
Loading Templates at runtime

I've just uploaded my latest article on ASPAlliance:

Dynamically loading item templates into your Templated controls can give you a lot of power when it comes to providing a customized interface. Read on...

Posted: Sep 27 2003, 06:07 PM by digory | with 1 comment(s)
Filed under:
Begging is begg(in)ing.

To Dave...

You don't insult me, I just can't stand the thought of the "me too" reaction-ripple that this is likely to have on my aggregator.

I do agree with Roy when he says that we shouldn't judge the circumstances of others, and I certainly don't - even for a second - claim to know who you are of what has led you to think that the conference needs you there.  I guess that I'd leave it up to you and your company (#242 on the Fortune 500 I believe) to decide that.

Anyways, while on the subject of begging I need to replace the old wooden bridge over my creek and the in-ground pool needs a new liner.  On top of that, the piano needs tuning and I think that I'm going to struggle to make the payments on my new laptop next month.  If you'd like to lend a hand, click the button below:

 Make payments with PayPal - it's fast, free and secure!

Posted: Sep 27 2003, 11:30 AM by digory | with 2 comment(s)
Filed under:
Application.DoStuff

I nice little post by Eric Gunnerson that talked how to add an odd-shaped splash screen to an application.  The most interesting thing that came out of this post for me was that he mentioned having to call Application.DoEvents to allow Windows to process the necessary messages to get the splash form to render properly.  Being a web-guy Application.DoEvents is something that I've never really come to terms with.  If you were to go under the hood of some of my winforms apps you would undoubtedly uncover a shot-gun approach to calling this method - i.e.:  sprayed at random.

Application.DoEvents in the library

 

Posted: Sep 27 2003, 09:45 AM by digory | with no comments
Filed under:
Javascript Links

Today Marcie enquired about  favourite javascript links, here's my list:

References

DevEdge - Javascript reference
http://devedge.netscape.com/central/javascript/

DevEdge JavaScript 1.3 Client-Side Reference
http://devedge.netscape.com/library/manuals/2000/javascript/1.3/reference/index.html

MS DHTML Reference
http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/dhtml.asp

W3C DOM Level 1
http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/def-index.html


Interesting Links

http://www.xs4all.nl/~ppk/js/index.html
http://m.synovic.home.att.net/

Regex Reminders [1] - Replacement Operations

A common application for regular expressions is to find and replace strings within a body of text. These operations range from something as simple as finding some text and removing it to locating and re-writing Hmtl tags. Let's take a quick look at the signatures of the .NET Regular Expression Replace overloads.

[VB]
    Instance
    --------
    Replace( ByVal input As String, ByVal replacement As String ) As String
    Replace( ByVal input As String, ByVal replacement As String, int count ) As String
    Replace( ByVal input As String, ByVal replacement As String, int count, int startat ) As String
    Replace( ByVal input As String, ByVal evaluator As MatchEvaluator ) As String
    Replace( ByVal input As String, ByVal evaluator As MatchEvaluator, ByVal count As Integer ) As String
    Replace( ByVal input As String, ByVal evaluator As MatchEvaluator, , ByVal count As Integer, ByVal startat As Integer ) As String

    Shared
    ------
    Replace( ByVal input As String, ByVal pattern As String, ByVal replacement As String ) As String
    Replace( ByVal input As String, ByVal pattern As String, ByVal replacement As String, ByVal options As RegexOptions ) As String
    Replace( ByVal input As String, ByVal pattern As String, ByVal evaluator As MatchEvaluator ) As String
    Replace( ByVal input As String, ByVal pattern As String, ByVal evaluator As MatchEvaluator, ByVal options As RegexOptions ) As String
[C#]
    instance
    --------
    string Replace( string input, string replacement )
    string Replace( string input, string replacement, int count )
    string Replace( string input, string replacement, int count, int startat )
    string Replace( string input, MatchEvaluator evaluator )
    string Replace( string input, MatchEvaluator evaluator, int count )
    string Replace( string input, MatchEvaluator evaluator, int count, int startat )

    static
    ------
    string Replace( string input, string pattern, string replacement )
    string Replace( string input, string pattern, string replacement, RegexOptions options )
    string Replace( string input, string pattern, MatchEvaluator evaluator  )
    string Replace( string input, string pattern, MatchEvaluator evaluator, RegexOptions options )
Msdn documentation

So, as you can see, there are instance and static (Shared) methods that are available to call when performing replacement operations. The most significant differences between the options are that you can either use a static string or a MatchEvaluator for the replacement argument. You would use a MatchEvaluator when you need to perform additional operations on the matched item - which we'll look at in a moment.

Simple Replacement - straight replace

A straight replacement is useful when you want look for patterns of text and simply replace them with another string (perhaps a zero length string). For example, you might want to find specific words and CAPITALIZE them or replace them with another word, or, just plain-old remove them. Here are some examples of simple, straight replacements:

Find a word and Capitalize it (using an instance method):

    [VB]

Dim source As String = "This is a body of text"
Dim find As String = "body"

Dim  re As New Regex( find, RegexOptions.IgnoreCase )
Dim result As String = "Result: " & re.Replace( source, find.ToUpper() )
    [C#]

string source = @"This is a body of text" ;
string find = "body" ;

Regex re = new Regex( find, RegexOptions.IgnoreCase ) ;
string result = "Result: " + re.Replace( source, find.ToUpper() ) ;
 

Trim leading and trailing whitespace (using a static method):

   [VB]
   
Dim source As String = "           foo                 "
Dim find As String = "(^\s+)|(\s+$)"
Dim result As String = "Result: " & Regex.Replace( source, find, "", RegexOptions.IgnoreCase )
 
    [C#]

string source = "           foo                 " ;
string find = @"(^\s+)|(\s+$)" ;
string result = "Result: " + Regex.Replace( source, find, "", RegexOptions.IgnoreCase )

Simple Replacement - referring to captured items

Another common use of Replace involves referring to the captured groups using the special $n or ${groupName} notation, for example:

Swap names around (using ordinal notation):

    [VB]

Dim source As String = String.Format("Mr. Darren Neimke{0}Mr. John Doe{0}Ms. Jane Doe", Environment.NewLine )
Dim find As String = "(\w+\.)\s+(\b\w+\b)\s+(\b\w+\b)"
Dim result As String = Regex.Replace( source, find, "$3, $1 $2" )
    [C#]

string source = String.Format("Mr. Darren Neimke{0}Mr. John Doe{0}Ms. Jane Doe", Environment.NewLine ) ;
string find = @"(\w+\.)\s+(\b\w+\b)\s+(\b\w+\b)" ;
string result = "Result: " + Regex.Replace( source, find, @"$3, $1 $2" ) ;

Format .com urls into hyperlinks (using named groups notation):

    [VB]
 
Dim source As String = "http://www.regexlib.com"
Dim find As String = "(?'Url'http\:\/\/www\.\w+\.com)"
Dim result As String = "Result: " & Regex.Replace( source, find, "<a href=""${url}"">${Url}</a>" )
    [C#]

string source = @"http://www.regexlib.com" ;
string find = @"(?'Url'http\:\/\/www\.\w+\.com)" ;
string result = "Result: " + Regex.Replace( source, find, @"<a href=""${url}"">${Url}</a>" ) ;

Simple Replacement - limiting the scope of replacement

You can use the overloaded instance method that takes a startat position argument to direct the regex to miss a section and only match within a given section of text:

Emboldens the word "blah" but only when found in the body of the document:

    [VB]
    
Dim source As String = "<html><head><title>blah</title></head><body>blah</body></html>"
Dim find As String = "(?'theWord'blah)"
Dim  re As New Regex( find, RegexOptions.IgnoreCase )
Dim result As String = "Result: " & re.Replace( source, "<b>${theWord}</b>", 9999, source.IndexOf("<body>") )
    [C#]

string source = @"     <html>
    <head>
        <title>blah</title>
    </head>
    <body>
        blah
    </body>
</html>" ;
string find = @"(?'theWord'blah)" ;

Regex re = new Regex( find, RegexOptions.IgnoreCase ) ;
string result = "Result: " + re.Replace( source, @"<b>${theWord}</b>", 9999, source.IndexOf("<body>") ) ;

MatchEvaluator - using a pointer as a replacement argument.

By using an overload that takse a MatchEvaluator for the replacement argument you can point to a delegate method to dynamically build the replace string. This is especially useful if you need to perform more complicated logic on the Match'ed text before inserting its replacement. Each match in the replace operation is handed off to the method that you define for your MatchEvaluator and, that method can do whatever it likes to the match and simply return a string that is then used as the replacement value. Here's an example using a MatchEvaluator that emboldens the word "foo" but only when NOT found as part of ANCHORS:

Match "foo" not in anchors using MatchEvaluator

    [VB]

Dim source As String = "<a >foo</a>foo"
Dim find As String = "(?'Url'<a [^>]*>.*?</a>)|(?'theWord'foo)"
Dim  re As New Regex( find, RegexOptions.IgnoreCase )

' use a MatchEvaluator with a pointer to the delegate method
Dim result As String = re.Replace( source, New MatchEvaluator( AddressOf FormatLinkBits ) )


' Delegate method
Private Function FormatLinkBits( ByVal m As Match ) As String
    If m.Groups("theWord").Success Then
        Dim theWord As String =  m.Groups("theWord").Value
        Return "<b>" & theWord & "</b>"
    Else 
        Return m.Value
    End If
End Function
    [C#]

string source = sourceTextBox.Text ;
Regex re = new Regex( @"(?'Url'<a [^>]*>.*?</a>)|(?'theWord'foo)" ) ;

// use a MatchEvaluator with a pointer to the delegate method
string result = re.Replace( source, new MatchEvaluator( FormatLinkBits ) ) ;


// delegate method
private string FormatLinkBits( Match m )
{
    if( m.Groups["theWord"].Success ) 
    {
        string theWord = m.Groups["theWord"].Value ;
        return "<b>" + theWord + "</b>" ;
    }
    else
        return m.Value ;
}

Here's another example that filters bad words and replaces them with censored text:

    [VB]

Dim source As String = "poo and browner are swearing expressions!"
Dim find As String = "(shit|poo|crap|turd|browner)"
Dim  re As New Regex( find, RegexOptions.IgnoreCase )

' use a MatchEvaluator with a pointer to the delegate method
Dim result As String = re.Replace( source, New MatchEvaluator( AddressOf FormatSwearWords ) )    


' delegate method
Private Function FormatSwearWords( ByVal m As Match ) As String
    Dim l As Integer = m.Value.Length
    Return m.Value.Substring(0, 2) & new String("#"c, l - 2)
End Function
    [C#]
  
string source = "poo and browner are swearing expressions!" ;
Regex re = new Regex( "shit|poo|crap|turd|browner" ) ;

// use a MatchEvaluator with a pointer to the delegate method
string result = re.Replace( source, new MatchEvaluator( FormatSwearWords ) ) ;

private string FormatSwearWords( Match m )
{
    int len = m.Value.Length ;
    return m.Value.Substring(0, 2) + new String('#', len - 2) ;
}
Posted: Sep 26 2003, 09:50 AM by digory | with 63 comment(s)
Filed under: , ,
Regex Reminders #0 - Commenting Regular Expressions
Free spacing and comment mode
.NET Regular Expressions allow you to embed comments and whitespace within pattern strings making them clearer to 
read (because of the whitespace), and easier to maintain (due to the modularity). To use this feature you must turn on the RegexOptions.IgnorePatternWhitespace flag. This can be achieved
either by using the RegexOptions enumerated datatype or, via the (?x) mode modifier. Therefore the following
two examples are functionally identical: Regex re = new Regex( @" # This pattern matches Foo (?i) # turn on insensitivity # The Foo bit \b(Foo)\b " , RegexOptions.IgnorePatternWhitespace ) ; Regex re = new Regex( @"(?x) # This pattern matches Foo (?i) # turn on insensitivity # The Foo bit \b(Foo)\b " ) ; Using IgnorePatternWhitespace option, comments can be embedded in one of two ways. Firstly, a raw '#'
character can be used to mark the beginning of a comment and the comment runs up to the first NEWLINE
(\n) character that is encountered. This can be easily achieved in C# with verbatim strings @"..."
or in VB by appending newline characters within the string using Chr(10), vbCrLf or Environment.NewLine.
Comments can also be declared using the (?#...) syntax. The following 3 snippets demonstrate examples of each of these methods... C# Verbatim Strings. using System; using System.Collections; using System.Text.RegularExpressions ; namespace Regex Snippets.Tests { public class CommentedCSharp { public static void Main() { Regex re = new Regex( @" # This pattern matches Foo (?i) # turn on insensitivity # The Foo bit \b(Foo)\b " , RegexOptions.IgnorePatternWhitespace ) ; for ( Match m = re.Match( "foo bar Foo" ) ; m.Success ; m = m.NextMatch() ) Console.WriteLine( m.Value + Environment.NewLine ) ; Console.ReadLine(); } } } VB.NET using (?#...) syntax. Option Strict On Imports System.Text.RegularExpressions Namespace Regex Snippets.Tests Module CommentedVBOne Public Sub Main() ' Demonstrates a VB Whitespace pattern using the '" (?#...) " & _ ' syntax Dim re As New Regex( _ " (?# This pattern matches Foo ) " & _ " (?i) (?# turn on insensitivity ) " & _ " (?# The Foo bit ) " & _ " \b(Foo)\b " _ , RegexOptions.IgnorePatternWhitespace) Dim m As Match = re.Match("foo bar foo") Dim s As String = "" While m.Success s &= (m.Value & Environment.NewLine) m = m.NextMatch() End While MessageBox.Show(s) End Sub End Module End Namespace VB.NET using appended newlines. Option Strict On Imports System.Text.RegularExpressions Namespace Regex Snippets.Tests Module CommentedVBTwo Public Sub Main() ' Demonstrates a VB Whitespace pattern using the '" (?#...) " & _ ' syntax Dim re As New Regex( _ " # This pattern matches Foo " & vbCrLf & _ " (?i) # turn on insensitivity " & vbCrLf & _ " # The Foo bit " & vbCrLf & _ " \b(Foo)\b " _ , RegexOptions.IgnorePatternWhitespace) Dim m As Match = re.Match("foo bar foo") Dim s As String = "" While m.Success s &= (m.Value & Environment.NewLine) m = m.NextMatch() End While MessageBox.Show(s) End Sub End Module End Namespace
Posted: Sep 23 2003, 06:40 PM by digory | with 24 comment(s)
Filed under:
Regex Reminders - A brief explanation

Over the next couple weeks I'm going to post a series of regular expression examinations; each one will be a code intensive focus on a certain operations such as "Replace" or "Working with Matches and Groups".  The goal of the Regex Reminders is to end up with a lot of code for working with regex's that people can just use to "grab and go".  The series will also spend time looking at common regex techniques such as alternation and grouping techniques.

Each of the reminders will contain code samples written in both VB and C#.

It is anticipated that the entire series will span 7 or 8 items and will also appear as a link from RegexLib.com.

The first 4 items will be:

  • Regex Reminders [0] - Commenting Regular Expressions
  • Regex Reminders [1] - Replacement Operations
  • Regex Reminders [2] - Working with Matches, Groups and Captures
  • Regex Reminders [3] - Gunning for speed : efficiency
Posted: Sep 23 2003, 02:59 PM by digory | with 1 comment(s)
Filed under:
Timing javascript

A little snippet that demonstrates how I perform speed tests against js code:

<html>
<
body>

<script language="javascript">

var Foos = { One:0, Two:0 } ;

Foos.Speak = function()
{
    return ( this.One + " : " + this.Two ) ;
}


function Bars()
{
    this.One = this.Two = 0 ;
}

Bars.prototype.Speak = function()
{
    return ( this.One + " : " + this.Two ) ;
}

bars = new Bars() ;



// Test
window.onload = function()
{
    // test 1
    var startTime=new Date() ;
    var s ;
    for( var i = 0; i < 200000; i++ )
    {
        Foos.Speak() ;
    }
    var endTime=new Date();
    document.getElementById("spnResult1").innerText = (endTime-startTime) ;


    // test 2
    startTime=new Date() ;
    for( var i = 0; i < 200000; i++ )
    {
        bars.Speak() ;
    }
    endTime=new Date();
    document.getElementById("spnResult2").innerText = (endTime-startTime) ;
}
script>

Foos: span id="spnResult1"> ms<br>
Bars: span id="spnResult2"> ms<br>

html>
More Posts Next page »