6 Mar 2013

Reading file with dynamic memmory allocation in C

/*
 Will read a file from disk while dynamically allocating memory.

 Example usage: ./exe [file-name]
 */

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

typedef struct string_t {
 int memsize;
 int length;
 char *text;
 int error;
};
typedef struct string_t string;

string redfile(FILE *file);
void str_dump(string *s);

string redfile(FILE *file) {
 int charsize = sizeof(char);
 int charcount = 0;
 int blocksize = 10;
 int memsize = blocksize;
 char *line = (char*) malloc(charsize * (memsize+1));
 char *linep = line;

 string l;
 l.error = 0;
 l.length = 0;
 l.memsize = memsize;
 l.length = charcount;
 l.text = linep;

 while (1) {

  if(charcount > memsize) {
   // reallocate memmory
   memsize = memsize+blocksize;
   char *al = realloc(linep, charsize * (memsize+1));

   if (al == NULL) {
    fprintf(stderr, "Error, out of memory.\n");
    *line = '\0';
    l.text = linep;
    l.error = 1;
    return l;
   }
  }

  char c = fgetc(file);

  //if (c == '\n' || c == '\r' || c == EOF) {
  if (c == EOF) {
   charcount--;
   break;
  }

  // remember input char
  *line = c;
  *(line++);
  charcount++;
 }

 *line = '\0';
 l.text = linep;
 l.memsize = memsize;
 l.length = charcount;

 return l;
}

void str_dump(string *s) {
 if (s->error == 0) {
  printf("memsize: %d\n", s->memsize);
  printf("length:  %d\n", s->length);
  printf("error:   %d\n", s->error);
  printf("text:    %s\n", s->text);
  printf("total:   %lu\n", sizeof(*s)+1);
 } else
  printf("Error: %d.\n", s->error);
}

int main(int argc, char **argv) {
 // string l = redfile(stdin);

 if(argc < 2) {
  fprintf(stderr, "Usage: %s [file]\n", argv[0]);
  exit(1);
 }

 FILE *f = fopen(argv[1], "r");
 if (f == NULL) {
  fprintf(stderr, "Error: failed to open file: %s\n", argv[1]);
  exit(2);
 }

 string l = redfile(f);

 if (l.error != 0) {
  fprintf(stderr, "Error: redfile() error: '%d'\n", l.error);
  fclose(f);
  exit(l.error);
 }

 str_dump(&l);

 fclose(f);

 exit(0);
}