[geany/geany] a5dea8: Grab all MIO changes from uctags

Jiří Techet git-noreply at xxxxx
Mon Dec 17 21:05:38 UTC 2018


Branch:      refs/heads/master
Author:      Jiří Techet <techet at gmail.com>
Committer:   Jiří Techet <techet at gmail.com>
Date:        Sat, 08 Oct 2016 12:13:41 UTC
Commit:      a5dea8091bdd84de1f70c7989ff2a3c79d31a9ee
             https://github.com/geany/geany/commit/a5dea8091bdd84de1f70c7989ff2a3c79d31a9ee

Log Message:
-----------
Grab all MIO changes from uctags


Modified Paths:
--------------
    ctags/main/mio.c
    ctags/main/mio.h

Modified: ctags/main/mio.c
382 lines changed, 351 insertions(+), 31 deletions(-)
===================================================================
@@ -18,6 +18,22 @@
  *
  */
 
+#ifndef QUALIFIER
+#include "general.h"  /* must always come first */
+
+#include "routines.h"
+#include "debug.h"
+#else
+
+#if defined (HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#ifdef USE_STDBOOL_H
+#include <stdbool.h>
+#endif
+#endif
+
 #include "mio.h"
 
 #include <stdarg.h>
@@ -27,6 +43,63 @@
 #include <stdlib.h>
 #include <limits.h>
 
+#ifdef QUALIFIER
+#define xMalloc(n,Type)    (Type *)eMalloc((size_t)(n) * sizeof (Type))
+#define xCalloc(n,Type)    (Type *)eCalloc((size_t)(n), sizeof (Type))
+#define xRealloc(p,n,Type) (Type *)eRealloc((p), (n) * sizeof (Type))
+
+extern void *eMalloc (const size_t size)
+{
+	void *buffer = malloc (size);
+
+	if (buffer == NULL)
+	{
+		fprintf(stderr, "out of memory");
+		abort ();
+	}
+
+	return buffer;
+}
+
+extern void *eCalloc (const size_t count, const size_t size)
+{
+	void *buffer = calloc (count, size);
+
+	if (buffer == NULL)
+	{
+		fprintf(stderr, "out of memory");
+		abort ();
+	}
+
+	return buffer;
+}
+
+extern void *eRealloc (void *const ptr, const size_t size)
+{
+	void *buffer;
+	if (ptr == NULL)
+		buffer = eMalloc (size);
+	else
+	{
+		buffer = realloc (ptr, size);
+		if (buffer == NULL)
+		{
+			fprintf(stderr, "out of memory");
+			abort ();
+		}
+	}
+	return buffer;
+}
+
+extern void eFree (void *const ptr)
+{
+	free (ptr);
+}
+
+#  define Assert(c)
+#  define AssertNotReached()
+#endif
+
 /* minimal reallocation chunk size */
 #define MIO_CHUNK_SIZE 4096
 
@@ -42,9 +115,12 @@
  * file based operations and in-memory operations. Its goal is to ease the port
  * of an application that uses C file I/O API to perform in-memory operations.
  *
- * A #MIO object is created using mio_new_file() or mio_new_memory(), depending
- * on whether you want file or in-memory operations, and destroyed using
- * mio_free(). There is also some other convenient API to create file-based
+ * A #MIO object is created using mio_new_file(), mio_new_memory() or mio_new_mio(),
+ * depending on whether you want file or in-memory operations.
+ * Its life is managed by reference counting. Just after calling one of functions
+ * for creating, the count is 1. mio_ref() increments the counter. mio_free()
+ * decrements it. When the counter becomes 0, the #MIO object will be destroyed
+ * in mio_free(). There is also some other convenient API to create file-based
  * #MIO objects for more complex cases, such as mio_new_file_full() and
  * mio_new_fp().
  *
@@ -58,6 +134,43 @@
  */
 
 
