//    findbook.java by Steven R. Brandt
//    <p>
//    An example file explaining how to use
//    com.stevesoft.pat, com.stevesoft.pat.wrap,
//    and com.stevesoft.pat.apps
//    <p>
//    This software comes without express or implied warranty.
//    No claim is made about the suitability of this software for
//    any purpose and neither I nor SteveSoft shall be liable for
//    damages suffered by the user of this software.
import com.stevesoft.pat.*;

// This program is a speed test for finding text.
// Which goes faster on your machine/java version pair, the
// indexOf method of String or the search method of Regex?
//
// I've had to work on both my package and the text since I
// originally put this on the web, java 1.1.4 seems to be
// faster.
//
// If you want a bit more speed, you can invoke the SkipBMH searcher
// directly.  It just searches for substrings and doesn't have the
// overhead of Regex because it can't do as much -- but it is still
// more versatile than String's indexOf because it can, optionally,
// ignore case.
//
// In any event, the timings will vary with each run and you should
// run this experiment a few times to get a good idea of which routine
// is fastest.

// When java 1.1.6 came out it was necessary to modify this example
// extensively.  First, because of the jit, the value of imax needed
// to be drastically increased.  Secondly, two optimizations (that
// take effect even without -O) caused the loop that tested the
// speed of the String.indexOf method to appear to execute in zero
// time.

// Optimization one:  I needed to make the "nothing" class to trick the
// compiler into thinking that I was using the result of indexOf.
// Without this, the loop in which it is called gets optimized away.

// Optimization two:  I needed to have two slightly different Strings
// and to alternate between them on successive searches.  Without doing
// this, java 1.1.6 is smart enough to take the call to indexOf outside
// the loop, and thus the loop iterates only on the doNothing() method.

// Even aside from this, the indexOf method is a little
// faster now, and I had to go back and re-optimize SkipBMH so that I
// could consistantly win race #3 on the Windows platform.

class nothing {
  public void doNothing(int x) {}
  public void doNothing(boolean x) {}
}

public class findbook {
    public static void main(String[] unused) {
        while(true)
            race();
    }
    public static void race() {
        nothing n=new nothing();

        // A random large number...
        int imax = 100000;
        new Regex(); // Print startup message.

        String[] pats = new String[]{"book","Java book","that Java book"};
        String txt = "I've checked upstairs.  "+
            "I've looked between the old newspapers in the living room.  "+
            "I've looked at the office bookshelf.  "+
            "I've searched through that big pile in attic.  "+
            "I've rumaged around in the basement, the bedroom, and the kitchen.  "+
            "I've even looked under the refrigerator. "+
            "Now where on earth did I put that Java book?";
        String[] txts = new String[]{"One: "+txt,"Two: "+txt};


        for(int j=0;j<pats.length;j++) {
            System.out.println("\n\nRace #"+(j+1));
            String pat = pats[j];
            System.out.println("Look for this string ==>"+pat+"<==");

            Regex r = new Regex(pat);
            r.optimize();

            SkipBMH sbmh = new SkipBMH(pat);

            // prove that it gets the same answer as indexof
            r.search(txt);
            if(r.matchedFrom() != txt.indexOf(pat))
                throw new Error("Regex didn't work!");

            if(sbmh.search(txt) != txt.indexOf(pat))
                throw new Error("SkipBMH didn't work!");

            // try to prevent garbage collection from
            // interfering with the timing test.
            System.gc();

            // and they're off...
            long t1 = System.currentTimeMillis();
            for(int i=0;i<imax;i++) {
                /* Of the following three ways of writing this next
                 * line, only one of them executes in non-zero time.
                 * In the other two cases, the call to indexOf is
                 * apparently moved outside the loop.
                 */
                n.doNothing(txts[i%2].indexOf(pat));
                //txts[i%2].indexOf(pat);
                //n.doNothing(txt.indexOf(pat));
            }
            long t2 = System.currentTimeMillis();
            for(int i=0;i<imax;i++)
                n.doNothing(r.search(txts[i%2]));
            long t3 = System.currentTimeMillis();
            for(int i=0;i<imax;i++)
                n.doNothing(sbmh.search(txts[i%2]));
            long t4 = System.currentTimeMillis();

            System.out.println("Time for String.indexOf="+(t2-t1));
            System.out.println("Time for Regex.search="+(t3-t2));
            System.out.println("Time for SkipBMH.search="+(t4-t3));
        }
    }
}

