Browse Source

faux: Unfinished faux_file lib

Serj Kalichev 4 years ago
parent
commit
1a133123e1
8 changed files with 237 additions and 2 deletions
  1. 5 2
      faux/Makefile.am
  2. 1 0
      faux/base/base.c
  3. 22 0
      faux/file.h
  4. 3 0
      faux/file/Makefile.am
  5. 152 0
      faux/file/file.c
  6. 12 0
      faux/file/private.h
  7. 1 0
      faux/str.h
  8. 41 0
      faux/str/str.c

+ 5 - 2
faux/Makefile.am

@@ -10,7 +10,8 @@ nobase_include_HEADERS += \
 	faux/conv.h \
 	faux/log.h \
 	faux/list.h \
-	faux/ini.h
+	faux/ini.h \
+	faux/file.h
 
 #	faux/argv.h \
 #	faux/dump.h \
@@ -24,7 +25,8 @@ EXTRA_DIST += \
 	faux/conv/Makefile.am \
 	faux/log/Makefile.am \
 	faux/list/Makefile.am \
-	faux/ini/Makefile.am
+	faux/ini/Makefile.am \
+	faux/file/Makefile.am
 
 #	faux/argv/Makefile.am \
 #	faux/dump/Makefile.am \
@@ -39,6 +41,7 @@ include $(top_srcdir)/faux/conv/Makefile.am
 include $(top_srcdir)/faux/log/Makefile.am
 include $(top_srcdir)/faux/list/Makefile.am
 include $(top_srcdir)/faux/ini/Makefile.am
+include $(top_srcdir)/faux/file/Makefile.am
 
 #include $(top_srcdir)/faux/argv/Makefile.am
 #include $(top_srcdir)/faux/dump/Makefile.am

+ 1 - 0
faux/base/base.c

@@ -66,6 +66,7 @@ void faux_bzero(void *ptr, size_t size) {
 	memset(ptr, '\0', size);
 }
 
+
 /** The malloc() implementation with writing zeroes to allocated buffer.
  *
  * The POSIX defines calloc() function to allocate memory and write zero bytes

+ 22 - 0
faux/file.h

@@ -0,0 +1,22 @@
+/** @file file.h
+ * @brief Public interface to work with files.
+ */
+
+#ifndef _faux_file_h
+#define _faux_file_h
+
+#include "faux/faux.h"
+
+typedef struct faux_file_s faux_file_t;
+
+C_DECL_BEGIN
+
+faux_file_t *faux_file_fdopen(int fd);
+faux_file_t *faux_file_open(const char *pathname, int flags, mode_t mode);
+int faux_file_close(faux_file_t *file);
+int faux_file_fileno(faux_file_t *file);
+char *faux_file_getline(faux_file_t *file);
+
+C_DECL_END
+
+#endif				/* _faux_file_h */

+ 3 - 0
faux/file/Makefile.am

@@ -0,0 +1,3 @@
+libfaux_la_SOURCES += \
+	faux/file/file.c \
+	faux/file/private.h

+ 152 - 0
faux/file/file.c

