#include <stdio.h>
#include <stdlib.h>

// some node structure for our 'linked list'
typedef struct node{
     struct node* next;
     int data;
}node_t;


// Computes the length of a linked list
unsigned long length(node_t* head){
     // Handle error/invalid input
     if(head==NULL){
	  return 0;
     }

     // Keep count by iterating through loop
     unsigned long len = 0;
     node_t* iter = head;
     while(iter->next!=NULL){
	  ++len;
	  iter = iter->next;
     }

     // return our result
     return len;
}

// Sets a nodes value in a linked list at a position
// On failure: Returns without any mutation to list.
void setNodeValue(node_t* head, unsigned long index, int value){
     if(index > length(head)){
	  return;
     }

     // Iterate again
     unsigned long counter=0;
     node_t* iter = head;
     while(iter->next!=NULL){
	  if(counter==index){
	       iter->data = value;
	       return;
	  }
	  ++counter;
	  iter = iter->next;
     }
}


// Prints a nodes value in a linked list at a position
// On failure: Returns without any mutation to list.
int getNodeValue(node_t* head, unsigned long index){
     if(index > length(head)){
	  return;
     }

     // Iterate again
     unsigned long counter=0;
     node_t* iter = head;
     while(iter->next!=NULL){
	  if(counter==index){
	       return(iter->data);
	  }
	  ++counter;
	  iter = iter->next;
     }
}

// Iterate through list and 'free')
void freeList(node_t* head){
     if(NULL==head){
	  return;
     }

     node_t* iter = head; // stack allocated pointer
     node_t* next = head->next;
     while(NULL != iter->next){
	  free(iter);
	  iter = next;
	  next = iter->next;
     }
     free(iter);
}


// Create a 'global' for our example linked list.
node_t* myLinkedList = NULL;


int main(){

     // Allocate some memory for our global
     myLinkedList = (node_t*)malloc(sizeof(node_t));
     myLinkedList->data = 0;
     myLinkedList->next = NULL;

     // Populate linked list with some nodes
     int i = 0;
     node_t* iter = myLinkedList;
     for(i =0; i < 100; ++i){
	  // Create some new node
	  node_t* temp = (node_t*)malloc(sizeof(node_t));
	  temp->data = i;
	  temp->next = NULL;
	  // Attach it to our iterator
	  iter->next = temp;
	  // temp is our last node, this is where we pickup our iteration.
	  iter=temp;
     }

     // This loop is a bit inefficient, in that we are
     // constantly computing 'length' during run-time for
     // a data structure that could change in size.
     // Ideally, we should just make the 'length' call
     // once before this loop.
     for(i = 0; i < length(myLinkedList); ++i){
	  setNodeValue(myLinkedList,i,1000-i);
	  printf("%d\n",getNodeValue(myLinkedList,i));
     }

     // Free memory :)
     freeList(myLinkedList);

     return 0;
}
