// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
**********************************************************************
* Copyright (c) 2002-2007, International Business Machines
* Corporation and others.  All Rights Reserved.
**********************************************************************
*/
package com.ibm.icu.dev.test.perf;
import java.util.HashSet;
import java.util.Iterator;

import com.ibm.icu.text.UnicodeSet;
import com.ibm.icu.text.UnicodeSetIterator;

/**
 * A class for testing UnicodeSet performance.
 *
 * @author Alan Liu
 * @since ICU 2.4
 */
public class UnicodeSetPerf extends PerfTest {

    String pattern;
    UnicodeSet testChars;
    UnicodeSetIterator it;
    UnicodeSet us;
    HashSet hs;

    public static void main(String[] args) throws Exception {
        new UnicodeSetPerf().run(args);
    }

    protected void setup(String[] args) {
        // We only take one argument, the pattern
        if (args.length != 1) {
            throw new RuntimeException("Please supply UnicodeSet pattern");
        }

        pattern = args[0];
        testChars = new UnicodeSet(pattern);
        it = new UnicodeSetIterator(testChars);
        us = new UnicodeSet();
        hs = new HashSet();
    }

    PerfTest.Function testUnicodeSetAdd() {
        return new PerfTest.Function() {
            public void call() {
                us.clear();
                it.reset();
                int n=0;
                while (it.nextRange()) {
                    for (int cp = it.codepoint; cp <= it.codepointEnd; ++cp) {
                        us.add(cp);
                        ++n;
                    }
                }
            }

            public long getOperationsPerIteration() {
                return testChars.size();
            }
        };
    }

    PerfTest.Function testHashSetAdd() {
        return new PerfTest.Function() {
            public void call() {
                hs.clear();
                it.reset();
                int n=0;
                while (it.nextRange()) {
                    for (int cp = it.codepoint; cp <= it.codepointEnd; ++cp) {
                        hs.add(new Integer(cp));
                        ++n;
                    }
                }
            }

            public long getOperationsPerIteration() {
                return testChars.size();
            }
        };
    }

    PerfTest.Function testUnicodeSetContains() {
        us.clear();
        us.set(testChars);
        
        return new PerfTest.Function() {
            public void call() {
                int temp = 0;
                for (int cp = 0; cp <= 0x10FFFF; ++cp) {
                    if (us.contains(cp)) {
                        temp += cp;
                    }
                }
            }

            public long getOperationsPerIteration() {
                return 0x110000;
            }
        };
    }

    PerfTest.Function testHashSetContains() {
        hs.clear();
        it.reset();
        while (it.next()) {
            hs.add(new Integer(it.codepoint));
        }
        return new PerfTest.Function() {
            public void call() {
                int temp = 0;
                for (int cp = 0; cp <= 0x10FFFF; ++cp) {
                    if (hs.contains(new Integer(cp))) {
                        temp += cp;
                    }
                }
            }

            public long getOperationsPerIteration() {
                return 0x110000;
            }
        };
    }

    PerfTest.Function testUnicodeSetIterate() {
        return new PerfTest.Function() {
            public void call() {
                int temp = 0;
                UnicodeSetIterator uit = new UnicodeSetIterator(testChars);
                while (uit.next()) {
                    temp += uit.codepoint;
                }
            }

            public long getOperationsPerIteration() {
                return testChars.size();
            }
        };
    }

    PerfTest.Function testHashSetIterate() {
        hs.clear();
        it.reset();
        while (it.next()) {
            hs.add(new Integer(it.codepoint));
        }
        return new PerfTest.Function() {
            public void call() {
                int temp = 0;
                Iterator itr = hs.iterator();
                while (itr.hasNext()) {
                    temp += ((Integer)itr.next()).intValue();
                }
            }

            public long getOperationsPerIteration() {
                return testChars.size();
            }
        };
    }
}
