/* File: util.c -- Utility functions */
/****************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include "util.h"

typedef struct node* Node;

struct node {
    void* item;    
    Node next;
}; 

struct linkedlist {
    Node head;    
};

LinkedList emptyList() {
    LinkedList result = malloc(sizeof(struct linkedlist));
    result->head = NULL;
    return result;
}

void* getFirst(LinkedList list) {
    Node node = list->head;
    if (node) {
        return node->item;
    } else {
        return NULL;        
    }
}

void deleteList(LinkedList list) {
    Node node = list->head;
    while(node) {
        Node temp = node;    
        node = node->next;
        free(temp);
    }
    free(list);
}

void list_add(LinkedList list, void* item) {
    Node* node = &(list->head);
    while(*node) {    
        node = &((*node)->next);    
    }
    *node = malloc(sizeof(struct node));
    (*node)->item = item;
    (*node)->next = NULL;
}

int linkedListSize(LinkedList list) {
    int count = 0;
    Node node = list->head;
    while(node) {    
        node = node->next;
        count++;
    }
    return count;
}

void printList(LinkedList list, void (*print)(void* item)) {
    Node node = list->head;
    if (node) {
        print(node->item);
        node = node->next;
    }
    while(node) {    
        printf(", ");
        print(node->item);
        node = node->next;
    }
}

int identity(void* i1, void* i2) {
    return i1 == i2;
}

void* removeItem(LinkedList list, void* item, int (*eq)(void* i1, void* i2)) {
    Node* node = &(list->head);
    while(*node) {
        if (eq((*node)->item, item)) {
            Node temp = *node;
            *node = temp->next;
            void* result = temp->item;
            free(temp);
            return result;
        }
        node = &((*node)->next);
    }
    return NULL;
}

void* replaceItem(LinkedList list, void* remove, void* replace, int (*eq)(void* i1, void* i2)) {
    Node* node = &(list->head);
    while(*node) {
        if (eq((*node)->item, remove)) {
            (*node)->item = replace;
            return replace;
        }
        node = &((*node)->next);
    }
    return NULL;
}

char* copyString(char* s)
{
    char* result = malloc(strlen(s)+1);
    strcpy(result, s);
    return result;     
}

int nonwhitespace(char* s)
{
    while(1) {    
        switch(*s) {
        case 0:
            return 0;
        case ' ': case '\t': case '\n': 
        case '\r': case '\f':
            break;
        default:
            return 1;
        }
        s++;
    }
}


void* doubleAndCopy(void* area, size_t size) {
    void* new_area = malloc(size << 1);
    memcpy(new_area, area, size);
    free(area);
    return new_area;
}
/*
char *readNext(char *ln)
{
    char *token, *tmp;
    int len;
    
    if (ln == NULL)
        return NULL;
    
    // skip all spaces
    else if (*ln == '\n')
        return NULL;

void* doubleAndCopy(void* area, size_t size) {
    void* new_area = malloc(size << 1);
    memcpy(new_area, area, size);
    free(area);
    return new_area;
}
    else if (*ln == '\0')
        return NULL;
    else if (*ln == ' ')
        return readNext(++ln);
    else if (*ln == '\t')
        return readNext(++ln);
        else {
            tmp = ln;
            ln = strpbrk(ln," \t \n \0 EOF");
            len = ln - tmp;
            token = (char *) calloc(len+1, sizeof(char));
            strncpy(token,tmp,len);
            return token;
        }
}


char *readLine(FILE *fp) {
    char *rln = malloc(MAXPERLINE+1);
    rln = fgets(rln, MAXPERLINE+1, fp);
    
    // skip space at the begining of the line
    while(rln!= NULL && *rln==' ') {
        rln++;
    }
    return rln;
}


int isNumber(char *c)
{
    if (c==NULL) return 0;
    
    
    if (*c == '-' || *c == '+')
        c++;
    
    if (c==NULL) return 0;
    
    while(*c != '\0') {
        if (!isdigit(*c++))
            return 0;
    }
    return 1;
}


void toupperString(char *c)
{
    while(c!=NULL && *c!='\0')
        *c++ = toupper(*c);
}

void tolowerString(char *c)
{
    while(c!=NULL && *c!='\0')
        *c++ = tolower(*c);
}

char *gotoNS(char *c)
{
    while(c!= NULL && (*c == ' ' ||
            *c == '\t')) {
    c++;
            }
            return c;
}

char *inttoString(int n)
{
    int length = 2;
    int i = n;
    if (i < 0) {
        i = -n;
        length++;
    }
    while(i) {
        i >>= 3;
        length++;
    }
    char *s = malloc(length);
    sprintf(s, "%d", n);
    return s;
}

int hashValue(char *token, int it, int size)
{
    int j;
    int k=0;
    while((j=*token++) != '\0')
        k += k+j;
    return ((k % size) + it*(1 + k%(size-1)))%size;
    
}

void printspace(int n)
{
    int j;
    for (j=0;j<n;j++)
        printf(" ");
}


int set_add(int num, int n)
{
    int tmp = num;
    int one = 1;
    
    if (n<0) return num;
    
    return (tmp | (one << n));
}


int unSetBit(int num, int n)
{
    int tmp = num;
    int one = 1;
    
    if (n<0) return num;
    
    return (tmp & ~(one << n));
}
*/

// end of util.c