int main(int argc, char ** argv)
{
    int num_keys = atoi(argv[1]);
    int i, value = 0;

    if(argc <= 2)
        return 1;

    SETUP

    double before = get_time();

    if(!strcmp(argv[2], "sequential"))
    {
        for(i = 0; i < num_keys; i++)
            INSERT_INT_INTO_HASH(i, value);
    }

    else if(!strcmp(argv[2], "random"))
    {
        srandom(1); // for a fair/deterministic comparison
        for(i = 0; i < num_keys; i++)
            INSERT_INT_INTO_HASH((int)random(), value);
    }

    else if(!strcmp(argv[2], "delete"))
    {
        for(i = 0; i < num_keys; i++)
            INSERT_INT_INTO_HASH(i, value);
        before = get_time();
        for(i = 0; i < num_keys; i++)
            DELETE_INT_FROM_HASH(i);
    }

    else if(!strcmp(argv[2], "sequentialstring"))
    {
        for(i = 0; i < num_keys; i++)
            INSERT_STR_INTO_HASH(new_string_from_integer(i), value);
    }

    else if(!strcmp(argv[2], "randomstring"))
    {
        srandom(1); // for a fair/deterministic comparison
        for(i = 0; i < num_keys; i++)
            INSERT_STR_INTO_HASH(new_string_from_integer((int)random()), value);
    }

    else if(!strcmp(argv[2], "deletestring"))
    {
        for(i = 0; i < num_keys; i++)
            INSERT_STR_INTO_HASH(new_string_from_integer(i), value);
        before = get_time();
        for(i = 0; i < num_keys; i++)
            DELETE_STR_FROM_HASH(new_string_from_integer(i));
    }

    double after = get_time();
    printf("%f\n", after-before);
    fflush(stdout);
    sleep(1000000);
}
static inline const char* InsertStrIntoHash(const char* key, int value)
{
	INSERT_STR_INTO_HASH(key, value);
	return key;
}
static inline void SetStringIntoHash(const char* key, int value, size_t length)
{
	INSERT_STR_INTO_HASH(key, value);
}
int main(int argc, char ** argv)
{
    if (argc <= 3)
        usage(argv[0]);

    char * benchmark = argv[1];
    int    num_keys  = atoi(argv[2]);
    int    value     = 0;
    int    i;

    SETUP

    interval  = atoi(argv[3]);
    startTime = get_time();
    startData = get_data_mem();

    if (!strcmp(benchmark, "sequential"))
    {
        for(i = 0; i < num_keys; i++) {
            INSERT_INT_INTO_HASH(i, value);
            printPoint(i);
        }
    }

    else if (!strcmp(benchmark, "random"))
    {
        srandom(1); // for a fair/deterministic comparison

        for(i = 0; i < num_keys; i++) {
            INSERT_INT_INTO_HASH((int)random(), value);
            printPoint(i);
        }
    }

    else if (!strcmp(benchmark, "delete"))
    {
        for(i = 0; i < num_keys; i++)
            INSERT_INT_INTO_HASH(i, value);

        startTime = get_time();

        for(i = 0; i < num_keys; i++) {
            DELETE_INT_FROM_HASH(i);
            printPoint(i);
        }
    }

    else if (!strcmp(benchmark, "sequentialstring"))
    {
        for(i = 0; i < num_keys; i++) {
            INSERT_STR_INTO_HASH(new_string_from_integer(i), value);
            printPoint(i);
        }
    }

    else if (!strcmp(benchmark, "randomstring"))
    {
        srandom(1); // for a fair/deterministic comparison

        for(i = 0; i < num_keys; i++) {
            INSERT_STR_INTO_HASH(new_string_from_integer((int)random()), value);
            printPoint(i);
        }
    }

    else if (!strcmp(benchmark, "deletestring"))
    {
        for(i = 0; i < num_keys; i++)
            INSERT_STR_INTO_HASH(new_string_from_integer(i), value);

        startTime = get_time();

        for(i = 0; i < num_keys; i++) {
            DELETE_STR_FROM_HASH(new_string_from_integer(i));
            printPoint(i);
        }
    }

    /* This benchmark counts the number of distinct words (strings on nonspace characters) in the king james bible.
     */
    else if (!strcmp(benchmark, "kjvmark"))
    {
        const char * file = "data/king-james-bible.txt";

        if (argc >= 5 && strcmp(argv[3], "-f") == 0)
            file = argv[4];

        size_t size = filesize(file);
        char * text = (char *)malloc(size + 1);    // + 1 allows '\0' termination of last word
        int    fd;

        if ((fd = open(file, O_RDONLY)) < 0) {
            fprintf(stderr, "%s: Failed to open %s\n", argv[0], file);
            exit(1);
        }

        if (read(fd, text, size) != size) {
            fprintf(stderr, "%s: Failed to read %lu bytes from %s\n", argv[0], size, file);
            exit(1);
        }

        // Reset start time and memory now that preparations are done
        startTime = get_time();
        startData = get_data_mem();

        size_t start = 0;

        for (;;) {
            while (start < size && isspace(text[start]))
                start++;

            if (start == size)
                break;

            size_t endWord = start + 1;

            while (endWord < size && !isspace(text[endWord]))
                endWord++;

            text[endWord] = '\0';    // '\0' terminate the "word" (actually a space delimitted sequence)
            INSERT_STR_INTO_HASH(&text[start], value);
            start = endWord + 1;
        }

        if (STR_HASH_GET_SIZE() != 34027) {
            fprintf(stderr, "%s: Incorrect number of pseudo words were found in the KJV text (expected 34027, got %lu)\n", argv[0],
                    STR_HASH_GET_SIZE());
            exit(1);
        }

        printPoint(-1);    // -1 forces printing
    }

    else {
        fprintf(stderr, "%s: No such benchmark '%s'", argv[0], benchmark);
        usage(argv[0]);
    }
}