read: implement openBuffer() using openInputFile()

In addition, add automatic memory MIO opening to read.c for small files
and remove the same optimization from Geany. Simplify tm_ctags_parse()
as the memory/file branches are identical now.
This commit is contained in:
Jiří Techet 2016-10-11 12:26:51 +02:00
parent 2f4d43ac93
commit aafb127024
5 changed files with 61 additions and 84 deletions

View File

@ -574,7 +574,7 @@ static bool createTagsForFile (const char *const fileName,
{
bool retried = false;
if (openInputFile (fileName, language))
if (openInputFile (fileName, language, NULL))
{
makeFileTag (fileName);

View File

@ -401,10 +401,46 @@ static bool parseLineDirective (char *s)
* Input file I/O operations
*/
#define MAX_IN_MEMORY_FILE_SIZE (1024*1024)
extern MIO *getMio (const char *const fileName, const char *const openMode,
bool memStreamRequired)
{
FILE *src;
fileStatus *st;
unsigned long size;
unsigned char *data;
st = eStat (fileName);
size = st->size;
eStatFree (st);
if ((!memStreamRequired)
&& (size > MAX_IN_MEMORY_FILE_SIZE || size == 0))
return mio_new_file (fileName, openMode);
src = fopen (fileName, openMode);
if (!src)
return NULL;
data = eMalloc (size);
if (fread (data, 1, size, src) != size)
{
eFree (data);
fclose (src);
if (memStreamRequired)
return NULL;
else
return mio_new_file (fileName, openMode);
}
fclose (src);
return mio_new_memory (data, size, eRealloc, eFree);
}
/* This function opens an input file, and resets the line counter. If it
* fails, it will display an error message and leave the File.mio set to NULL.
*/
extern bool openInputFile (const char *const fileName, const langType language)
extern bool openInputFile (const char *const fileName, const langType language,
MIO *mio)
{
const char *const openMode = "rb";
bool opened = false;
@ -417,7 +453,8 @@ extern bool openInputFile (const char *const fileName, const langType language)
File.mio = NULL;
}
File.mio = mio_new_file (fileName, openMode);
File.mio = mio? mio_ref (mio): getMio (fileName, openMode, true);
if (File.mio == NULL)
error (WARNING | PERROR, "cannot open \"%s\"", fileName);
else
@ -447,43 +484,15 @@ extern bool openInputFile (const char *const fileName, const langType language)
* This func is NOT THREAD SAFE.
* The user should not tamper with the buffer while this func is executing.
*/
extern bool bufferOpen (unsigned char *buffer, size_t buffer_size,
const char *const fileName, const langType language )
extern bool bufferOpen (const char *const fileName, const langType language,
unsigned char *buffer, size_t buffer_size)
{
bool opened = false;
/* Check whether a file of a buffer were already open, then close them.
*/
if (File.mio != NULL) {
mio_free (File.mio); /* close any open source file */
File.mio = NULL;
}
/* check if we got a good buffer */
if (buffer == NULL || buffer_size == 0) {
opened = false;
return opened;
}
opened = true;
File.mio = mio_new_memory (buffer, buffer_size, NULL, NULL);
setInputFileName (fileName);
mio_getpos (File.mio, &StartOfLine);
mio_getpos (File.mio, &File.filePosition);
File.currentLine = NULL;
File.input.lineNumber = 0L;
if (File.line != NULL)
vStringClear (File.line);
setSourceFileParameters (vStringNewInit (fileName), language);
File.source.lineNumber = 0L;
verbose ("OPENING %s as %s language %sfile\n", fileName,
getLanguageName (language),
File.source.isHeader ? "include " : "");
MIO *mio;
bool opened;
mio = mio_new_memory (buffer, buffer_size, NULL, NULL);
opened = openInputFile (fileName, language, mio);
mio_free (mio);
return opened;
}

View File

@ -70,15 +70,21 @@ extern kindOption *getInputLanguageFileKind (void);
extern bool doesInputLanguageRequestAutomaticFQTag (void);
extern void freeInputFileResources (void);
extern bool openInputFile (const char *const fileName, const langType language);
/* Stream opend by getMio can be passed to openInputFile as the 3rd
argument. If the 3rd argument is NULL, openInputFile calls getMio
internally. The 3rd argument is introduced for reusing mio object
created in parser guessing stage. */
extern bool openInputFile (const char *const fileName, const langType language, MIO *mio);
extern bool bufferOpen (const char *const fileName, const langType language,
unsigned char *buffer, size_t buffer_size);
extern MIO *getMio (const char *const fileName, const char *const openMode,
bool memStreamRequired);
extern void closeInputFile (void);
extern int getcFromInputFile (void);
extern int getNthPrevCFromInputFile (unsigned int nth, int def);
extern int skipToCharacterInInputFile (int c);
extern void ungetcToInputFile (int c);
extern const unsigned char *readLineFromInputFile (void);
extern bool bufferOpen (unsigned char *buffer, size_t buffer_size,
const char *const fileName, const langType language );
extern const char *getSourceFileTagPath (void);
extern const char *getSourceLanguageName (void);

View File

@ -69,27 +69,13 @@ void tm_ctags_parse(guchar *buffer, gsize buffer_size,
while (retry && passCount < 3)
{
pass_callback(user_data);
if (!buffer && openInputFile (file_name, lang))
if ((!buffer && openInputFile (file_name, lang, NULL)) ||
(buffer && bufferOpen (file_name, lang, buffer, buffer_size)))
{
if (LanguageTable [lang]->parser != NULL)
{
LanguageTable [lang]->parser ();
closeInputFile ();
retry = FALSE;
break;
}
else if (LanguageTable [lang]->parser2 != NULL)
retry = LanguageTable [lang]->parser2 (passCount);
closeInputFile ();
}
else if (buffer && bufferOpen (buffer, buffer_size, file_name, lang))
{
if (LanguageTable [lang]->parser != NULL)
{
LanguageTable [lang]->parser ();
closeInputFile ();
retry = FALSE;
break;
}
else if (LanguageTable [lang]->parser2 != NULL)
retry = LanguageTable [lang]->parser2 (passCount);
@ -98,7 +84,7 @@ void tm_ctags_parse(guchar *buffer, gsize buffer_size,
else
{
g_warning("Unable to open %s", file_name);
return;
break;
}
++ passCount;
}

View File

@ -790,8 +790,6 @@ gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize
{
const char *file_name;
gboolean retry = TRUE;
gboolean parse_file = FALSE;
gboolean free_buf = FALSE;
if ((NULL == source_file) || (NULL == source_file->file_name))
{
@ -807,40 +805,18 @@ gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize
file_name = source_file->file_name;
if (!use_buffer)
{
GStatBuf s;
/* load file to memory and parse it from memory unless the file is too big */
if (g_stat(file_name, &s) != 0 || s.st_size > 10*1024*1024)
parse_file = TRUE;
else
{
if (!g_file_get_contents(file_name, (gchar**)&text_buf, (gsize*)&buf_size, NULL))
{
g_warning("Unable to open %s", file_name);
return FALSE;
}
free_buf = TRUE;
}
}
if (!parse_file && (NULL == text_buf || 0 == buf_size))
if (use_buffer && (NULL == text_buf || 0 == buf_size))
{
/* Empty buffer, "parse" by setting empty tag array */
tm_tags_array_free(source_file->tags_array, FALSE);
if (free_buf)
g_free(text_buf);
return TRUE;
}
tm_tags_array_free(source_file->tags_array, FALSE);
tm_ctags_parse(parse_file ? NULL : text_buf, buf_size, file_name,
tm_ctags_parse(use_buffer ? text_buf : NULL, buf_size, file_name,
source_file->lang, ctags_new_tag, ctags_pass_start, source_file);
if (free_buf)
g_free(text_buf);
return !retry;
}