funkalicious 0.1

matdb-dotcode.c File Reference

#include <stdio.h>
#include <math.h>
#include <strings.h>
#include <stdlib.h>
#include <glib-2.0/glib.h>
#include "config.h"
#include <libdotcode/matdb.h>
#include <libdotcode/matdb-dotcode.h>
Include dependency graph for matdb-dotcode.c:

Go to the source code of this file.

Defines

#define GERROR_DOMAIN_MATDB_DOTCODE   4096

Functions

ssize_t getline (char **lineptr, size_t *n, FILE *stream)
static void destroy_string (gpointer data)
static void destroy_double (gpointer data)
static void destroy_inner_bowhash (gpointer data)
int insert_into_matdb (struct matdb *mdb, struct matdb_material **mat, struct matdb_bowing **bow)
static void prettify_line (char *line)
struct matdbread_matdb_dotcode (const GString *name, int *err)
struct matdbread_matdb_dotcode_gio (GFile *f, GError **error)

Define Documentation

#define GERROR_DOMAIN_MATDB_DOTCODE   4096

Definition at line 29 of file matdb-dotcode.c.

Referenced by read_matdb_dotcode_gio().


Function Documentation

static void destroy_double ( gpointer  data) [static]

Definition at line 60 of file matdb-dotcode.c.

Referenced by read_matdb_dotcode(), and read_matdb_dotcode_gio().

                                         {
  free((double*)data);
}

Here is the caller graph for this function:

static void destroy_inner_bowhash ( gpointer  data) [static]

Definition at line 63 of file matdb-dotcode.c.

Referenced by insert_into_matdb().

                                                 {
  g_hash_table_unref((GHashTable*)data);
}

Here is the caller graph for this function:

static void destroy_string ( gpointer  data) [static]

Definition at line 57 of file matdb-dotcode.c.

Referenced by insert_into_matdb(), read_matdb_dotcode(), and read_matdb_dotcode_gio().

                                          {
  free((char*)data);
}

Here is the caller graph for this function:

ssize_t getline ( char **  lineptr,
size_t *  n,
FILE *  stream 
)

Definition at line 33 of file matdb-dotcode.c.

References c.

Referenced by read_matdb_dotcode().

                                                         {
  GString *s = g_string_new_len("", 4096);
  int c;
  long int i=0;
  while(((c=fgetc(stream)) != '\n') && (c!=EOF) && ((n != NULL) || (i<*n))) {
    if((*lineptr) == NULL) {
      (*lineptr)[i] = c;
    }else{
      s = g_string_append_c(s, c);
    }
    i++;
  }
  if((*lineptr) == NULL) {
    *lineptr = s->str;
    g_string_free(s, FALSE);
  }else{
    g_string_free(s, TRUE);
  }
  return i;
}

Here is the caller graph for this function:

int insert_into_matdb ( struct matdb mdb,
struct matdb_material **  mat,
struct matdb_bowing **  bow 
)

Definition at line 67 of file matdb-dotcode.c.

References matdb::bowings, destroy_inner_bowhash(), destroy_string(), and matdb::materials.

