Bonus files, invalid unfortunately since it's too late now i guess.
This commit is contained in:
parent
53a181c5d7
commit
80022d2f9d
41
phase2/tome_reader_bonus.c
Normal file
41
phase2/tome_reader_bonus.c
Normal file
@ -0,0 +1,41 @@
|
||||
// INFO: INVALID SINCE SUBMISSION IS OVER
|
||||
|
||||
#include "tome_utils_bonus.h"
|
||||
|
||||
#ifndef OPEN_MAX // If the GCC compiler does not define any value
|
||||
#define OPEN_MAX 5 // Give it a default one (lines)
|
||||
#endif // This should make clangd shut up about it
|
||||
int main(int argc, char *argv[]) {
|
||||
char *data;
|
||||
int fd[OPEN_MAX];
|
||||
// INFO: I'm sorry, I don't have much time left to implement a pipe input.
|
||||
if (argc < 2) {
|
||||
printer("Usage: ./tome_reader <file1> <file2> ...");
|
||||
exit(1);
|
||||
} else {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
fd[i - 1] = get_fd(argv[i], O_RDONLY);
|
||||
if (fd[i] == ERR) {
|
||||
printer("Error: Unable to open file\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < argc - 1; i++) {
|
||||
printer("--------------");
|
||||
// Loop until we get nothing
|
||||
while ((data = tome_reader(fd[i])) != NULL) {
|
||||
|
||||
printer("\n");
|
||||
printer("New line: ");
|
||||
printer(data);
|
||||
printer("--------------");
|
||||
free(data);
|
||||
}
|
||||
printer("\n");
|
||||
if (fd[i] != 0)
|
||||
close(fd[i]); // Close the file descriptor
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
286
phase2/tome_utils_bonus.c
Normal file
286
phase2/tome_utils_bonus.c
Normal file
@ -0,0 +1,286 @@
|
||||
// INFO: INVALID SINCE SUBMISSION IS OVER
|
||||
|
||||
#include "tome_utils_bonus.h"
|
||||
|
||||
#define strlen invalid // make sure that the built-in strlen is not used
|
||||
|
||||
#ifndef BUFFER_SIZE // If the GCC compiler does not define any value
|
||||
#define BUFFER_SIZE 40 // Give it a default one (lines)
|
||||
#endif // This should make clangd shut up about it
|
||||
|
||||
#ifndef OPEN_MAX // If the GCC compiler does not define any value
|
||||
#define OPEN_MAX 5 // Give it a default one (lines)
|
||||
#endif // This should make clangd shut up about it
|
||||
#ifndef DEBUG
|
||||
#define DEBUG FALSE
|
||||
#endif
|
||||
|
||||
// INFO: THINGS TO KEEP IN MIND:
|
||||
// printf is not used in this challenge, by default it's not being used unless
|
||||
// it's for debugging for simplicity sake.
|
||||
|
||||
/*
|
||||
* @info This is a simple implementation of the strlen function
|
||||
*
|
||||
* @brief Returns the length of a string
|
||||
* @param str The string to measure
|
||||
* @return The length of the string
|
||||
* @error Returns 0 if str is NULL
|
||||
*/
|
||||
int strlen(const char *str) {
|
||||
if (str == NULL) {
|
||||
return 0;
|
||||
}
|
||||
int i = 0;
|
||||
while (str[i] != '\0') {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* @info crude and basic implementation of "print"
|
||||
*
|
||||
* @brief Writes a string to STDOUT
|
||||
* @param str The string to write
|
||||
* @error does nothing if str is NULL
|
||||
*/
|
||||
void printer(const char *str, ...) {
|
||||
// screw me i guess
|
||||
// va_list args;
|
||||
if (str == NULL) {
|
||||
return;
|
||||
}
|
||||
write(1, str, strlen(str));
|
||||
}
|
||||
|
||||
/*
|
||||
* @info Convenience function to get the file descriptor
|
||||
*
|
||||
* @brief Returns the file descriptor of a file
|
||||
* @param filename The name of the file
|
||||
* @param mode The mode to open the file in
|
||||
* @return The file descriptor of the file
|
||||
* @error Returns -1 if the file cannot be opened
|
||||
*/
|
||||
int get_fd(char *filename, int mode) {
|
||||
if (filename == NULL)
|
||||
return ERR;
|
||||
int fd = open(filename, mode);
|
||||
if (fd == ERR)
|
||||
return ERR;
|
||||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* @info This function checks if a string contains a newline character
|
||||
*
|
||||
* @brief Returns TRUE (1) if the string contains a newline character, FALSE (0)
|
||||
* otherwise
|
||||
* @param str The string to check
|
||||
* @error Returns ERR (-1) if str is NULL
|
||||
*/
|
||||
int newlineexists(const char *str) {
|
||||
if (str == NULL)
|
||||
return ERR;
|
||||
for (int i = 0; str[i] != '\0'; i++) {
|
||||
if (str[i] == '\n') {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @info This function concatenates two strings
|
||||
*
|
||||
* @brief Returns a new string that is the concatenation of str1 and str2
|
||||
* @param str1 The first string
|
||||
* @param str2 The second string
|
||||
* @return The concatenated string
|
||||
* @error Returns NULL if str1 or str2 is NULL, or if memory allocation fails
|
||||
*/
|
||||
char *concat(char const *str1, char const *str2) {
|
||||
char *result;
|
||||
int i, j;
|
||||
// Sanity check
|
||||
if (!str1 || !str2)
|
||||
return NULL;
|
||||
result = malloc(strlen(str1) + strlen(str2) + 1); // +1 for eof
|
||||
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
for (i = 0; str1[i] != '\0'; i++) {
|
||||
result[i] = str1[i];
|
||||
}
|
||||
if (DEBUG)
|
||||
printf("[DEBUG]: Concatenating: [%s] + [%s]\n", str1, str2);
|
||||
for (j = 0; str2[j] != '\0'; j++, i++) {
|
||||
result[i] = str2[j];
|
||||
}
|
||||
result[i] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @info This function reads from a file descriptor and stores the content in a
|
||||
* string
|
||||
*
|
||||
* @brief Reads from a file descriptor and stores the content in a string
|
||||
* @param fd The file descriptor to read from
|
||||
* @param buf The buffer to store the content
|
||||
* @param str The string to store the content
|
||||
* @return The string containing the content read from the file descriptor
|
||||
* @error Returns NULL if there is an error reading from the file descriptor or
|
||||
* if memory allocation fails
|
||||
*/
|
||||
char *read_content(int fd, char *buf, char *temp, char *str) {
|
||||
int bytes;
|
||||
while (TRUE) {
|
||||
bytes = read(fd, buf, BUFFER_SIZE);
|
||||
if (bytes == ERR) {
|
||||
return NULL;
|
||||
}
|
||||
if (DEBUG)
|
||||
printf("[DEBUG]: Bytes gives : [%d]\n", bytes);
|
||||
buf[bytes] = '\0';
|
||||
if (DEBUG)
|
||||
printf("[DEBUG]: Buffer is: [%s]\n", buf);
|
||||
|
||||
if (DEBUG)
|
||||
printf("[DEBUG]: read %d bytes: \"%s\"\n", bytes, buf);
|
||||
temp = str; // move the temporary data to str
|
||||
if (temp == NULL) {
|
||||
temp = malloc(sizeof(char));
|
||||
if (temp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
temp[0] = '\0';
|
||||
}
|
||||
if (DEBUG)
|
||||
printf("[DEBUG]:We got a [%s] and [%s]\n", temp, buf);
|
||||
str = concat(temp, buf); // concatenate the temporary data with the buffer
|
||||
if (DEBUG)
|
||||
printf("[DEBUG]:Variable temp: (%s), buf: (%s)\n", temp, buf);
|
||||
if (DEBUG)
|
||||
printf("[DEBUG]: Concatenated str is: [%s]\n", str);
|
||||
free(temp);
|
||||
|
||||
if (newlineexists(str) == TRUE || bytes == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* @info This function returns a string up to the first newline character
|
||||
*
|
||||
* @brief Returns a string up to the first newline character
|
||||
* @param str The string to search
|
||||
* @return A string up to the first newline character
|
||||
* @error Returns NULL if str is NULL or if there is no newline character in the
|
||||
* string
|
||||
* @details
|
||||
* This function allocates memory for the new string, so it is the
|
||||
* responsibility of the caller to free it when it is no longer needed.
|
||||
*/
|
||||
char *before_nl(const char *str) {
|
||||
int i;
|
||||
char *ptr = NULL;
|
||||
// Sanity check
|
||||
if (str == NULL || str[0] == '\0')
|
||||
return NULL; // We got nothing or it's already EOF, we don't need this.
|
||||
for (i = 0; str[i] != '\n' && str[i] != '\0';
|
||||
i++) { // Count up until we reach a newline or EOF
|
||||
continue;
|
||||
}
|
||||
ptr = malloc(
|
||||
(i + 1 + 1) * // The str count plus the newline plus the null terminator
|
||||
sizeof(char)); // Dynamically allocate *just enough* space for the str
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; str[i] != '\n' && str[i] != '\0'; i++) { // Same thing here.
|
||||
ptr[i] = str[i];
|
||||
}
|
||||
if (str[i] == '\n') {
|
||||
ptr[i] = '\n';
|
||||
i++;
|
||||
}
|
||||
ptr[i] = '\0';
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* @info This function returns what's after the first newline character
|
||||
*
|
||||
* @brief I'm not repeating this ^
|
||||
* @param str The string to search
|
||||
* @return What's after the first newline character
|
||||
* @error Returns NULL if str is NULL, or malloc is going funky
|
||||
*/
|
||||
char *after_nl(char *str) {
|
||||
int i, j;
|
||||
char *ptr;
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
for (i = 0; str[i] != '\n' && str[i] != '\0'; i++)
|
||||
continue;
|
||||
if (str[i] == '\n') { // Consume the \n by skipping it
|
||||
i++;
|
||||
}
|
||||
if (str[i] == '\0') { // It's empty, might aswell drop it.
|
||||
free(str);
|
||||
return NULL;
|
||||
}
|
||||
if (DEBUG)
|
||||
printf("[DEBUG]: strlen(str) = %d\n", strlen(str));
|
||||
ptr = malloc((strlen(str) - i + 1) * sizeof(char));
|
||||
if (ptr == NULL)
|
||||
return NULL;
|
||||
j = 0;
|
||||
while (str[i] != '\0')
|
||||
ptr[j++] = str[i++];
|
||||
ptr[j] = '\0';
|
||||
free(str);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* @info This is similar to the get_next_line function homework I found on
|
||||
* GitHub ( src: https://github.com/pvaladares/42cursus-01-get_next_line )
|
||||
* Youtube ( url: https://www.youtube.com/watch?v=-Mt2FdJjVno )
|
||||
* (Heavily inspired, but not copied, I can explain what I wrote ;) )
|
||||
* @function tome_reader
|
||||
* @brief Reads a line from a file descriptor
|
||||
* @param fd The file descriptor to read from
|
||||
* @return The line read from the file descriptor
|
||||
*
|
||||
* @details
|
||||
* Here we start by defining a static variable str, which is used to store the
|
||||
* content read from the file descriptor.
|
||||
* We then proceed to actually get and return the line that is before the \n
|
||||
* Then we just take the same string and we chop everything before the first \n
|
||||
* and keep everything after.
|
||||
*/
|
||||
char *tome_reader(int fd) {
|
||||
// INFO: technically static is a global variable, but I hope it's allowed for
|
||||
// this one, removing static does the exact same thing. It's just for
|
||||
// cleanness sake.
|
||||
static char *str[OPEN_MAX];
|
||||
char *buf, *line;
|
||||
char *temp = NULL;
|
||||
if (fd == ERR || read(fd, 0, 0) == ERR) // Check if nothing wrong happened.
|
||||
return NULL;
|
||||
buf = malloc((BUFFER_SIZE + 1) * sizeof(char));
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
str[fd] = read_content(fd, buf, temp, str[fd]);
|
||||
if (str[fd] == NULL)
|
||||
return NULL;
|
||||
line = before_nl(str[fd]);
|
||||
str[fd] = after_nl(str[fd]);
|
||||
return line;
|
||||
}
|
||||
22
phase2/tome_utils_bonus.h
Normal file
22
phase2/tome_utils_bonus.h
Normal file
@ -0,0 +1,22 @@
|
||||
// INFO: INVALID SINCE SUBMISSION IS OVER
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// BOOLEAN VALUES
|
||||
enum {
|
||||
TRUE = 1,
|
||||
FALSE = 0,
|
||||
ERR = -1,
|
||||
};
|
||||
|
||||
void printer(const char *str, ...);
|
||||
int get_fd(char *filename, int mode);
|
||||
int newlineexists(const char *str);
|
||||
char *tome_reader(int fd);
|
||||
char *before_nl(const char *str);
|
||||
char *after_nl(char *str);
|
||||
char *read_content(int fd, char *buf, char *temp, char *str);
|
||||
char *concat(char const *string1, char const *string2);
|
||||
Loading…
x
Reference in New Issue
Block a user