@@ -0,0 +1,152 @@
+/** @file file.c
+ * @brief Functions for working with files.
+ *
+ * This library was created to exclude glibc's file stream operations like
+ * fopen(), fgets() etc. These functions use glibc internal buffer. To work
+ * with buffer glibc has its own fflush() function and special behaviour while
+ * fclose(). It brings a problems with stream file objects and system file
+ * descriptors while fork(). The file streams and system file descriptors can't
+ * be used interchangeably. So faux file library uses standard system file
+ * operations like open(), read() and emulate some usefull stream function like
+ * getline(). The faux file object has own buffer and doesn't use glibc's one.
+ * The faux_file_close() doesn't lseek() file descriptor as fclose() can do.
+ * You can use faux file object and standard file operation in the same time.
+ * The only thing to remember is internal buffer that can contain already
+ * readed bytes.
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+
+#include "private.h"
+#include "faux/faux.h"
+#include "faux/file.h"
+#include "faux/str.h"
+
+
+/** @brief Create file object using existent fd.
+ *
+ * Create file object an link it to existent file descriptor.
+ *
+ * @return Allocated and initialized file object or NULL on error.
+ */
+faux_file_t *faux_file_fdopen(int fd) {
+
+	struct stat stat_struct = {};
+	faux_file_t *f = NULL;
+
+	// Before object creation check is fd valid.
+	// Try to get stat().
+	if (fstat(fd, &stat_struct) < 0)
+		return NULL; // Illegal fd
+
+	f = faux_zmalloc(sizeof(*f));
+	assert(f);
+	if (!f)
+		return NULL;
+
+	// Init
+	f->fd = fd;
+	f->buf_size = FAUX_FILE_CHUNK_SIZE;
+	f->buf = faux_zmalloc(f->buf_size);
+	assert(f->buf);
+	if (!f->buf) {
+		faux_free(f);
+		return NULL;
+	}
+	f->len = 0;
+
+	return f;
+}
+
+
+faux_file_t *faux_file_open(const char *pathname, int flags, mode_t mode) {
+
+	int fd = -1;
+
+	assert(pathname);
+	if (!pathname)
+		return NULL;
+
+	fd = open(pathname, flags, mode);
+	if (fd < 0)
+		return NULL;
+
+	return faux_file_fdopen(fd);
+}
+
+
+int faux_file_close(faux_file_t *f) {
+
+	int fd = -1;
+
+	assert(f);
+	if (!f)
+		return -1;
+
+	fd = f->fd;
+	faux_free(f->buf);
+	faux_free(f);
+
+	return close(fd);
+}
+
+
+int faux_file_fileno(faux_file_t *f) {
+
+	assert(f);
+	if (!f)
+		return -1;
+
+	return f->fd;
+}
+
+
+static char *faux_file_takeaway_line(faux_file_t *f) {
+
+	char *find = NULL;
+	const char *eol = "\n\r";
+	size_t line_len = 0;
+	char *line = NULL;
+
+	assert(f);
+	if (!f)
+		return NULL;
+
+	find = faux_str_charsn(f->buf, eol, f->len);
+	if (!find)
+		return NULL; // End of line is not found
+	line_len = find - f->buf;
+	line = faux_str_dupn(f->buf, line_len);
+	assert(line);
+	if (!line)
+		return NULL; // Memory problems
+
+	// Remove line from the internal buffer
+	// Remove EOL char also. So additional '1' is used
+	f->len = f->len - line_len - 1;
+	memmove(f->buf, find + 1, f->len);
+
+	return line;
+}
+
+char *faux_file_getline(faux_file_t *f) {
+
+	char *find = NULL;
+
+	assert(f);
+	if (!f)
+		return NULL;
+
+	// May be buffer already contain line
+	find = faux_file_takeaway_line(f);
+	if (find)
+		return find;
+
+	return NULL;
+}

+ 12 - 0
faux/file/private.h

@@ -0,0 +1,12 @@
+#include "faux/faux.h"
+#include "faux/file.h"
+
+/** @brief Chunk size to allocate buffer */
+#define FAUX_FILE_CHUNK_SIZE 128
+
+struct faux_file_s {
+	int fd; // File descriptor
+	char *buf; // Data buffer
+	size_t buf_size; // Current buffer size
+	size_t len; // Current data length
+};

+ 1 - 0
faux/str.h

@@ -30,6 +30,7 @@ char *faux_str_toupper(const char *str);
 int faux_str_casecmpn(const char *str1, const char *str2, size_t n);
 int faux_str_casecmp(const char *str1, const char *str2);
 char *faux_str_casestr(const char *haystack, const char *needle);
+char *faux_str_charsn(const char *str, const char *chars_to_search, size_t n);
 
 
 //const char *faux_str_suffix(const char *string);

+ 41 - 0
faux/str/str.c

@@ -399,6 +399,47 @@ char *faux_str_c_esc(const char *src) {
 }
 
 
+/** @brief Search the n-th chars of string for one of the specified chars.
+ *
+ *	The function search for any of specified characters within string.
+ *	The search is limited to first n characters of the string. If
+ *	terminating '\0' is before n-th character then search will stop on
+ *	it.
+ *
+ *	@param [in] str String (or memory block) to search in.
+ *	@param [in] chars_to_string Chars enumeration to search for.
+ *	@return Pointer to the first occurence of one of specified chars.
+ *		NULL on error.
+ */
+char *faux_str_charsn(const char *str, const char *chars_to_search, size_t n) {
+
+	const char *current_char = NULL;
+	char *nullp = NULL;
+	size_t len = n;
+
+	assert(str);
+	assert(chars_to_search);
+	if (!str || !chars_to_search)
+		return NULL;
+
+	// May be '\0' is before n-th char
+	nullp = memchr(str, '\0', n);
+	if (nullp)
+		len = nullp - str;
+
+	current_char = chars_to_search;
+	while (*current_char != '\0') {
+		void *find = NULL;
+
+		find = memchr(str, *current_char, len);
+		if (find)
+			return (char *)find;
+		current_char++;
+	}
+
+	return NULL;
+}
+
 /* TODO: If it nedeed?
 const char *faux_str_nextword(const char *string,
 	size_t *len, size_t *offset, size_t *quoted)