Thread overview
Another short blog post/tutorial (Finding a string in a stream)
Mar 15, 2006
Alan Knowles
Mar 15, 2006
Regan Heath
Mar 16, 2006
Alan Knowles
Mar 16, 2006
Regan Heath
March 15, 2006
Since I got such good feedback before, I though I'd post about the latest short tutorial...

http://www.akbkhome.com/blog.php/View/116/More_DigitalMars_D__finding_a_string_in_a_stream.html

Feel free to comment / make suggestions.

Regards
Alan
March 15, 2006
On Wed, 15 Mar 2006 11:38:15 +0800, Alan Knowles <alan@akbhome.com> wrote:
> Since I got such good feedback before, I though I'd post about the latest short tutorial...
>
> http://www.akbkhome.com/blog.php/View/116/More_DigitalMars_D__finding_a_string_in_a_stream.html
>
> Feel free to comment / make suggestions.

Here is how I would write it.

NOTE:
 - eof is (and belongs) in the MimeStream.
 - eof is used with property syntax i.e. no () on the method call.
 - there is absolutely no need to copy the characters or allocate memory
 - nested functions are your friends

import std.stdio;

void main () {
    MimeStream x = new MimeStream("This is a test  - hello  with XXX - hello world - in the middle");
    uint lines = 0;
    bool ret = skipUntilBoundary(x,"- hello world -",lines);
    if (!ret) writefln("NO MATCH");
    else {
    	char c;
    	
    	writefln("GOT STRING! rest:");
    	while(x.getChar(c)) writef(c);
    }
}

class MimeStream
{
    char[] thestring = "";
    int pos = 0;

    this(char[] string) { thestring = string.dup; }

    bool getChar(inout char c)
    {
        if (eof) return false;
        c = thestring[pos++];
        return true;
    }

    bool eof()
    {
    	return (pos >= thestring.length);
    }
}

bool skipUntilBoundary(MimeStream x, char[] delim, inout uint lines)
{
	char c;	
	uint i;
	
	bool compareDelim()
	{	
		for(i = 0; i < delim.length; i++) {
			if (c != delim[i]) break;
			if (!x.getChar(c)) return false;
		}
		return (i == delim.length);
	}
	
	while(x.getChar(c) && !compareDelim()) {
		if (c == '\n') lines++;
	}
	
	return !x.eof;
}
March 16, 2006
You missed the challenge of the task :)

looking for "- ABC - DEF -" in "test - ABC - ABC - DEF -"
as you need to backtrack as you have eaten too many characters, by the time you get to the real match..

the nested functions look like a good idea. -> it does make things a bit cleaner.

The original code returned eof, although you are right, the caller should really check the Stream for eof, rather than this method.

Thanks
Alan

Regan Heath wrote:
> On Wed, 15 Mar 2006 11:38:15 +0800, Alan Knowles <alan@akbhome.com> wrote:
> 
>> Since I got such good feedback before, I though I'd post about the  latest short tutorial...
>>
>> http://www.akbkhome.com/blog.php/View/116/More_DigitalMars_D__finding_a_string_in_a_stream.html 
>>
>>
>> Feel free to comment / make suggestions.
> 
> 
> Here is how I would write it.
> 
> NOTE:
>  - eof is (and belongs) in the MimeStream.
>  - eof is used with property syntax i.e. no () on the method call.
>  - there is absolutely no need to copy the characters or allocate memory
>  - nested functions are your friends
> 
> import std.stdio;
> 
> void main () {
>     MimeStream x = new MimeStream("This is a test  - hello  with XXX -  hello world - in the middle");
>     uint lines = 0;
>     bool ret = skipUntilBoundary(x,"- hello world -",lines);
>     if (!ret) writefln("NO MATCH");
>     else {
>         char c;
>                writefln("GOT STRING! rest:");
>         while(x.getChar(c)) writef(c);
>     }
> }
> 
> class MimeStream
> {
>     char[] thestring = "";
>     int pos = 0;
> 
>     this(char[] string) { thestring = string.dup; }
> 
>     bool getChar(inout char c)
>     {
>         if (eof) return false;
>         c = thestring[pos++];
>         return true;
>     }
> 
>     bool eof()
>     {
>         return (pos >= thestring.length);
>     }
> }
> 
> bool skipUntilBoundary(MimeStream x, char[] delim, inout uint lines)
> {
>     char c;       uint i;
>         bool compareDelim()
>     {           for(i = 0; i < delim.length; i++) {
>             if (c != delim[i]) break;
>             if (!x.getChar(c)) return false;
>         }
>         return (i == delim.length);
>     }
>         while(x.getChar(c) && !compareDelim()) {
>         if (c == '\n') lines++;
>     }
>         return !x.eof;
> }
March 16, 2006
On Thu, 16 Mar 2006 09:58:55 +0800, Alan Knowles <alan@akbkhome.com> wrote:
> You missed the challenge of the task :)
>
> looking for "- ABC - DEF -" in "test - ABC - ABC - DEF -"
> as you need to backtrack as you have eaten too many characters, by the time you get to the real match..

You're right. I didn't imagine that possibility (due in part to the way the original code sidestepped the problem with it's revolving buffer and custom compare function).

Regan