Referenced by read_matdb_dotcode(), and read_matdb_dotcode_gio().

                                                                                                 {
  if((*mat) != NULL) {
#ifdef DEBUG_2
    fprintf(stderr, "inserting material %s\n", (*mat)->name->str);
#endif
    g_hash_table_insert(mdb->materials, (gpointer)g_strdup((*mat)->name->str), (gpointer)(*mat));
    (*mat) = NULL;
  }
  if((*bow) != NULL) {
#ifdef DEBUG_2
    fprintf(stderr, "inserting bowing %s:%s\n", (*bow)->from->str, (*bow)->to->str);
#endif
    /*Inner table*/
    GHashTable *it;
    if((it=(GHashTable*)g_hash_table_lookup(mdb->bowings, (*bow)->from->str)) == NULL) {
      if((it = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_inner_bowhash)) == NULL) {
  (*bow) = NULL;
  return 1;
      }
      g_hash_table_insert(mdb->bowings, (*bow)->from->str, it);
#ifdef DEBUG_2
      fprintf(stderr, "Got new hash table (from=%s)\n", (*bow)->from->str);
#endif
    }
    g_hash_table_insert(it, (gpointer)g_strdup((*bow)->to->str), (gpointer)(*bow));
    (*bow) = NULL;
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void prettify_line ( char *  line) [static]

Definition at line 99 of file matdb-dotcode.c.

Referenced by read_matdb_dotcode(), and read_matdb_dotcode_gio().

                                      {
  register char *look;
  register char *write;
  register int in_whitespace;
  register int leading_whitespace;
  for(look=write=line, in_whitespace=0, leading_whitespace=1; *look != '\0'; look++) {
#ifdef DEBUG_2
    fprintf(stderr, " look=%d(%c) write=%d(%c) in_whitespace=%d leading_whitespace=%d: ", (look-line), *look, (write-line), *write, in_whitespace, leading_whitespace);
#endif
    if(*look == '#') {
#ifdef DEBUG_2
      fprintf(stderr, "comment\n");
#endif
      *write = '\0';
      break;
    }
    switch(*look) {
    case ' ':
    case '\n':
    case '\t':
#ifdef DEBUG_2
      fprintf(stderr, "whitespace\n");
#endif
    if((!leading_whitespace) && (!in_whitespace)) *write++ = '\t';
    in_whitespace=1;
    break;
    default:
#ifdef DEBUG_2
      fprintf(stderr, "default\n");
#endif
      *write++ = *look;
      in_whitespace=leading_whitespace=0;
    }
  }
  *write='\0';
  for(look=write=line; *look != '\0'; look++) {
    switch(*look) {
    case ' ':
    case '\n':
    case '\t':
      if(*(look+1) == '\0') {
  *look = '\0';
      }
    }
  }
}

Here is the caller graph for this function:

struct matdb* read_matdb_dotcode ( const GString *  name,
int *  err 
) [read]

Definition at line 163 of file matdb-dotcode.c.

References matdb::bowings, destroy_bowing_gpointer(), destroy_double(), destroy_material_gpointer(), destroy_string(), matdb_bowing::from, getline(), insert_into_matdb(), matdb::materials, matdb_material::name, prettify_line(), and matdb_bowing::to.

                                                                {
#ifdef DEBUG_2
  fprintf(stderr, "in read_matdb_dotcode(%s, %d)\n", name->str, *err);
#endif
  *err=0;
  struct matdb *mdb = (struct matdb*)malloc(sizeof(struct matdb));
  if(mdb == NULL) {*err = 1; return NULL;}

  double *value;
  if((mdb->materials = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_material_gpointer)) == NULL) {
    *err = 1;
    free(mdb);
    return NULL;
  }
  if((mdb->bowings = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_bowing_gpointer)) == NULL) {
    *err = 1;
    g_hash_table_unref(mdb->materials);
    free(mdb);
    return NULL;
  }
  struct matdb_material *mat = NULL;
  struct matdb_bowing *bow = NULL;
  /*Valid sections:
   * 0 (no/global section)
   * 1 (material)
   * 2 (bow)
   */
  int section=0;
  size_t n;
  char *line;
  FILE *infile = fopen(name->str, "r");
  if(infile == NULL) {
    g_hash_table_unref(mdb->materials);
    g_hash_table_unref(mdb->bowings);
    free(mdb);
    *err=2;
    return NULL;
#ifdef DEBUG_2
  }else{
    fprintf(stderr, "infile=%x\n", (unsigned int)infile);
#endif
  }
  int val;
  while(!feof(infile)) {
#ifdef DEBUG_2
    fprintf(stderr, "mat=%p(%s), bow=%p(%s:%s)\n", (void*)mat, mat?mat->name->str:"", (void*)bow, bow?bow->from->str:"", bow?bow->to->str:"");
#endif
    line=NULL;
    if((val = getline(&line, &n, infile)) == -1) {
#ifdef DEBUG_2
      fprintf(stderr, "getline returned %d\n", val);
#endif
      if(!feof(infile)) *err = 4;
      //fclose(infile);
      break;
    }
#ifdef DEBUG_2
    fprintf(stderr, "line=(%s)\n", line);
#endif
    prettify_line(line);
#ifdef DEBUG_2
    fprintf(stderr, "%d: prettified line=(%s)\n", section, line);
#endif
    if(*line == '\0') {
      free(line);
      continue;
    }
    char *i = index(line, '\t');
    if(i == NULL) {
      *err &= 8;
    }
    *i++ = '\0';
    /*At this point, we have line which stores the first word on the
      line, and i which stores the second word on the line.
    */
    char *to;
    GHashTable *ht;
#ifdef DEBUG_2
    fprintf(stderr, "part_a=(%s) part_b=(%s)\n", line, i);
#endif
    /*If we have a material or bowing underway, save it off*/
    if(strcasecmp(line, "material") == 0) {
      insert_into_matdb(mdb, &mat, &bow);
      if((mat = (struct matdb_material*)malloc(sizeof(struct matdb_material))) == NULL) {
  *err &= 32;
      }
      if((mat->name = g_string_new(i)) == NULL) {
  *err &= 32;
  free(mat);
  section=0;
  continue;
      }
      if((mat->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
  *err &= 32;
  g_string_free(mat->name, TRUE);
  free(bow);
  section=0;
  continue;
      }
#ifdef DEBUG_2
      fprintf(stderr, "new material (%s):\n", i);
#endif
      section=1;
    }else if(strcasecmp(line, "bow") == 0) {
      insert_into_matdb(mdb, &mat, &bow);
      if((bow = (struct matdb_bowing*)malloc(sizeof(struct matdb_bowing))) == NULL) {
  *err &= 128;
      }
      if((to = index(i, ':')) == NULL) {
  *err &= 1024;
  free(bow);
  section=0;
  continue;
      }
      *to++ = '\0';
      /*Same trick as before, but i now stores the from material,
  and to the to material
      */
      if((bow->from = g_string_new(i)) == NULL) {
  *err &= 128;
  free(bow);
  section=0;
  continue;
      }
      if((bow->to = g_string_new(to)) == NULL) {
  *err &= 128;
  g_string_free(bow->from, TRUE);
  free(bow);
  section=0;
  continue;
      }
      if((bow->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
  *err &= 128;
  g_string_free(bow->to, TRUE);
  g_string_free(bow->from, TRUE);
  free(bow);
  section=0;
  continue;
      }
#ifdef DEBUG_2
      fprintf(stderr, "new bowing (%s:%s):\n", i, to);
#endif
      section=2;
    }else{
#ifdef DEBUG_2
      fprintf(stderr, "\t%d/%s\t", section, line);
#endif
      /*Process a property.*/
      switch(section) {
      case 1:
#ifdef DEBUG_2
  fprintf(stderr, "(1)\t");
#endif
  ht = mat->properties;
  break;
      case 2:
#ifdef DEBUG_2
  fprintf(stderr, "(2)\t");
#endif
  ht = bow->properties;
  break;
      default:
#ifdef DEBUG
  fprintf(stderr, "(default)\t");
#endif
  *err &= 16;
  section = 0;
      }
      if(section == 0) {
#ifdef DEBUG
  fprintf(stderr, "section was 0\n");
#endif
  continue;
      }
      if((value = (double*)malloc(sizeof(double))) == NULL) {
  *err &= 2048;
#ifdef DEBUG
  fprintf(stderr, "malloc of value failed\n");
#endif
  continue;
      }
      int num;
      if((num=sscanf(i, " %lg", value)) != 1) {
  *err &= 2048;
  free(value);
#ifdef DEBUG
  fprintf(stderr, "bad sscanf to get value (scanned \"%s\", returned %d)\n", i, num);
#endif
  continue;
      }
      g_hash_table_insert(ht, g_strdup(line), value);
#ifdef DEBUG_2
      fprintf(stderr, "%g(%s)\n", *value, line);
#endif
    }
    free(line);
    line=i=to=NULL;
    value=NULL;
  }
  fclose(infile);
  insert_into_matdb(mdb, &mat, &bow);
  return mdb;
}

Here is the call graph for this function:

struct matdb* read_matdb_dotcode_gio ( GFile *  f,
GError **  error 
) [read]

Definition at line 367 of file matdb-dotcode.c.

References matdb::bowings, destroy_bowing_gpointer(), destroy_double(), destroy_material_gpointer(), destroy_string(), e, matdb_bowing::from, GERROR_DOMAIN_MATDB_DOTCODE, insert_into_matdb(), matdb::materials, matdb_material::name, prettify_line(), str, and matdb_bowing::to.

Referenced by dotcode_displ_get_matdb(), and main().

                                                               {
  char* str;
#ifdef DEBUG_2
  fprintf(stderr, "in read_matdb_dotcode_gio(%s, %p)\n", str=g_file_get_uri(f), (void*)error);
  g_free(str);
#endif
  GError *e = NULL;
  struct matdb *mdb = (struct matdb*)malloc(sizeof(struct matdb));
  if(mdb == NULL) {
    *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 1, "ERROR: failed to allocate memory for matdb structure.");
    return NULL;
  }

  double *value;
  if((mdb->materials = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_material_gpointer)) == NULL) {
    *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 1, "ERROR: failed to allocate memory for matdb->materials hash table.");
    free(mdb);
    return NULL;
  }
  if((mdb->bowings = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_bowing_gpointer)) == NULL) {
    *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 1, "ERROR: failed to allocate memory for matdb->bowings hash table.");
    g_hash_table_unref(mdb->materials);
    free(mdb);
    return NULL;
  }
  struct matdb_material *mat = NULL;
  struct matdb_bowing *bow = NULL;
  /*Valid sections:
   * 0 (no/global section)
   * 1 (material)
   * 2 (bow)
   */
  int section=0;
  char *line;
  GFileInputStream *fis = g_file_read(f, NULL, &e);
  if((fis == NULL) || (e != NULL)) {
    g_propagate_prefixed_error(error, e, "Failed to open file (%s) for reading.", str=g_file_get_uri(f));
    g_free(str);
    g_hash_table_unref(mdb->bowings);
    g_hash_table_unref(mdb->materials);
    free(mdb);
    return NULL;
  }
  GDataInputStream *dis = g_data_input_stream_new((GInputStream*)fis);
  gsize amt_read = 1;
  /*Exit condition is line is NULL*/
  while(1) {
#ifdef DEBUG_2
    fprintf(stderr, "mat=%p(%s), bow=%p(%s:%s)\n", (void*)mat, mat?mat->name->str:"", (void*)bow, bow?bow->from->str:"", bow?bow->to->str:"");
#endif
    e=NULL;
    line = g_data_input_stream_read_line(dis, &amt_read, NULL, &e);
    if(e != NULL){
#ifdef DEBUG_2
      fprintf(stderr, "Error: getline returned %d chars\n", amt_read);
#endif
      g_propagate_prefixed_error(error, e, "Failed to read a line from file (%s)", str=g_file_get_uri(f));
      g_free(str);
      g_hash_table_unref(mdb->bowings);
      g_hash_table_unref(mdb->materials);
      free(mdb);
      return NULL;
    }
    if(line == NULL) break;
    if(amt_read == 0) {
#ifdef DEBUG
      fprintf(stderr, "read zero chars in that call; line=%s", line);
#endif
      continue;
    }
#ifdef DEBUG_2
    fprintf(stderr, "line=(%s)\n", line);
#endif
    prettify_line(line);
#ifdef DEBUG_2
    fprintf(stderr, "%d: prettified line=(%s)\n", section, line);
#endif
    if(*line == '\0') {
      free(line);
      continue;
    }
    char *i = index(line, '\t');
    if(i == NULL) {
      *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 8, "There was no tab on the line (line was \"%s\")", line);
      g_hash_table_unref(mdb->bowings);
      g_hash_table_unref(mdb->materials);
      free(mdb);
      return NULL;
    }
    *i++ = '\0';
    /*At this point, we have line which stores the first word on the
      line, and i which stores the second word on the line.
    */
    char *to;
    GHashTable *ht;