+typedef struct _MIOUserData MIOUserData;
+struct _MIOUserData {
+	void *d;
+	MIODestroyNotify f;
+};
+
+/**
+ * MIO:
+ *
+ * An object representing a #MIO stream. No assumptions should be made about
+ * what compose this object, and none of its fields should be accessed directly.
+ */
+struct _MIO {
+	/*< private >*/
+	MIOType type;
+	unsigned int refcount;
+	union {
+		struct {
+			FILE *fp;
+			MIOFCloseFunc close_func;
+		} file;
+		struct {
+			unsigned char *buf;
+			int ungetch;
+			size_t pos;
+			size_t size;
+			size_t allocated_size;
+			MIOReallocFunc realloc_func;
+			MIODestroyNotify free_func;
+			bool error;
+			bool eof;
+		} mem;
+	} impl;
+	MIOUserData udata;
+};
+
+
 /**
  * mio_new_file_full:
  * @filename: Filename to open, passed as-is to @open_func as the first argument
@@ -93,21 +206,24 @@ MIO *mio_new_file_full (const char *filename,
 	/* we need to create the MIO object first, because we may not be able to close
 	 * the opened file if the user passed NULL as the close function, which means
 	 * that everything must succeed if we've opened the file successfully */
-	mio = malloc (sizeof *mio);
+	mio = xMalloc (1, MIO);
 	if (mio)
 	{
 		FILE *fp = open_func (filename, mode);
 
 		if (! fp)
 		{
-			free (mio);
+			eFree (mio);
 			mio = NULL;
 		}
 		else
 		{
 			mio->type = MIO_TYPE_FILE;
 			mio->impl.file.fp = fp;
 			mio->impl.file.close_func = close_func;
+			mio->refcount = 1;
+			mio->udata.d = NULL;
+			mio->udata.f = NULL;
 		}
 	}
 
@@ -160,12 +276,15 @@ MIO *mio_new_fp (FILE *fp, MIOFCloseFunc close_func)
 	if (!fp)
 		return NULL;
 
-	mio = malloc (sizeof *mio);
+	mio = xMalloc (1, MIO);
 	if (mio)
 	{
 		mio->type = MIO_TYPE_FILE;
 		mio->impl.file.fp = fp;
 		mio->impl.file.close_func = close_func;
+		mio->refcount = 1;
+		mio->udata.d = NULL;
+		mio->udata.f = NULL;
 	}
 
 	return mio;
