/*
 * Fixed code for CSE 333 Section 2
 * 1. Draw a memory diagram for the execution to identify errors.
 * 2. Use gdb and valgrind to identify sources of runtime, logical,
 *    and memory errors.
 * 3. Clean up the code style.
 */

#include <string.h>  // strncpy, strlen
#include <stdio.h>   // printf
#include <stdlib.h>  // malloc, NULL, free, EXIT_FAILURE, EXIT_SUCCESS

// A SimpleString stores a C-string and its current length
typedef struct simplestring_st {
  char* word;
  int   length;
} SimpleString;

/*
* FIXED: Returning a pointer as an output parameter requires a double pointer
*/
// Allocate a new SimpleString on the heap initialized with word
// and return pointer to the new SimpleString in dest
void InitWord(char* word, SimpleString** dest);

int main(int argc, char* argv[]) {
  char comp[] = "computer";
  SimpleString ss = {comp, strlen(comp)};
  SimpleString* ss_ptr = &ss;

  // expecting "1. computer, 8"
  printf("1. %s, %d\n", ss_ptr->word, ss_ptr->length);

  char cse[] = "cse333";
  InitWord(cse, &ss_ptr);
  // expecting "2. cse333, 6"
  printf("2. %s, %d\n", ss_ptr->word, ss_ptr->length);
  
  /*
  * FIXED: Use free to fix memory leaks from heap-allocated reversed string
  * (Use valgrind to find this leak)
  */
  free(ss_ptr->word);
  free(ss_ptr);
  return EXIT_SUCCESS;
}

void InitWord(char* word, SimpleString** dest) {
  *dest = (SimpleString*) malloc(sizeof(SimpleString));
  if (*dest == NULL) {
    exit(EXIT_FAILURE);
  }
  (*dest)->length = strlen(word);
  (*dest)->word = (char*) malloc(sizeof(char) * ((*dest)->length + 1));
  if (((*dest)->word) == NULL) {
    exit(EXIT_FAILURE);
  }
  strncpy((*dest)->word, word, (*dest)->length + 1);
}