Parse common part of header and accept other years.
[cascardo/rnetclient.git] / decfile.c
index be30687..bc2a2ea 100644 (file)
--- a/decfile.c
+++ b/decfile.c
@@ -74,6 +74,7 @@ static void decfile_release_lines(struct rnet_decfile *decfile)
 }
 
 static char * get_header(struct rnet_decfile *decfile);
+static int parse_header_common(struct pmhash *hash, char **buffer);
 static int parse_header_2013(struct pmhash *hash, char *buffer);
 static int parse_header_2014(struct pmhash *hash, char *buffer);
 static int parse_header_2015(struct pmhash *hash, char *buffer);
@@ -81,19 +82,29 @@ static int decfile_parse_file(struct rnet_decfile *decfile);
 
 static int decfile_parse_header(struct rnet_decfile *decfile)
 {
-       char *buffer = get_header(decfile);
+       char *buffer;
+       int r;
+       char *p;
+
+       p = buffer = get_header(decfile);
        if (!buffer)
                return -EINVAL;
+
+       r = parse_header_common(decfile->header, &p);
+       if (r)
+               return r;
+
        switch (strlen(buffer)) {
        case RNET_HEADER_SIZE_2013:
-               return parse_header_2013(decfile->header, buffer);
+               return parse_header_2013(decfile->header, p);
        case RNET_HEADER_SIZE_2014:
-               return parse_header_2014(decfile->header, buffer);
+               return parse_header_2014(decfile->header, p);
        case RNET_HEADER_SIZE_2015:
-               return parse_header_2015(decfile->header, buffer);
+               return parse_header_2015(decfile->header, p);
        default:
-               return -EINVAL;
+               fprintf(stderr, "Unknown file version, but proceeding anyway.\n");
        }
+       return 0;
 }
 
 static int decfile_parse(struct rnet_decfile *decfile)
@@ -174,14 +185,6 @@ static char * get_header(struct rnet_decfile *decfile)
        return NULL;
 }
 