@@ -214,7 +333,7 @@ MIO *mio_new_memory (unsigned char *data,
 {
 	MIO *mio;
 
-	mio = malloc (sizeof *mio);
+	mio = xMalloc (1, MIO);
 	if (mio)
 	{
 		mio->type = MIO_TYPE_MEMORY;
@@ -227,11 +346,89 @@ MIO *mio_new_memory (unsigned char *data,
 		mio->impl.mem.free_func = free_func;
 		mio->impl.mem.eof = false;
 		mio->impl.mem.error = false;
+		mio->refcount = 1;
+		mio->udata.d = NULL;
+		mio->udata.f = NULL;
 	}
 
 	return mio;
 }
 
+/**
+ * mio_new_mio:
+ * @base: The original mio
+ * @start: stream offset of the @base where new mio starts
+ * @size: the length of the data copied from @base to new mio
+ *
+ * Creates a new #MIO object by copying data from existing #MIO (@base).
+ * The range for copying are given with @start and @size.
+ * Copying data at the range from @start to the end of @base is
+ * done if 0 is given as @size.
+ *
+ * If @size(!= 0) is larger than the length from @start to the end of
+ * @base, %NULL is return.
+ *
+ * The function doesn't move the file position of @base.
+ *
+ * Free-function: mio_free()
+ *
+ */
+
+MIO *mio_new_mio (MIO *base, long start, size_t size)
+{
+	unsigned char *data;
+	long original_pos;
+	MIO *submio;
+	size_t r;
+
+	original_pos = mio_tell (base);
+
+	if (size == 0)
+	{
+		long end;
+
+		if (mio_seek (base, 0, SEEK_END) != 0)
+			return NULL;
+		end = mio_tell (base);
+		size = end - start;
+		Assert (size >= 0);
+	}
+
+	if (mio_seek (base, start, SEEK_SET) != 0)
+		return NULL;
+
+	data = xMalloc (size, unsigned char);
+	r= mio_read (base, data, 1, size);
+	mio_seek (base, original_pos, SEEK_SET);
+
+	if (r != size)
+		goto cleanup;
+
+	submio = mio_new_memory (data, size, eRealloc, eFree);
+	if (! submio)
+		goto cleanup;
+
+	return submio;
+
+cleanup:
+	eFree (data);
+	return NULL;
+}
+
+/**
+ * mio_ref:
+ * @mio: A #MIO object
+ *
+ * Increments the reference counter of a #MIO.
+ *
+ * Returns: passed @mio.
+ */
+MIO *mio_ref        (MIO *mio)
+{
+	mio->refcount++;
+	return mio;
+}
+
 /**
  * mio_file_get_fp:
  * @mio: A #MIO object
@@ -288,7 +485,8 @@ unsigned char *mio_memory_get_data (MIO *mio, size_t *size)
  * mio_free:
  * @mio: A #MIO object
  *
- * Destroys a #MIO object.
+ * Decrements the reference counter of a #MIO and destroys the #MIO
+ * object if its counter becomes 0.
  *
  * Returns: Error code obtained from the registered MIOFCloseFunc or 0 on success.
  */
@@ -298,14 +496,20 @@ int mio_free (MIO *mio)
 
 	if (mio)
 	{
+		if (--mio->refcount)
+			return 0;
+
+		if (mio->udata.d && mio->udata.f)
+			mio->udata.f (mio->udata.d);
+
 		if (mio->type == MIO_TYPE_FILE)
 		{
 			if (mio->impl.file.close_func)
 				rv = mio->impl.file.close_func (mio->impl.file.fp);
 			mio->impl.file.close_func = NULL;
 			mio->impl.file.fp = NULL;
 		}
-		else
+		else if (mio->type == MIO_TYPE_MEMORY)
 		{
 			if (mio->impl.mem.free_func)
 				mio->impl.mem.free_func (mio->impl.mem.buf);
@@ -318,8 +522,10 @@ int mio_free (MIO *mio)
 			mio->impl.mem.eof = false;
 			mio->impl.mem.error = false;
 		}
+		else
+			AssertNotReached ();
 
-		free (mio);
+		eFree (mio);
 	}
 
 	return rv;
@@ -347,7 +553,7 @@ size_t mio_read (MIO *mio,
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return fread (ptr_, size, nmemb, mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		size_t n_read = 0;
 
@@ -382,6 +588,11 @@ size_t mio_read (MIO *mio,
 
 		return n_read;
 	}
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
 }
 
 /*
@@ -490,7 +701,7 @@ size_t mio_write (MIO *mio,
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return fwrite (ptr, size, nmemb, mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		size_t n_written = 0;
 
@@ -506,6 +717,11 @@ size_t mio_write (MIO *mio,
 
 		return n_written;
 	}
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
 }
 
 /**
@@ -522,7 +738,7 @@ int mio_putc (MIO *mio, int c)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return fputc (c, mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		int rv = EOF;
 
@@ -535,6 +751,11 @@ int mio_putc (MIO *mio, int c)
 
 		return rv;
 	}
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
 }
 
 /**
@@ -550,7 +771,7 @@ int mio_puts (MIO *mio, const char *s)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return fputs (s, mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		int rv = EOF;
 		size_t len;
@@ -565,6 +786,11 @@ int mio_puts (MIO *mio, const char *s)
 
 		return rv;
 	}
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
 }
 
 /**
@@ -583,7 +809,7 @@ int mio_vprintf (MIO *mio, const char *format, va_list ap)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return vfprintf (mio->impl.file.fp, format, ap);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		int rv = -1;
 		size_t n;
@@ -623,6 +849,11 @@ int mio_vprintf (MIO *mio, const char *format, va_list ap)
 
 		return rv;
 	}
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
 }
 
 /**
@@ -662,7 +893,7 @@ int mio_getc (MIO *mio)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return fgetc (mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		int rv = EOF;
 
@@ -682,6 +913,11 @@ int mio_getc (MIO *mio)
 
 		return rv;
 	}
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
 }
 
 /**
@@ -704,7 +940,7 @@ int mio_ungetc (MIO *mio, int ch)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return ungetc (ch, mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		int rv = EOF;
 
@@ -717,6 +953,11 @@ int mio_ungetc (MIO *mio, int ch)
 
 		return rv;
 	}
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
 }
 
 /**
@@ -735,28 +976,35 @@ char *mio_gets (MIO *mio, char *s, size_t size)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return fgets (s, (int)size, mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		char *rv = NULL;
 
 		if (size > 0)
 		{
 			size_t i = 0;
+			bool newline = false;
+			/* Avoiding dereference inside the for loop below improves
+			 * performance so we do it here. */
+			size_t pos = mio->impl.mem.pos;
+			size_t buf_size = mio->impl.mem.size;
+			unsigned char *buf = mio->impl.mem.buf;
 
 			if (mio->impl.mem.ungetch != EOF)
 			{
 				s[i] = (char)mio->impl.mem.ungetch;
 				mio->impl.mem.ungetch = EOF;
-				mio->impl.mem.pos++;
+				pos++;
 				i++;
 			}
-			for (; mio->impl.mem.pos < mio->impl.mem.size && i < (size - 1); i++)
+			for (; pos < buf_size && i < (size - 1); i++)
 			{
-				s[i] = (char)mio->impl.mem.buf[mio->impl.mem.pos];
-				mio->impl.mem.pos++;
+				s[i] = (char)buf[pos];
+				pos++;
 				if (s[i] == '\n')
 				{
 					i++;
+					newline = true;
 					break;
 				}
 			}
@@ -765,12 +1013,19 @@ char *mio_gets (MIO *mio, char *s, size_t size)
 				s[i] = 0;
 				rv = s;
 			}
-			if (mio->impl.mem.pos >= mio->impl.mem.size)
+			if (!newline && pos >= buf_size)
 				mio->impl.mem.eof = true;
+			mio->impl.mem.pos = pos;
+			mio->impl.mem.size = buf_size;
 		}
 
 		return rv;
 	}
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
 }
 
 /**
@@ -784,11 +1039,13 @@ void mio_clearerr (MIO *mio)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		clearerr (mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		mio->impl.mem.error = false;
 		mio->impl.mem.eof = false;
 	}
+	else
+		AssertNotReached ();
 }
 
 /**
@@ -804,8 +1061,13 @@ int mio_eof (MIO *mio)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return feof (mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 		return mio->impl.mem.eof != false;
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
 }
 
 /**
@@ -821,8 +1083,13 @@ int mio_error (MIO *mio)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return ferror (mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 		return mio->impl.mem.error != false;
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
 }
 
 /**
@@ -843,7 +1110,7 @@ int mio_seek (MIO *mio, long offset, int whence)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return fseek (mio->impl.file.fp, offset, whence);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		/* FIXME: should we support seeking out of bounds like lseek() seems to do? */
 		int rv = -1;
@@ -894,6 +1161,12 @@ int mio_seek (MIO *mio, long offset, int whence)
 
 		return rv;
 	}
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
+
 }
 
 /**
@@ -910,7 +1183,7 @@ long mio_tell (MIO *mio)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		return ftell (mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		long rv = -1;
 
@@ -925,6 +1198,11 @@ long mio_tell (MIO *mio)
 
 		return rv;
 	}
+	else
+	{
+		AssertNotReached ();
+		return 0;
+	}
 }
 
 /**
@@ -939,13 +1217,15 @@ void mio_rewind (MIO *mio)
 {
 	if (mio->type == MIO_TYPE_FILE)
 		rewind (mio->impl.file.fp);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		mio->impl.mem.pos = 0;
 		mio->impl.mem.ungetch = EOF;
 		mio->impl.mem.eof = false;
 		mio->impl.mem.error = false;
 	}
+	else
+		AssertNotReached ();
 }
 
 /**
@@ -967,7 +1247,7 @@ int mio_getpos (MIO *mio, MIOPos *pos)
 	pos->type = mio->type;
 	if (mio->type == MIO_TYPE_FILE)
 		rv = fgetpos (mio->impl.file.fp, &pos->impl.file);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		rv = -1;
 
@@ -984,6 +1264,9 @@ int mio_getpos (MIO *mio, MIOPos *pos)
 			rv = 0;
 		}
 	}
+	else
+		AssertNotReached();
+
 #ifdef MIO_DEBUG
 	if (rv != -1)
 	{
@@ -1028,7 +1311,7 @@ int mio_setpos (MIO *mio, MIOPos *pos)
 
 	if (mio->type == MIO_TYPE_FILE)
 		rv = fsetpos (mio->impl.file.fp, &pos->impl.file);
-	else
+	else if (mio->type == MIO_TYPE_MEMORY)
 	{
 		rv = -1;
 
@@ -1041,6 +1324,8 @@ int mio_setpos (MIO *mio, MIOPos *pos)
 			rv = 0;
 		}
 	}
+	else
+		AssertNotReached ();
 
 	return rv;
 }
@@ -1061,3 +1346,38 @@ int mio_flush (MIO *mio)
 		return fflush (mio->impl.file.fp);
 	return 0;
 }
+
+
+/**
+ * mio_attach_user_data:
+ * @mio: A #MIO object
+ * @user_data: a pointer to any data object
+ * @user_data_free_func: a call back function to destroy the data object passed as @user_data
+ *
+ * Attach any data object to a #MIO object. Attached data can be got with
+ * mio_get_user_data(). The attached data is destroyed when new data is attached to
+ * the #MIO object, or #the MIO object itself is destroyed. For destroying the data
+ * @user_data_free_func is used.
+ *
+ */
+
+void  mio_attach_user_data (MIO *mio, void *user_data, MIODestroyNotify user_data_free_func)
+{
+	if (mio->udata.d && mio->udata.f)
+		mio->udata.f (mio->udata.d);
+
+	mio->udata.d = user_data;
+	mio->udata.f = user_data_free_func;
+}
+
+/**
+ * mio_get_user_data:
+ * @mio: A #MIO object
+ *
+ * Returns: user data attached with mio_attach_user_data() to a #MIO object.
+ *
+ */
+void *mio_get_user_data (MIO *mio)
+{
+	return mio->udata.d;
+}