#ifdef DEBUG_2
    fprintf(stderr, "part_a=(%s) part_b=(%s)\n", line, i);
#endif
    /*If we have a material or bowing underway, save it off*/
    if(strcasecmp(line, "material") == 0) {
      insert_into_matdb(mdb, &mat, &bow);
      if((mat = (struct matdb_material*)malloc(sizeof(struct matdb_material))) == NULL) {
  *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 32, "Failed to allocate memory for a new matdb material");
  g_hash_table_unref(mdb->bowings);
  g_hash_table_unref(mdb->materials);
  free(mdb);
  return NULL;
      }
      if((mat->name = g_string_new(i)) == NULL) {
  *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 32, "Failed to allocate string for material name");
  g_hash_table_unref(mdb->bowings);
  g_hash_table_unref(mdb->materials);
  free(mdb);
  return NULL;
      }
      if((mat->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
  *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 32, "Failed to allocate new properties hash for material %s", i);
  g_hash_table_unref(mdb->bowings);
  g_hash_table_unref(mdb->materials);
  free(mdb);
  return NULL;
      }
#ifdef DEBUG_2
      fprintf(stderr, "new material (%s):\n", i);
#endif
      section=1;
    }else if(strcasecmp(line, "bow") == 0) {
      insert_into_matdb(mdb, &mat, &bow);
      if((bow = (struct matdb_bowing*)malloc(sizeof(struct matdb_bowing))) == NULL) {
  *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 32, "Failed to allocate new bowing");
  g_hash_table_unref(mdb->bowings);
  g_hash_table_unref(mdb->materials);
  free(mdb);
  return NULL;
      }
      if((to = index(i, ':')) == NULL) {
  *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 1024, "Failed to allocate new bowing");
  g_hash_table_unref(mdb->bowings);
  g_hash_table_unref(mdb->materials);
  free(mdb);
  return NULL;
      }
      *to++ = '\0';
      /*Same trick as before, but i now stores the from material,
  and to the to material
      */
      if((bow->from = g_string_new(i)) == NULL) {
  *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 128, "Failed to allocate new string (for \"%s\")", i);
  g_hash_table_unref(mdb->bowings);
  g_hash_table_unref(mdb->materials);
  free(mdb);
  return NULL;
      }
      if((bow->to = g_string_new(to)) == NULL) {
  *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 128, "Failed to allocate new string (for \"%s\")", to);
  g_hash_table_unref(mdb->bowings);
  g_hash_table_unref(mdb->materials);
  free(mdb);
  return NULL;
      }
      if((bow->properties = g_hash_table_new_full(&g_str_hash, &g_str_equal, &destroy_string, &destroy_double)) == NULL) {
  *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 128, "Failed to allocate new bowing hash table for properties for material %s,%s", bow->from->str, bow->to->str);
  g_hash_table_unref(mdb->bowings);
  g_hash_table_unref(mdb->materials);
  free(mdb);
  return NULL;
      }
