Last active
June 17, 2021 15:17
-
-
Save Colk-tech/9feb379c500946c82ddf091aa6688437 to your computer and use it in GitHub Desktop.
A useful library to read a file which is variable length. Written in C.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // Created by Manaki ITO on 2021/06/17. | |
| // | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #define DEFAULT_STR_BUFFER_LENGTH 512 | |
| #define DEFAULT_BUFFER_BYTES DEFAULT_STR_BUFFER_LENGTH * sizeof(char) | |
| #define print_error(...) {fprintf(stderr, "\x1b[31m"); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\x1b[39m\n");} | |
| #define fatal_with_message(exit_code, ...) {print_error(__VA_ARGS__); exit(exit_code);} | |
| void read_lines_from(char *filename, char **result); | |
| long long int line_number(char *filename); | |
| int find_char(char *string, long long int str_length, char query); | |
| void delete_char(char *string, long long int str_length, char query); | |
| int sample_usage(void) { | |
| char filename[] = "filename.c"; | |
| long long int lines = line_number(filename); | |
| char **result = NULL; | |
| result = (char**) malloc(sizeof(char*) * lines - 1); | |
| read_lines_from(filename, result); | |
| for (int i = 0; i < lines - 1; i++) { | |
| printf("%s\n", result[i]); | |
| } | |
| return 0; | |
| } | |
| void read_lines_from(char *filename, char **result) { | |
| FILE *fp = NULL; | |
| char *current_line = NULL; | |
| char *buf = NULL; | |
| long long int line_count = 0; | |
| long long int current_buffer_bytes = -1; | |
| fp = fopen(filename, "r"); | |
| if (fp == NULL) { | |
| fatal_with_message(1, | |
| "[X] Error: Failed to open \"%s\".\n" | |
| "Make sure the file name is correct and not accessed by any other process.\n" | |
| "Aborting", | |
| filename); | |
| } | |
| buf = (char *) malloc(sizeof(char) * DEFAULT_BUFFER_BYTES); | |
| if (buf == NULL) { | |
| fatal_with_message(1, | |
| "[X] Unexpected error: Failed to allocate memory.\n" | |
| "Make sure the file name is correct and not accessed by any other process.\n" | |
| "Aborting") | |
| } | |
| while (1) { | |
| current_buffer_bytes = DEFAULT_BUFFER_BYTES; | |
| current_line = (char *) malloc(current_buffer_bytes); | |
| if (current_line == NULL) { | |
| fatal_with_message(1, | |
| "[X] Unexpected error: Failed to allocate memory.\n" | |
| "Make sure the file name is correct and not accessed by any other process.\n" | |
| "Aborting") | |
| } | |
| if (fgets(current_line, DEFAULT_BUFFER_BYTES, fp) == NULL) { | |
| break; | |
| } | |
| while (1) { | |
| int continue_required = !( | |
| find_char(current_line, current_buffer_bytes, '\n') || | |
| find_char(current_line, current_buffer_bytes, EOF)); | |
| if (!continue_required) { | |
| break; | |
| } | |
| if (fgets(buf, DEFAULT_BUFFER_BYTES, fp) == NULL) { | |
| break; | |
| } | |
| current_buffer_bytes += DEFAULT_STR_BUFFER_LENGTH; | |
| current_line = realloc(current_line, current_buffer_bytes); | |
| if (current_line == NULL) { | |
| fatal_with_message(1, | |
| "[X] Unexpected error: Failed to allocate memory.\n" | |
| "Make sure the file name is correct and not accessed by any other process.\n" | |
| "Aborting") | |
| } | |
| strcat(current_line, buf); | |
| memset(buf, '\0', DEFAULT_BUFFER_BYTES); | |
| } | |
| delete_char(current_line, current_buffer_bytes / sizeof(char), '\n'); | |
| delete_char(current_line, current_buffer_bytes / sizeof(char), '\r'); | |
| result[line_count] = (char *) malloc(current_buffer_bytes); | |
| memcpy(result[line_count], current_line, current_buffer_bytes); | |
| free(current_line); | |
| line_count++; | |
| } | |
| fclose(fp); | |
| } | |
| long long int line_number(char *filename) { | |
| FILE *fp; | |
| size_t read_size; | |
| char buf[DEFAULT_BUFFER_BYTES]; | |
| long long int lines = 0; | |
| if ((fp = fopen(filename, "r")) == NULL) { | |
| fatal_with_message(1, | |
| "[X] Unexpected error: Failed to allocate memory.\n" | |
| "Make sure the file name is correct and not accessed by any other process.\n" | |
| "Aborting") | |
| } | |
| while ((read_size = fread(buf, 1, DEFAULT_BUFFER_BYTES, fp)) > 0) { | |
| for (size_t i = 0; i < read_size; i++) { | |
| if (buf[i] == '\n') { | |
| lines++; | |
| } | |
| } | |
| } | |
| lines++; | |
| fclose(fp); | |
| return lines; | |
| } | |
| int find_char(char *string, long long int str_length, char query) { | |
| long long int i = 0; | |
| while (i < str_length) { | |
| if (string[i] == query) { | |
| return 1; | |
| } | |
| i++; | |
| } | |
| return 0; | |
| } | |
| void delete_char(char *string, long long int str_length, char query) { | |
| char *temp; | |
| long long int size = str_length * sizeof(char); | |
| temp = (char *) malloc(size); | |
| if (temp == NULL) { | |
| fatal_with_message(1, | |
| "[X] Unexpected error: Failed to allocate memory.\n" | |
| "Make sure the file name is correct and not accessed by any other process.\n" | |
| "Aborting") | |
| } | |
| memset(temp, '\0', size); | |
| for (int i = 0; i < str_length; i++) { | |
| if (string[i] != query) { | |
| temp[i] = string[i]; | |
| } | |
| } | |
| memcpy(string, temp, str_length * sizeof(char)); | |
| free(temp); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment