CS-PROJECTS / c08_gis_system / cmdReader.c
cmdReader.c
Raw
// 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);
}