Cleanup by breaking up C impl to separate sources
This commit is contained in:
parent
2660e765c3
commit
cd2ecb5c8f
8 changed files with 245 additions and 183 deletions
|
@ -6,7 +6,10 @@ else
|
|||
endif
|
||||
|
||||
SOURCES = \
|
||||
src/main.o
|
||||
src/main.o \
|
||||
src/argparse.o \
|
||||
src/csventry.o \
|
||||
src/strdlist.o
|
||||
|
||||
all: fields_from_csv
|
||||
|
||||
|
|
33
c_impl/src/argparse.c
Normal file
33
c_impl/src/argparse.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "argparse.h"
|
||||
|
||||
ParsedArgs parse_args(int argc, char **argv) {
|
||||
// init
|
||||
ParsedArgs args;
|
||||
args.input_filename = NULL;
|
||||
args.fields = create_strdlist();
|
||||
args.usage_print = 0;
|
||||
args.error = 0;
|
||||
|
||||
--argc;
|
||||
++argv;
|
||||
|
||||
// get filename and field from args
|
||||
if (argc > 1) {
|
||||
args.input_filename = argv[0];
|
||||
} else {
|
||||
args.error = 1;
|
||||
args.usage_print = 1;
|
||||
}
|
||||
|
||||
--argc;
|
||||
++argv;
|
||||
|
||||
while (argc > 0) {
|
||||
append_strdlist(args.fields, argv[0]);
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
// vim: et: ts=2: sts=2: sw=2
|
16
c_impl/src/argparse.h
Normal file
16
c_impl/src/argparse.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef SEODISPARATE_FIELDS_FROM_CSV_ARG_PARSE_H_
|
||||
#define SEODISPARATE_FIELDS_FROM_CSV_ARG_PARSE_H_
|
||||
|
||||
#include "strdlist.h"
|
||||
|
||||
typedef struct ParsedArgs {
|
||||
const char *input_filename;
|
||||
StrDList *fields;
|
||||
int usage_print;
|
||||
int error;
|
||||
} ParsedArgs;
|
||||
|
||||
ParsedArgs parse_args(int argc, char **argv);
|
||||
|
||||
#endif
|
||||
// vim: et: ts=2: sts=2: sw=2
|
64
c_impl/src/csventry.c
Normal file
64
c_impl/src/csventry.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include "csventry.h"
|
||||
|
||||
CSVEntry get_field(FILE *fd, size_t field_idx) {
|
||||
size_t current_size = 512;
|
||||
CSVEntry entry;
|
||||
entry.is_end_of_line = 0;
|
||||
entry.is_end_of_file = 0;
|
||||
entry.is_chosen_field = 0;
|
||||
entry.buf = NULL;
|
||||
size_t idx = 0;
|
||||
int next = fgetc(fd);
|
||||
|
||||
while (next != EOF) {
|
||||
if (next == ',') {
|
||||
break;
|
||||
} else if (next == '\n') {
|
||||
entry.is_end_of_line = 1;
|
||||
break;
|
||||
} else if (next == ' ' || next == '\t') {
|
||||
next = fgetc(fd);
|
||||
continue;
|
||||
}
|
||||
if (!entry.buf) {
|
||||
// malloc of buf deferred to here in case a field reaches EOF
|
||||
entry.buf = malloc(current_size);
|
||||
}
|
||||
entry.buf[idx++] = next;
|
||||
if (idx >= current_size) {
|
||||
current_size *= 2;
|
||||
entry.buf = realloc(entry.buf, current_size);
|
||||
}
|
||||
|
||||
next = fgetc(fd);
|
||||
}
|
||||
|
||||
if (next == EOF) {
|
||||
entry.is_end_of_file = 1;
|
||||
}
|
||||
|
||||
if (entry.buf) {
|
||||
if (idx >= current_size) {
|
||||
current_size += 1;
|
||||
entry.buf = realloc(entry.buf, current_size);
|
||||
entry.buf[idx] = 0;
|
||||
} else {
|
||||
entry.buf[idx] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
entry.idx = field_idx;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
void cleanup_csventry(CSVEntry *csvEntry, int nullify) {
|
||||
if (csvEntry->buf) {
|
||||
free(csvEntry->buf);
|
||||
}
|
||||
if (nullify) {
|
||||
csvEntry->buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et: ts=2: sts=2: sw=2
|
19
c_impl/src/csventry.h
Normal file
19
c_impl/src/csventry.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef SEODISPARATE_FIELDS_FROM_CSV_CSVENTRY_H_
|
||||
#define SEODISPARATE_FIELDS_FROM_CSV_CSVENTRY_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct CSVEntry {
|
||||
char *buf;
|
||||
size_t idx;
|
||||
int is_end_of_line;
|
||||
int is_end_of_file;
|
||||
int is_chosen_field;
|
||||
} CSVEntry;
|
||||
|
||||
CSVEntry get_field(FILE *fd, size_t field_idx);
|
||||
void cleanup_csventry(CSVEntry *csvEntry, int nullify);
|
||||
|
||||
#endif
|
||||
// vim: et: ts=2: sts=2: sw=2
|
|
@ -2,18 +2,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct StrDList {
|
||||
char *string;
|
||||
struct StrDList *next;
|
||||
struct StrDList *prev;
|
||||
} StrDList;
|
||||
|
||||
typedef struct ParsedArgs {
|
||||
const char *input_filename;
|
||||
StrDList *fields;
|
||||
int usage_printed;
|
||||
int error;
|
||||
} ParsedArgs;
|
||||
#include "argparse.h"
|
||||
#include "csventry.h"
|
||||
#include "strdlist.h"
|
||||
|
||||
void usage() {
|
||||
puts(
|
||||
|
@ -21,176 +12,14 @@ void usage() {
|
|||
"./fields_from_csv <input_csv> <field> [<field>...]\n");
|
||||
}
|
||||
|
||||
StrDList *create_strdlist() { return calloc(1, sizeof(StrDList)); }
|
||||
|
||||
void append_strdlist(StrDList *head, const char *string) {
|
||||
StrDList *current = head;
|
||||
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
current->next = calloc(1, sizeof(StrDList));
|
||||
current->next->prev = current;
|
||||
size_t string_size = strlen(string);
|
||||
current->next->string = malloc(string_size + 1);
|
||||
memcpy(current->next->string, string, string_size);
|
||||
current->next->string[string_size] = 0;
|
||||
}
|
||||
|
||||
void cleanup_strdlist(StrDList **head) {
|
||||
if (!head || !*head) {
|
||||
return;
|
||||
}
|
||||
|
||||
StrDList *current = *head;
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
while (current->prev) {
|
||||
current = current->prev;
|
||||
if (current->next->string) {
|
||||
free(current->next->string);
|
||||
}
|
||||
free(current->next);
|
||||
current->next = NULL;
|
||||
}
|
||||
|
||||
(*head)->next = NULL;
|
||||
|
||||
free(*head);
|
||||
*head = NULL;
|
||||
}
|
||||
|
||||
size_t print_and_count_strdlist(StrDList *head) {
|
||||
size_t count = 0;
|
||||
StrDList *current = head;
|
||||
puts("Printing strdlist...");
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
printf("%s ", current->string);
|
||||
++count;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int strdlist_has_str(StrDList *head, const char *str) {
|
||||
StrDList *current = head;
|
||||
int idx = 0;
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
if (strcmp(current->string, str) == 0) {
|
||||
return idx;
|
||||
} else {
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ParsedArgs parse_args(int argc, char **argv) {
|
||||
// init
|
||||
ParsedArgs args;
|
||||
args.input_filename = NULL;
|
||||
args.fields = create_strdlist();
|
||||
args.usage_printed = 0;
|
||||
args.error = 0;
|
||||
|
||||
--argc;
|
||||
++argv;
|
||||
|
||||
// get filename and field from args
|
||||
if (argc > 1) {
|
||||
args.input_filename = argv[0];
|
||||
} else {
|
||||
args.error = 1;
|
||||
usage();
|
||||
args.usage_printed = 1;
|
||||
}
|
||||
|
||||
--argc;
|
||||
++argv;
|
||||
|
||||
while (argc > 0) {
|
||||
append_strdlist(args.fields, argv[0]);
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
typedef struct CSVEntry {
|
||||
char *buf;
|
||||
size_t idx;
|
||||
int is_end_of_line;
|
||||
int is_end_of_file;
|
||||
int is_chosen_field;
|
||||
} CSVEntry;
|
||||
|
||||
CSVEntry get_field(FILE *fd, size_t field_idx) {
|
||||
size_t current_size = 512;
|
||||
CSVEntry entry;
|
||||
entry.is_end_of_line = 0;
|
||||
entry.is_end_of_file = 0;
|
||||
entry.is_chosen_field = 0;
|
||||
entry.buf = NULL;
|
||||
size_t idx = 0;
|
||||
int next = fgetc(fd);
|
||||
|
||||
while (next != EOF) {
|
||||
if (next == ',') {
|
||||
break;
|
||||
} else if (next == '\n') {
|
||||
entry.is_end_of_line = 1;
|
||||
break;
|
||||
} else if (next == ' ' || next == '\t') {
|
||||
next = fgetc(fd);
|
||||
continue;
|
||||
}
|
||||
if (!entry.buf) {
|
||||
// malloc of buf deferred to here in case a field reaches EOF
|
||||
entry.buf = malloc(current_size);
|
||||
}
|
||||
entry.buf[idx++] = next;
|
||||
if (idx >= current_size) {
|
||||
current_size *= 2;
|
||||
entry.buf = realloc(entry.buf, current_size);
|
||||
}
|
||||
|
||||
next = fgetc(fd);
|
||||
}
|
||||
|
||||
if (next == EOF) {
|
||||
entry.is_end_of_file = 1;
|
||||
}
|
||||
|
||||
if (entry.buf) {
|
||||
if (idx >= current_size) {
|
||||
current_size += 1;
|
||||
entry.buf = realloc(entry.buf, current_size);
|
||||
entry.buf[idx] = 0;
|
||||
} else {
|
||||
entry.buf[idx] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
entry.idx = field_idx;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
ParsedArgs args = parse_args(argc, argv);
|
||||
|
||||
if (args.error) {
|
||||
cleanup_strdlist(&args.fields);
|
||||
return 1;
|
||||
} else if (args.usage_printed) {
|
||||
} else if (args.usage_print) {
|
||||
usage();
|
||||
cleanup_strdlist(&args.fields);
|
||||
return 0;
|
||||
}
|
||||
|
@ -242,9 +71,7 @@ int main(int argc, char **argv) {
|
|||
printf("%s, ", entry.buf);
|
||||
}
|
||||
|
||||
if (entry.buf) {
|
||||
free(entry.buf);
|
||||
}
|
||||
cleanup_csventry(&entry, 1);
|
||||
|
||||
if (entry.is_end_of_file) {
|
||||
break;
|
||||
|
@ -258,11 +85,11 @@ int main(int argc, char **argv) {
|
|||
|
||||
fclose(csv_fd);
|
||||
for (size_t i = 0; i < number_of_entries; ++i) {
|
||||
if (entries[i].buf) {
|
||||
free(entries[i].buf);
|
||||
}
|
||||
cleanup_csventry(entries + i, 0);
|
||||
}
|
||||
free(entries);
|
||||
cleanup_strdlist(&args.fields);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: et: ts=2: sts=2: sw=2
|
||||
|
|
77
c_impl/src/strdlist.c
Normal file
77
c_impl/src/strdlist.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include "strdlist.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
StrDList *create_strdlist() { return calloc(1, sizeof(StrDList)); }
|
||||
|
||||
void append_strdlist(StrDList *head, const char *string) {
|
||||
StrDList *current = head;
|
||||
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
current->next = calloc(1, sizeof(StrDList));
|
||||
current->next->prev = current;
|
||||
size_t string_size = strlen(string);
|
||||
current->next->string = malloc(string_size + 1);
|
||||
memcpy(current->next->string, string, string_size);
|
||||
current->next->string[string_size] = 0;
|
||||
}
|
||||
|
||||
void cleanup_strdlist(StrDList **head) {
|
||||
if (!head || !*head) {
|
||||
return;
|
||||
}
|
||||
|
||||
StrDList *current = *head;
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
while (current->prev) {
|
||||
current = current->prev;
|
||||
if (current->next->string) {
|
||||
free(current->next->string);
|
||||
}
|
||||
free(current->next);
|
||||
current->next = NULL;
|
||||
}
|
||||
|
||||
(*head)->next = NULL;
|
||||
|
||||
free(*head);
|
||||
*head = NULL;
|
||||
}
|
||||
|
||||
size_t print_and_count_strdlist(StrDList *head) {
|
||||
size_t count = 0;
|
||||
StrDList *current = head;
|
||||
puts("Printing strdlist...");
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
printf("%s ", current->string);
|
||||
++count;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int strdlist_has_str(StrDList *head, const char *str) {
|
||||
StrDList *current = head;
|
||||
int idx = 0;
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
if (strcmp(current->string, str) == 0) {
|
||||
return idx;
|
||||
} else {
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// vim: et: ts=2: sts=2: sw=2
|
23
c_impl/src/strdlist.h
Normal file
23
c_impl/src/strdlist.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef SEODISPARATE_FIELDS_FROM_CSV_STRDLIST_H_
|
||||
#define SEODISPARATE_FIELDS_FROM_CSV_STRDLIST_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct StrDList {
|
||||
char *string;
|
||||
struct StrDList *next;
|
||||
struct StrDList *prev;
|
||||
} StrDList;
|
||||
|
||||
StrDList *create_strdlist();
|
||||
|
||||
void append_strdlist(StrDList *head, const char *string);
|
||||
|
||||
void cleanup_strdlist(StrDList **head);
|
||||
|
||||
size_t print_and_count_strdlist(StrDList *head);
|
||||
|
||||
int strdlist_has_str(StrDList *head, const char *str);
|
||||
|
||||
#endif
|
||||
// vim: et: ts=2: sts=2: sw=2
|
Loading…
Reference in a new issue