#ifdef DEBUG_2
      fprintf(stderr, "new bowing (%s:%s):\n", i, to);
#endif
      section=2;
    }else{
#ifdef DEBUG_2
      fprintf(stderr, "\t%d/%s\t", section, line);
#endif
      /*Process a property.*/
      switch(section) {
      case 1:
#ifdef DEBUG_2
  fprintf(stderr, "(1)\t");
#endif
  ht = mat->properties;
  break;
      case 2:
#ifdef DEBUG_2
  fprintf(stderr, "(2)\t");
#endif
  ht = bow->properties;
  break;
      default:
#ifdef DEBUG
  fprintf(stderr, "(default)\t");
#endif
  *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 16, "Invalid section index (%d)\n", section);
  g_hash_table_unref(mdb->bowings);
  g_hash_table_unref(mdb->materials);
  free(mdb);
  return NULL;
      }
      if(section == 0) {
#ifdef DEBUG_2
  fprintf(stderr, "section was 0\n");
#endif
  continue;
      }
      if((value = (double*)malloc(sizeof(double))) == NULL) {
  *error = g_error_new(GERROR_DOMAIN_MATDB_DOTCODE, 2048, "Malloc of value failed");
  g_hash_table_unref(mdb->bowings);
  g_hash_table_unref(mdb->materials);
  free(mdb);
  return NULL;
#ifdef DEBUG
  fprintf(stderr, "malloc of value failed\n");
#endif
  continue;
      }
      int num;
      if((num=sscanf(i, " %lg", value)) != 1) {
  /*Invalid values are used to insert NaNs*/
  num=nan("NaN");
#ifdef DEBUG
  fprintf(stderr, "bad sscanf to get value (scanned \"%s\", returned %d; using NaN)\n", i, num);
#endif
      }
      g_hash_table_insert(ht, g_strdup(line), value);
#ifdef DEBUG_2
      fprintf(stderr, "%g(%s)\n", *value, line);
#endif
    }
    free(line);
    line=i=to=NULL;
    value=NULL;
  }
#ifdef DEBUG_2
  fprintf(stderr, "amt_read=%lu", (long unsigned int)amt_read);
#endif
  g_input_stream_close((GInputStream*)fis, NULL, &e);
  if(e != NULL) {
    g_propagate_prefixed_error(error, e, "Error closing file (%s):", str=g_file_get_uri(f));
    g_free(str);
  }
  insert_into_matdb(mdb, &mat, &bow);
  return mdb;
}

Here is the call graph for this function:

Here is the caller graph for this function:

 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines