#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>

#include "parse.h"
#include "dm.h"
#include "dm_globals.h"

// functions in this file
//void str2upper(char *text);
//void cCreateMatrix(char ***m, int a, int b);
//void cFreeMatrix(char **m, int a);
//void free_db_row(struct db_row *row);
//void get_column_info(struct db_row *row, char *heading_name, char *out);

// method: str2upper
//
// arguments:
//  char *text: (input\output) pointer of string to change
//
// return: none.
//
// uses no global variables
// this function will start at *text, and go until the null char converting
// all characters to uppercase using toupper().
//
void str2upper(char *text) {

  // Error checking
  //
  if (!text)
    return;

  // For each character until *c == 0
  //
  char *c = text;
  for (;*c;c++)
    *c = toupper(*c); 
}

// method: cCreateMatrix
//
// arguments:
//  char ***m: (input\output) pointer to a 2-dim pointer
//  int a: (input) number of first dim
//  int b: (input) number of second dim
//
// return: none. will exit(0) on failure.
//
// uses no global variables
// creates a 2 dimensional array. pass in a pointer to a char **.
//
void cCreateMatrix(char ***m, int a, int b) {
  
  int i;

  // Simple error checking
  if (m == NULL || a == 0 || b == 0) {
    return;
  }

  // create first array dim
  //
  *m = (char **) malloc( sizeof(char **) * a );
  if (!*m) {
    printf("in cCreateMatrix: Unable to allocate "
	   "memory for a=%i b=%i items\n", a,b);
    fflush(stdout);
    exit(0);
  }
  // for each element in first dim, create the second dim
  //
  for (i = 0; i < a; i++){
    (*m)[i] = (char *) malloc( sizeof(char) * b );
    if (!((*m)[i])) {
      printf("in cCreateMatrix: P2: Unable to allocate "
	     "memory for a=%i b=%i items\n", a,b);
      fflush(stdout);
      exit(0);
    }
  }
}

// method: cFreeMatrix
//
// arguments:
//  char **m: (input\output) 2-dim pointer
//  int a: (input) number of elements in 2nd dim. (same as b above)
//
// return: none. will exit(0) on failure.
//
// uses no global variables
// destroys each 2nd dim array, then the first dim array. Must remember that
// the original pointer when passed in will still point to some location in
// memory. if access is attempted again will segfault.
//
void cFreeMatrix(char **m, int a) {

  for (int i = 0; i < a; i++)
    free(m[i]);
  
  free(m);
}

// method: free_db_row
//
// arguments:
//  struct db_row *row: (input) struct to erase allocation
//
// return: none. 
//
// uses no global variables
// destroys the db_row struct passed in. Original pointer passed in will need
// to be set to null because it will still point somewhere.
//
void free_db_row(struct db_row *row) {
  
  cFreeMatrix(row->headings, MAX_COLS);
  cFreeMatrix(row->item, MAX_COLS);
  free(row);
}

// method: get_column_info
//
// arguments:
//  struct db_row *row: (input) struct that contains data
//  char *heading_name: (input) name of heading we are looking for in the
//                      parallel arrays of the struct
//  char *out: (output) the data contained in the same index as the header
//
// return: none. 
//
// uses no global variables
// destroys the db_row struct passed in. Original pointer passed in will need
// to be set to null because it will still point somewhere. The data is blindly
// copied into the output buffer so no check on buffer bounds is performed.
//
void get_column_info(struct db_row *row, char *heading_name, char *out) {
  int index;

  // For each of the columns, look for a specific heading
  //
  for(index = 0; index < row->num_cols; index++)
    if (!strcmp(row->headings[index], heading_name))
      break;

  // if index is >=, we didn't find it
  //
  if (index >= row->num_cols)
    out[0] = '\0';
  // else we did find it, so copy it blindly with no size-check
  //
  else
    strcpy(out, row->item[index]);
}