-static int parse_header_2015(struct pmhash *hash, char *buffer)
-{
-       int r;
-       char *p = buffer;
-       char *key;
-       char *val;
-       char *tail;
-
 #define parse(field, sz) \
        r = -ENOMEM; \
        val = malloc(sz + 1); \
@@ -196,12 +199,15 @@ static int parse_header_2015(struct pmhash *hash, char *buffer)
        if (pmhash_add(&hash, key, val)) \
                goto out_add;
 
+static int parse_header_common(struct pmhash *hash, char **buffer)
+{
+       int r;
+       char *p = *buffer;
+       char *key;
+       char *val;
+
        parse("sistema", 8);
        parse("exerc", 4);
-       if (strcmp(val, "2015")) {
-               r = -EINVAL;
-               goto out_val;
-       }
        parse("ano", 4);
        parse("codigo_recnet", 4);
        parse("in_ret", 1);
@@ -213,8 +219,34 @@ static int parse_header_2015(struct pmhash *hash, char *buffer)
        parse("uf", 2);
        parse("hash", 10);
 
-       if (p - buffer != RNET_HEADER_HEAD_2015) {
-               fprintf(stderr, "RNET_HEADER_HEAD_2015 in decfile.h needs to be adjusted to %ti\n", p - buffer);
+       if (p - *buffer != RNET_HEADER_HEAD_COMMON) {
+               fprintf(stderr, "RNET_HEADER_HEAD_COMMON in decfile.h needs to be adjusted to %ti\n", p - *buffer);
+               goto out_val;
+       }
+
+       *buffer = p;
+
+       return 0;
+out_add:
+       free(key);
+out_key:
+       free(val);
+out_val:
+       return r;
+}
+
+static int parse_header_2015(struct pmhash *hash, char *buffer)
+{
+       int r;
+       char *p = buffer;
+       char *key;
+       char *val;
+       char *tail;
+       char *exerc;
+
+       exerc = pmhash_get(hash, "exerc");
+       if (strcmp(exerc, "2015")) {
+               r = -EINVAL;
                goto out_val;
        }
 
@@ -331,8 +363,8 @@ static int parse_header_2015(struct pmhash *hash, char *buffer)
        } else if (p - buffer != RNET_HEADER_SIZE_2015) {
                fprintf(stderr, "RNET_HEADER_SIZE_2015 in decfile.h needs to be adjusted to %ti,\nor parse_header in decfile.c needs updating\n", p - buffer);
                goto out_val;
-       } else if (p - tail != RNET_HEADER_TAIL_2015) {
-               fprintf(stderr, "RNET_HEADER_TAIL_2015 in decfile.h needs to be adjusted to %ti\n", p - tail);
+       } else if (p - tail != RNET_HEADER_TAIL_COMMON) {
+               fprintf(stderr, "RNET_HEADER_TAIL_COMMON in decfile.h needs to be adjusted to %ti\n", p - tail);
                goto out_val;
        }
 
@@ -352,42 +384,13 @@ static int parse_header_2014(struct pmhash *hash, char *buffer)
        char *key;
        char *val;
        char *tail;
+       char *exerc;
 
-#define parse(field, sz) \
-       r = -ENOMEM; \
-       val = malloc(sz + 1); \
-       if (!val) \
-               goto out_val; \
-       val[sz] = 0; \
-       memcpy(val, p, sz); \
-       p += sz; \
-       key = strdup(field); \
-       if (!key) \
-               goto out_key; \
-       if (pmhash_add(&hash, key, val)) \
-               goto out_add;
-
-       parse("sistema", 8);
-       parse("exerc", 4);
-       if (strcmp(val, "2014")) {
+       exerc = pmhash_get(hash, "exerc");
+       if (strcmp(exerc, "2014")) {
                r = -EINVAL;
                goto out_val;
        }
-       parse("ano", 4);
-       parse("codigo_recnet", 4);
-       parse("in_ret", 1);
-       parse("cpf", 11);
-       parse("filler", 3);
-       parse("tipo_ni", 1);
-       parse("nr_versao", 3);
-       parse("nome", 60);
-       parse("uf", 2);
-       parse("hash", 10);
-
-       if (p - buffer != RNET_HEADER_HEAD_2014) {
-               fprintf(stderr, "RNET_HEADER_HEAD_2014 in decfile.h needs to be adjusted to %ti\n", p - buffer);
-               goto out_val;
-       }
 
        parse("in_cert", 1);
        parse("dt_nasc", 8);
@@ -485,8 +488,8 @@ static int parse_header_2014(struct pmhash *hash, char *buffer)
        } else if (p - buffer != RNET_HEADER_SIZE_2014) {
                fprintf(stderr, "RNET_HEADER_SIZE_2014 in decfile.h needs to be adjusted to %ti,\nor parse_header in decfile.c needs updating\n", p - buffer);
                goto out_val;
-       } else if (p - tail != RNET_HEADER_TAIL_2014) {
-               fprintf(stderr, "RNET_HEADER_TAIL_2014 in decfile.h needs to be adjusted to %ti\n", p - tail);
+       } else if (p - tail != RNET_HEADER_TAIL_COMMON) {
+               fprintf(stderr, "RNET_HEADER_TAIL_COMMON in decfile.h needs to be adjusted to %ti\n", p - tail);
                goto out_val;
        }
 
@@ -506,42 +509,13 @@ static int parse_header_2013(struct pmhash *hash, char *buffer)
        char *key;
        char *val;
        char *tail;
+       char *exerc;
 
-#define parse(field, sz) \
-       r = -ENOMEM; \
-       val = malloc(sz + 1); \
-       if (!val) \
-               goto out_val; \
-       val[sz] = 0; \
-       memcpy(val, p, sz); \
-       p += sz; \
-       key = strdup(field); \
-       if (!key) \
-               goto out_key; \
-       if (pmhash_add(&hash, key, val)) \
-               goto out_add;
-
-       parse("sistema", 8);
-       parse("exerc", 4);
-       if (strcmp(val, "2013")) {
+       exerc = pmhash_get(hash, "exerc");
+       if (strcmp(exerc, "2013")) {
                r = -EINVAL;
                goto out_val;
        }
-       parse("ano", 4);
-       parse("codigo_recnet", 4);
-       parse("in_ret", 1);
-       parse("cpf", 11);
-       parse("filler", 3);
-       parse("tipo_ni", 1);
-       parse("nr_versao", 3);
-       parse("nome", 60);
-       parse("uf", 2);
-       parse("hash", 10);
-
-       if (p - buffer != RNET_HEADER_HEAD_2013) {
-               fprintf(stderr, "RNET_HEADER_HEAD_2013 in decfile.h needs to be adjusted to %ti\n", p - buffer);
-               goto out_val;
-       }
 
        parse("in_cert", 1);
        parse("dt_nasc", 8);
@@ -634,8 +608,8 @@ static int parse_header_2013(struct pmhash *hash, char *buffer)
        } else if (p - buffer != RNET_HEADER_SIZE_2013) {
                fprintf(stderr, "RNET_HEADER_SIZE_2013 in decfile.h needs to be adjusted to %ti,\nor parse_header in decfile.c needs updating\n", p - buffer);
                goto out_val;
-       } else if (p - tail != RNET_HEADER_TAIL_2013) {
-               fprintf(stderr, "RNET_HEADER_TAIL_2013 in decfile.h needs to be adjusted to %ti\n", p - tail);
+       } else if (p - tail != RNET_HEADER_TAIL_COMMON) {
+               fprintf(stderr, "RNET_HEADER_TAIL_COMMON in decfile.h needs to be adjusted to %ti\n", p - tail);
                goto out_val;
        }
 
@@ -648,6 +622,8 @@ out_val:
        return r;
 }
 
+#undef parse
+
 char *rnet_decfile_get_header_field(struct rnet_decfile *decfile, char *field)
 {
        return pmhash_get(decfile->header, field);