[<prev] [next>] [day] [month] [year] [list]
Message-ID: <CAFf+5zivvBhC3xjU0Eottf=BEJicH_DQeZhgN7-0OG2B9m=_rg@mail.gmail.com>
Date: Sat, 10 May 2025 08:33:57 +0530
From: Amit <amitchoudhary0523@...il.com>
To: linux-kernel@...r.kernel.org
Subject: Alternate implementation of C standard library's getline() function
which is much simpler to use than getline().
File get_line_from_file.c implements a function get_line_from_file() which is
an alternate implementation of C standard library's getline() function and this
function is much simpler to use than getline().
There are three files and their contents are listed below:
--------------------
get_line_from_file.c
--------------------
/*
* License:
*
* This file has been released under "unlicense" license
* (https://unlicense.org).
*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or distribute
* this software, either in source code form or as a compiled binary, for any
* purpose, commercial or non-commercial, and by any means.
*
* For more information about this license, please visit - https://unlicense.org
*/
/*
* Author: Amit Choudhary
* Email: amitchoudhary0523 AT gmail DOT com
*/
#include "get_line_from_file.h"
#include <stddef.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#define NEW_LINE '\n'
#define BUF_SIZE_INCREMENT 1024
char *get_line_from_file(int fd, int *error_num)
{
char *buf = NULL;
char *buf_temp = NULL;
long curr_buf_size = 0;
long curr_data_len = 0;
ssize_t bytes_read = -1;
int end_of_file_reached_or_error = 0;
int new_line_found = 0;
long i = 0;
*error_num = NO_ERROR;
if (fd < 0) {
*error_num = INVALID_FD;
return NULL;
}
while (1) {
buf_temp = buf;
buf = realloc(buf, (size_t)(curr_buf_size + BUF_SIZE_INCREMENT));
if (!buf) {
free(buf_temp);
*error_num = NO_MEMORY;
return NULL;
}
curr_buf_size = curr_buf_size + BUF_SIZE_INCREMENT;
// read data from file
while (curr_data_len != curr_buf_size) {
bytes_read = read(fd, buf + curr_data_len,
(size_t)(curr_buf_size - curr_data_len));
if (bytes_read == 0) { // end of file reached
// Check if no bytes were read earlier also in this call to
// get_line_from_file(). If yes, then this means that end of
// test file was reached (but not actually read) in the last
// call to get_line_from_file(). So, this time end of file was
// read and 0 was returned by read. So, since there are no bytes
// to process, free the buffer and return NULL.
if (curr_data_len == 0) {
free(buf);
return NULL;
}
} // end of if bytes_read == 0
if (bytes_read <= 0) {
end_of_file_reached_or_error = 1;
break;
} // end of if bytes_read <= 0
curr_data_len = curr_data_len + bytes_read;
} // end of inner while (1) loop
new_line_found = 0;
for (i = 0; i < curr_data_len; i++) {
if (buf[i] == NEW_LINE) {
buf[i] = 0;
new_line_found = 1;
break;
}
} // end of for loop
if (new_line_found) {
// realloc and seek
buf_temp = buf;
buf = realloc(buf, (size_t)(i + 1));
if (!buf) {
free(buf_temp);
*error_num = NO_MEMORY;
return NULL;
}
if (lseek(fd, (i + 1) - curr_data_len, SEEK_CUR) < 0) {
*error_num = FILE_LSEEK_ERROR;
free(buf);
return NULL;
}
return buf;
} else { // new line not found
// NEW_LINE not found and end of file has been reached or some
// error happened. So, allocate one extra byte for terminating
// null byte and return.
if (end_of_file_reached_or_error) {
buf_temp = buf;
buf = realloc(buf, (size_t)(curr_data_len + 1));
if (!buf) {
free(buf_temp);
*error_num = NO_MEMORY;
return NULL;
}
buf[curr_data_len] = 0;
return buf;
} // end of if end_of_file_reached_or_error
} // end of if - else (new_line_found)
} // end of outer while (1) loop
} // end of get_line_from_file
--------------------
get_line_from_file.h
--------------------
/*
* License:
*
* This file has been released under "unlicense" license
* (https://unlicense.org).
*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or distribute
* this software, either in source code form or as a compiled binary, for any
* purpose, commercial or non-commercial, and by any means.
*
* For more information about this license, please visit - https://unlicense.org
*/
/*
* Author: Amit Choudhary
* Email: amitchoudhary0523 AT gmail DOT com
*/
#ifndef _GET_LINE_FROM_FILE_H_
#define _GET_LINE_FROM_FILE_H_
#define NO_ERROR 0 // no error happened.
#define INVALID_FD -1 // fd is less than 0.
#define NO_MEMORY -2 // memory not available.
#define FILE_LSEEK_ERROR -3 // error in seeking file
/*
* char *get_line_from_file(int fd, int *error_num):
*
* Function get_line_from_file() is an alternate implementation of C standard
* library's getline() function and this function is much simpler to use than
* getline().
*
* Function get_line_from_file() returns a line from the file represented by fd.
*
* This function supports only regular files (no pipes, sockets, etc).
*
* If fd is less than 0 then NULL is returned and *error_num is assigned the
* appropriate error value (INVALID_FD in this case).
*
* In case of any error, *error_num is assigned the appropriate error value.
*
* The high level algorithm of this function is:
*
* The function get_line_from_file() reads some bytes in a buffer from the
* file and tries to find the newline in the buffer. If the newline is not
* found then it reads more bytes from the file in the buffer. When the
* newline is found in the buffer, then the newline is replaced with the
* null terminating character and the buffer is reallocated to the correct
* size. Then the file offset for reading is set to the start of the next
* line. And then the buffer is returned to the user.
*
* Please note that the returned line/buffer doesn't contain any newlines.
*
* The line/buffer returned by this function is allocated using realloc(),
* so it is user's responsibility to free the line (free memory).
*/
char *get_line_from_file(int fd, int *error_num);
#endif
-------------------------
test_get_line_from_file.c
-------------------------
/*
* License:
*
* This file has been released under "unlicense" license
* (https://unlicense.org).
*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or distribute
* this software, either in source code form or as a compiled binary, for any
* purpose, commercial or non-commercial, and by any means.
*
* For more information about this license, please visit - https://unlicense.org
*/
/*
* Author: Amit Choudhary
* Email: amitchoudhary0523 AT gmail DOT com
*/
#include "get_line_from_file.h"
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd = -1;
char *line = NULL;
int error_num = 0;
if (argc != 2) {
printf("\n");
printf("Error: Incorrect usage.\n");
printf("\n");
printf("This program takes only one argument which is the name of a"
" file whose contents have to be printed.\n");
printf("\n");
printf("Usage: %s file_name\n", argv[0]);
printf("\n");
printf("Please try again. Exiting..\n");
printf("\n");
exit(1);
}
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
printf("\n%s: File \"%s\" could not be opened. Exiting..\n\n",
__FILE__, argv[1]);
exit(1);
}
while ((line = get_line_from_file(fd, &error_num)) != NULL) {
printf("%s\n", line);
free(line);
}
if (error_num != 0) {
printf("\nError number returned = %d\n\n", error_num);
}
close(fd);
} // end of function main()
Powered by blists - more mailing lists