Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions csv_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ CSVParseResult csv_parse_line_inplace(const char *line, Arena *arena, const CSVC
return result;
}

char* read_full_record(FILE *file, Arena *arena) {
char* read_full_record(FILE *file, Arena *arena, const CSVConfig *config) {
if (!file || !arena) {
return NULL;
}
Expand Down Expand Up @@ -251,22 +251,22 @@ char* read_full_record(FILE *file, Arena *arena) {
record_capacity = new_capacity;
}

if (c == '"') {
if (c == config->enclosure) {
if (in_quotes) {
int next_c = fgetc(file);
if (next_c == '"') {
record[record_len++] = '"';
record[record_len++] = '"';
if (next_c == config->enclosure) {
record[record_len++] = config->enclosure;
record[record_len++] = config->enclosure;
} else {
record[record_len++] = '"';
record[record_len++] = config->enclosure;
in_quotes = false;
if (next_c != EOF) {
ungetc(next_c, file);
}
}
} else {
in_quotes = true;
record[record_len++] = '"';
record[record_len++] = config->enclosure;
}
} else if (c == '\n' || c == '\r') {
if (!in_quotes) {
Expand Down
2 changes: 1 addition & 1 deletion csv_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ typedef struct {
ParseContext parse_ctx;
} CSVParser;

char* read_full_record(FILE *file, Arena *arena);
char* read_full_record(FILE *file, Arena *arena, const CSVConfig *config);
int parse_csv_line(const char *line, char **fields, int max_fields, Arena *arena, const CSVConfig *config);
int parse_headers(const char *line, char **fields, int max_fields, Arena *arena, const CSVConfig *config);

Expand Down
28 changes: 14 additions & 14 deletions csv_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ CSVReader* csv_reader_init_with_config(Arena *persistent_arena, Arena *temp_aren
reader->owns_arenas = false;

if (config->hasHeader) {
char *line = read_full_record(reader->file, reader->persistent_arena);
char *line = read_full_record(reader->file, reader->persistent_arena, config);
if (line) {
reader->line_number++;
CSVParseResult result = csv_parse_line_inplace(line, reader->persistent_arena, config, reader->line_number);
Expand Down Expand Up @@ -99,7 +99,7 @@ CSVReader* csv_reader_init_standalone(CSVConfig *config) {
reader->owns_arenas = true;

if (config->hasHeader) {
char *line = read_full_record(reader->file, reader->persistent_arena);
char *line = read_full_record(reader->file, reader->persistent_arena, config);
if (line) {
reader->line_number++;
CSVParseResult result = csv_parse_line_inplace(line, reader->persistent_arena, config, reader->line_number);
Expand All @@ -114,14 +114,14 @@ CSVReader* csv_reader_init_standalone(CSVConfig *config) {
return reader;
}

CSVRecord* csv_reader_next_record(CSVReader *reader) {
CSVRecord* csv_reader_next_record(CSVReader *reader, CSVConfig *config) {
if (!reader || !reader->file) {
return NULL;
}

arena_reset(reader->temp_arena);

char *line = read_full_record(reader->file, reader->temp_arena);
char *line = read_full_record(reader->file, reader->temp_arena, config);
if (!line) {
return NULL;
}
Expand Down Expand Up @@ -191,13 +191,13 @@ char** csv_reader_get_headers(CSVReader *reader, int *header_count) {
return NULL;
}

void csv_reader_rewind(CSVReader *reader) {
void csv_reader_rewind(CSVReader *reader, CSVConfig *config) {
if (reader && reader->file) {
rewind(reader->file);
reader->line_number = 0;

if (reader->config->hasHeader && reader->headers_loaded) {
char *line = read_full_record(reader->file, reader->persistent_arena);
char *line = read_full_record(reader->file, reader->persistent_arena, config);
if (line) {
reader->line_number = 1;
}
Expand All @@ -216,8 +216,8 @@ int csv_reader_set_config(CSVReader *reader, Arena *persistent_arena, Arena *tem
return 1;
}

long csv_reader_get_record_count(CSVReader *reader) {
if (!reader || !reader->file) {
long csv_reader_get_record_count(CSVReader *reader, CSVConfig *config) {
if (!reader || !reader->file || !config) {
return -1;
}

Expand All @@ -231,15 +231,15 @@ long csv_reader_get_record_count(CSVReader *reader) {
long record_count = 0;

if (reader->config && reader->config->hasHeader) {
char *header_line = read_full_record(reader->file, reader->persistent_arena);
char *header_line = read_full_record(reader->file, reader->persistent_arena, config);
if (!header_line) {
fseek(reader->file, current_pos, SEEK_SET);
return 0;
}
}

while (1) {
char *line = read_full_record(reader->file, reader->persistent_arena);
char *line = read_full_record(reader->file, reader->persistent_arena, config);
if (!line) {
break;
}
Expand Down Expand Up @@ -273,16 +273,16 @@ long csv_reader_get_position(CSVReader *reader) {
return reader->line_number;
}

int csv_reader_seek(CSVReader *reader, long position) {
if (!reader || !reader->file || position < 0) {
int csv_reader_seek(CSVReader *reader, long position, CSVConfig *config) {
if (!reader || !reader->file || position < 0 || !config) {
return 0;
}

csv_reader_rewind(reader);
csv_reader_rewind(reader, config);

for (long i = 0; i < position; i++) {
arena_reset(reader->temp_arena);
char *line = read_full_record(reader->file, reader->temp_arena);
char *line = read_full_record(reader->file, reader->temp_arena, config);
if (!line) {
return 0;
}
Expand Down
8 changes: 4 additions & 4 deletions csv_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ typedef struct {
CSVReader* csv_reader_init_with_config(Arena *persistent_arena, Arena *temp_arena, CSVConfig *config);
CSVReader* csv_reader_init_standalone(CSVConfig *config);
void csv_reader_free(CSVReader *reader);
CSVRecord* csv_reader_next_record(CSVReader *reader);
CSVRecord* csv_reader_next_record(CSVReader *reader, CSVConfig *config);


void csv_reader_rewind(CSVReader *reader);
void csv_reader_rewind(CSVReader *reader, CSVConfig* config);
int csv_reader_set_config(CSVReader *reader, Arena *persistent_arena, Arena *temp_arena, const CSVConfig *config);
long csv_reader_get_record_count(CSVReader *reader);
long csv_reader_get_record_count(CSVReader *reader, CSVConfig* config);
long csv_reader_get_position(CSVReader *reader);
char** csv_reader_get_headers(CSVReader *reader, int *header_count);
int csv_reader_seek(CSVReader *reader, long position);
int csv_reader_seek(CSVReader *reader, long position, CSVConfig *config);
int csv_reader_has_next(CSVReader *reader);

#endif
12 changes: 7 additions & 5 deletions tests/test_csv_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,25 +173,27 @@ void test_read_full_record() {
rewind(test_file);

Arena arena;
assert(arena_create(&arena, 4096) == ARENA_OK);
assert(arena_create(&arena, 4096*2) == ARENA_OK);

CSVConfig *config = csv_config_create(&arena);

// Read first record (should handle multi-line quoted field)
char *record1 = read_full_record(test_file, &arena);
char *record1 = read_full_record(test_file, &arena, config);
assert(record1 != NULL);
assert(strstr(record1, "field2\nwith newline") != NULL);

// Read second record (simple line)
char *record2 = read_full_record(test_file, &arena);
char *record2 = read_full_record(test_file, &arena, config);
assert(record2 != NULL);
assert(strcmp(record2, "simple,line,here") == 0);

// Read third record (multi-line)
char *record3 = read_full_record(test_file, &arena);
char *record3 = read_full_record(test_file, &arena, config);
assert(record3 != NULL);
assert(strstr(record3, "multi\nline\nfield") != NULL);

// No more records
char *record4 = read_full_record(test_file, &arena);
char *record4 = read_full_record(test_file, &arena, config);
assert(record4 == NULL);

fclose(test_file);
Expand Down
Loading