Modified: ctags/main/mio.h
40 lines changed, 12 insertions(+), 28 deletions(-)
===================================================================
@@ -21,7 +21,11 @@
 #ifndef MIO_H
 #define MIO_H
 
+#ifndef QUALIFIER
 #include "general.h"  /* must always come first */
+#else
+#include "gcc-attr.h"
+#endif
 
 #include <stdio.h>
 #include <stdarg.h>
@@ -96,7 +100,7 @@ typedef void (*MIODestroyNotify) (void *data);
  */
 struct _MIOPos {
 	/*< private >*/
-	unsigned int type;
+	MIOType type;
 #ifdef MIO_DEBUG
 	void *tag;
 #endif
@@ -106,33 +110,6 @@ struct _MIOPos {
 	} impl;
 };
 
-/**
- * MIO:
- *
- * An object representing a #MIO stream. No assumptions should be made about
- * what compose this object, and none of its fields should be accessed directly.
- */
-struct _MIO {
-	/*< private >*/
-	unsigned int type;
-	union {
-		struct {
-			FILE *fp;
-			MIOFCloseFunc close_func;
-		} file;
-		struct {
-			unsigned char *buf;
-			int ungetch;
-			size_t pos;
-			size_t size;
-			size_t allocated_size;
-			MIOReallocFunc realloc_func;
-			MIODestroyNotify free_func;
-			bool error;
-			bool eof;
-		} mem;
-	} impl;
-};
 
 
 MIO *mio_new_file (const char *filename, const char *mode);
@@ -145,6 +122,10 @@ MIO *mio_new_memory (unsigned char *data,
 					 size_t size,
 					 MIOReallocFunc realloc_func,
 					 MIODestroyNotify free_func);
+
+MIO *mio_new_mio    (MIO *base, long start, size_t size);
+MIO *mio_ref        (MIO *mio);
+
 int mio_free (MIO *mio);
 FILE *mio_file_get_fp (MIO *mio);
 unsigned char *mio_memory_get_data (MIO *mio, size_t *size);
@@ -175,4 +156,7 @@ int mio_getpos (MIO *mio, MIOPos *pos);
 int mio_setpos (MIO *mio, MIOPos *pos);
 int mio_flush (MIO *mio);
 
+void  mio_attach_user_data (MIO *mio, void *user_data, MIODestroyNotify user_data_free_func);
+void *mio_get_user_data (MIO *mio);
+
 #endif /* MIO_H */



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list