cstring: improve readline
authorNiki Roo <niki@nikiroo.be>
Fri, 21 Jun 2024 18:09:34 +0000 (20:09 +0200)
committerNiki Roo <niki@nikiroo.be>
Fri, 21 Jun 2024 18:09:34 +0000 (20:09 +0200)
cstring.c
cutils.c
cutils.h
desktop.c

index d25d4c9113b81f778bed0485b5834650ea3da1ab..58481ecbdf4baafa69fe9d59762c1a8997b180ce 100644 (file)
--- a/cstring.c
+++ b/cstring.c
@@ -633,66 +633,19 @@ void cstring_change_case(cstring_t *self, int up) {
        free_cstring(rep);
 }
 
-static char buffer[BUFFER_SIZE];
 int cstring_readline(cstring_t *self, FILE *file) {
-       size_t size = 0;
-       int full_line;
-
-       // sanity check:
-       if (!file)
-               return 0;
-
-       if (!feof(file)) {
-               // Allow '\0' in data (1/4)
-               //buffer[BUFFER_SIZE - 1] = '\0'; // just in case
-               memset(buffer, ~0, BUFFER_SIZE);
-
-               cstring_clear(self);
-               buffer[0] = '\0';
-
-               // Note: fgets() could return NULL if EOF is reached
-               if (!fgets(buffer, (int) BUFFER_SIZE - 1, file))
-                       return 0;
-               
-               // Allow '\0' in data (2/4)
-               //size = strlen(buffer);
-               size = BUFFER_SIZE;
-               while(size && buffer[size - 1])
-                       size--;
-               if (size)
-                       size--;
-
-               full_line = ((file && feof(file)) || size == 0
-                               || buffer[size - 1] == '\n');
-               size = cstring_remove_crlf_sz(buffer, size);
-               cstring_addfN(self, buffer, 0, size);
-
-               // No luck, we need to continue getting data
-               while (!full_line) {
-                       // Allow '\0' in data (3/4)
-                       //buffer[BUFFER_SIZE - 1] = '\0'; // just in case
-                       memset(buffer, ~0, BUFFER_SIZE);
-                       
-                       if (!fgets(buffer, (int) BUFFER_SIZE - 1, file))
-                               break;
-
-                       // Allow '\0' in data (4/4)
-                       //size = strlen(buffer);
-                       size = BUFFER_SIZE;
-                       while(size && buffer[size - 1])
-                               size--;
-                       if (size)
-                               size--;
-                       
-                       full_line = ((file && feof(file)) || size == 0
-                                       || buffer[size - 1] == '\n');
-                       size = cstring_remove_crlf_sz(buffer, size);
-                       cstring_addfN(self, buffer, 0, size);
-               }
-
+       ssize_t sz = getline(
+               &(self->string), 
+               &(((priv_t *) self->priv)->buffer_length), 
+               file
+       );
+       
+       if (sz > 0) {
+               self->length = cstring_remove_crlf_sz(self->string, sz);
                return 1;
        }
-
+       
+       cstring_clear(self);
        return 0;
 }
 
index 1141c2c0f439acd8397e01fadcaeb793d40da7ba..4547c4bd3a793859fca8f3b9c440754736fcee72 100644 (file)
--- a/cutils.c
+++ b/cutils.c
@@ -42,3 +42,43 @@ char *strdup(const char *source) {
        return new;
 }
 #endif
+
+#ifndef getline
+ssize_t getline(char **strp, size_t *n, FILE *f) {
+       char *str = *strp;
+       size_t max = *n;
+       ssize_t sz = 0;
+       
+       if (!str) {
+               max = 1024;
+               str = malloc(max);
+       }
+       
+       int car = '\0';
+       for (sz = 0 ; car >= 0 ; sz++) {
+               int car = fgetc(f);
+               if (car < 0)
+                       break;
+
+               if (max <= sz) {
+                       max *= 2;
+                       str = realloc(str, max);
+               }
+               
+               str[sz] = car;
+               
+               if (car == '\n')
+                       break;
+       }
+       
+       if ((car < 0) && !sz)
+               sz = -1;
+       
+       if (sz >= 0)
+               str[sz] = '\0';
+       
+       *strp = str;
+       *n = max;
+       return sz;
+}
+#endif
index 0090a3169d049c9fbd358715f65ed652d78da78d..8fcaadd0de848fb52fad2f9253d1be7563805821 100644 (file)
--- a/cutils.h
+++ b/cutils.h
 /**
  * @file cutils.h
  * @author Niki
- * @date 2020 - 2022
+ * @date 2020 - 2024
  *
  * @brief Include all the other .h as well as C99-compatible
- * <tt>strdup</tt>/<tt>strnlen</tt> functions if they are not already defined
+ * <tt>strdup</tt>/<tt>strnlen</tt>/<tt>getline</tt> functions 
+ * if they are not already defined
  */
 #ifndef CUTILS_H
 #define CUTILS_H
@@ -32,6 +33,8 @@
 extern "C" {
 #endif
 
+#include <stdlib.h>
+
 #include "cstring.h"
 #include "array.h"
 #include "desktop.h"
@@ -68,6 +71,16 @@ size_t strnlen(const char *s, size_t maxlen);
  */
 char *strdup(const char *source);
 #endif
+//#if _POSIX_C_SOURCE < 200809L
+//#ifndef _GNU_SOURCE
+/**
+ * getline() reads an entire line from stream, storing the address of the
+ * buffer containing the text into *lineptr.  The buffer is null-
+ * terminated and includes the newline character, if one was found.
+ */
+ssize_t getline(char **strp, size_t *n, FILE *f);
+//#endif
+//#endif
 
 /* */
 
index 1892811137d89904cc962580684000eda279c790..4f2cb24abe22219597c81a187e64d62a297976a5 100644 (file)
--- a/desktop.c
+++ b/desktop.c
@@ -25,7 +25,9 @@
 #include <string.h>
 #include <strings.h>
 
-#include "cutils.h"
+#include "desktop.h"
+#include "array.h"
+#include "cstring.h"
 
 #define EXT "desktop"