// main.c
#include "arrayList.h"
#include "FIDIndex.h"
#include "StringHashTable.h"
#include "nextField.h"
#include "buildIndex.h"
#include "GISParse.h"
#include "cmdReader.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LINE_LENGTH 500
#define DEFAULT_MASTER_SIZE 256
uint32_t elfhash(const char *str);
int main(int args, char *files[])
{
// Reads in input file and create output file
FILE *readF = fopen(files[1], "r");
FILE *outF = fopen(files[2], "w");
// Checks for input file
if (!readF)
{
printf("Error: unable to create %s\n", files[1]);
return 1;
}
if (!outF)
outF = fopen("script.out", "w");
arrayList *masterFID = AL_create(DEFAULT_MASTER_SIZE, sizeof(FIDIndex), compareFIDIndex, cleanFID);
StringHashTable *masterName;
FILE *gis;
int cmdNum = 1;
char *line = calloc(MAX_LINE_LENGTH - 1, sizeof(char)),
*sep = "----------------------------------------------";
bool index_and_table_made = false;
while (fgets(line, MAX_LINE_LENGTH - 1, readF))
{
// Holds the current command and paramters
char *cmd, *p1, *p2, *tok = strtok(line, "\t");
if (*tok != ';')
{
// Populates command and paramter fields
cmd = tok, tok = strtok(NULL, "\t");
p1 = tok, tok = strtok(NULL, "\t");
if (tok != NULL)
p2 = strtok(tok, "\n");
if (!strcmp(cmd, "db_file"))
{
char *fileName = strtok(p1, "\n");
gis = fopen(fileName, "r");
build_FID(masterFID, gis); // Builds FID index
}
if (!strcmp(cmd, "table_sz"))
{
int size = atoi(p1);
masterName = StringHashTable_create(size, elfhash);
build_name(masterName, gis); // Builds hash table
index_and_table_made = true;
}
if (!strcmp(cmd, "exists"))
{
char *name = p1, *state = p2, *key = create_key(name, state);
uint32_t *locations = StringHashTable_getLocationsOf(masterName, key), x = 0;
if (locations)
while (locations[x])
x++;
fprintf(outF, "CMD\t%d:\t%s\t%s\t%s\n\n", cmdNum, cmd, name, state);
if (x == 0)
fprintf(outF, "Not found in index: %s %s\n%s\n", name, state, sep);
else
fprintf(outF, "%d occurrences: %s %s\n%s\n", x, name, state, sep);
cmdNum++;
}
if (!strcmp(cmd, "details_of"))
{
char *name = p1, *state = p2, *key = create_key(name, state);
uint32_t *locations = StringHashTable_getLocationsOf(masterName, key), x = 0;
fprintf(outF, "CMD\t%d:\t%s\t%s\t%s\n\n", cmdNum, cmd, name, state);
if (!locations)
fprintf(outF, "Not found in index: %s %s\n%s\n", name, state, sep);
else
{
while (locations[x])
{
char **details = get_details_of(gis, locations[x]),
**lat_long = get_readable_lat_and_long(locations[x], gis);
fprintf(outF, "FID:\t\t%s\nName:\t\t%s\nType:\t\t%s\nState:\t\t%s\nCounty:\t\t%s\n",
details[0], details[1], details[2], details[3], details[4]);
fprintf(outF, "Longitude:\t%sd %dm %ds %s\t(%s)\nLatitude:\t%sd %dm %ds %s\t(%s)\n\n",
lat_long[6], atoi(lat_long[7]), atoi(lat_long[8]), lat_long[9], details[8], lat_long[2],
atoi(lat_long[3]), atoi(lat_long[4]), lat_long[5], details[7]);
x++;
}
fprintf(outF, "%s\n", sep);
}
cmdNum++;
}
if (!strcmp(cmd, "distance_between"))
{
FIDIndex *entry1 = FIDIndex_create(p1, 0), *entry2 = FIDIndex_create(p2, 0),
*id1 = AL_find(masterFID, entry1), *id2 = AL_find(masterFID, entry2);
fprintf(outF, "CMD\t%d:\t%s\t%s\t%s\n\n", cmdNum, cmd, entry1->FID, entry2->FID);
if (!id1)
fprintf(outF, "Invalid feature ID:\t%s\n%s\n", entry1->FID, sep);
else if (!id2)
fprintf(outF, "Invalid feature ID:\t%s\n%s\n", entry2->FID, sep);
else
{
double distance = find_distance_between(id1->occuranceOffset, id2->occuranceOffset, gis);
char **first = get_readable_lat_and_long(id1->occuranceOffset, gis),
**second = get_readable_lat_and_long(id2->occuranceOffset, gis);
fprintf(outF, "First:\t( %sd %dm %ds %s,\t%sd %dm %ds %s )\t%s, %s\n",
first[6], atoi(first[7]), atoi(first[8]), first[9], first[2], atoi(first[3]), atoi(first[4]),
first[5], first[0], first[1]);
fprintf(outF, "Second:\t( %sd %dm %ds %s,\t%sd %dm %ds %s )\t%s, %s\n",
second[6], atoi(second[7]), atoi(second[8]), second[9], second[2], atoi(second[3]),
atoi(second[4]), second[5], second[0], second[1]);
fprintf(outF, "Distance:\t%.1fkm\n%s\n", distance, sep);
}
cmdNum++;
}
if (!strcmp(cmd, "quit"))
{
fprintf(outF, "CMD\t%d:\t%s\n\nExiting...\n%s", cmdNum, cmd, sep);
clean(masterFID, masterName);
fclose(gis);
break;
}
}
else if (index_and_table_made)
fprintf(outF, "%s", line);
}
fclose(readF);
fclose(outF);
free(line);
return 0;
}
uint32_t elfhash(const char *str)
{
assert(str != NULL); // self-destuct if called with NULL
uint32_t hashvalue = 0, // value to be returned
high; // high nybble of current hashvalue
while (*str)
{ // continue until *str is '\0'
hashvalue = (hashvalue << 4) + *str++; // shift high nybble out,
// add in next char,
// skip to the next char
if ((high = (hashvalue & 0xF0000000))) // if high nybble != 0000
hashvalue = hashvalue ^ (high >> 24); // fold it back in
hashvalue = hashvalue & 0x7FFFFFFF; // zero high nybble
}
return hashvalue;
}
/**
* Closes all files and clears the dynamically allocated arrayList and StringHashTable
*/
void clean(arrayList *list, StringHashTable *table)
{
StringHashTable_clear(table);
AL_clean(list);
free(table);
free(list);
}